vendor: 200,193 bytes, lines 1-7198
1/*! jQuery UI - v1.14.1 - 2024-10-30 2* https://jqueryui.com 3* Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-patch.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js 4* Copyright OpenJS Foundation and other contributors; Licensed MIT */ 5 6(function (factory) { 7 "use strict"; 8 9 if (typeof define === "function" && define.amd) { 10 11 // AMD. Register as an anonymous module. 12 define(["jquery"], factory); 13 } else { 14 15 // Browser globals 16 factory(jQuery); 17 } 18})(function ($) { 19 "use strict"; 20 21 $.ui = $.ui || {}; 22 23 var version = $.ui.version = "1.14.1"; 24 25 26 /*! 27 * jQuery UI Widget 1.14.1 28 * https://jqueryui.com 29 * 30 * Copyright OpenJS Foundation and other contributors 31 * Released under the MIT license. 32 * https://jquery.org/license 33 */ 34 35 //>>label: Widget 36 //>>group: Core 37 //>>description: Provides a factory for creating stateful widgets with a common API. 38 //>>docs: https://api.jqueryui.com/jQuery.widget/ 39 //>>demos: https://jqueryui.com/widget/ 40 41 42 var widgetUuid = 0; 43 var widgetHasOwnProperty = Array.prototype.hasOwnProperty; 44 var widgetSlice = Array.prototype.slice; 45 46 $.cleanData = (function (orig) { 47 return function (elems) { 48 var events, elem, i; 49 for (i = 0; (elem = elems[i]) != null; i++) { 50 51 // Only trigger remove when necessary to save time 52 events = $._data(elem, "events"); 53 if (events && events.remove) { 54 $(elem).triggerHandler("remove"); 55 } 56 } 57 orig(elems); 58 }; 59 })($.cleanData); 60 61 $.widget = function (name, base, prototype) { 62 var existingConstructor, constructor, basePrototype; 63 64 // ProxiedPrototype allows the provided prototype to remain unmodified 65 // so that it can be used as a mixin for multiple widgets (#8876) 66 var proxiedPrototype = {}; 67 68 var namespace = name.split(".")[0]; 69 name = name.split(".")[1]; 70 if (name === "__proto__" || name === "constructor") { 71 return $.error("Invalid widget name: " + name); 72 } 73 var fullName = namespace + "-" + name; 74 75 if (!prototype) { 76 prototype = base; 77 base = $.Widget; 78 } 79 80 if (Array.isArray(prototype)) { 81 prototype = $.extend.apply(null, [{}].concat(prototype)); 82 } 83 84 // Create selector for plugin 85 $.expr.pseudos[fullName.toLowerCase()] = function (elem) { 86 return !!$.data(elem, fullName); 87 }; 88 89 $[namespace] = $[namespace] || {}; 90 existingConstructor = $[namespace][name]; 91 constructor = $[namespace][name] = function (options, element) { 92 93 // Allow instantiation without "new" keyword 94 if (!this || !this._createWidget) { 95 return new constructor(options, element); 96 } 97 98 // Allow instantiation without initializing for simple inheritance 99 // must use "new" keyword (the code above always passes args) 100 if (arguments.length) { 101 this._createWidget(options, element); 102 } 103 }; 104 105 // Extend with the existing constructor to carry over any static properties 106 $.extend(constructor, existingConstructor, { 107 version: prototype.version, 108 109 // Copy the object used to create the prototype in case we need to 110 // redefine the widget later 111 _proto: $.extend({}, prototype), 112 113 // Track widgets that inherit from this widget in case this widget is 114 // redefined after a widget inherits from it 115 _childConstructors: [] 116 }); 117 118 basePrototype = new base(); 119 120 // We need to make the options hash a property directly on the new instance 121 // otherwise we'll modify the options hash on the prototype that we're 122 // inheriting from 123 basePrototype.options = $.widget.extend({}, basePrototype.options); 124 $.each(prototype, function (prop, value) { 125 if (typeof value !== "function") { 126 proxiedPrototype[prop] = value; 127 return; 128 } 129 proxiedPrototype[prop] = (function () { 130 function _super() { 131 return base.prototype[prop].apply(this, arguments); 132 } 133 134 function _superApply(args) { 135 return base.prototype[prop].apply(this, args); 136 } 137 138 return function () { 139 var __super = this._super; 140 var __superApply = this._superApply; 141 var returnValue; 142 143 this._super = _super; 144 this._superApply = _superApply; 145 146 returnValue = value.apply(this, arguments); 147 148 this._super = __super; 149 this._superApply = __superApply; 150 151 return returnValue; 152 }; 153 })(); 154 }); 155 constructor.prototype = $.widget.extend(basePrototype, { 156 157 // TODO: remove support for widgetEventPrefix 158 // always use the name + a colon as the prefix, e.g., draggable:start 159 // don't prefix for widgets that aren't DOM-based 160 widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name 161 }, proxiedPrototype, { 162 constructor: constructor, 163 namespace: namespace, 164 widgetName: name, 165 widgetFullName: fullName 166 }); 167 168 // If this widget is being redefined then we need to find all widgets that 169 // are inheriting from it and redefine all of them so that they inherit from 170 // the new version of this widget. We're essentially trying to replace one 171 // level in the prototype chain. 172 if (existingConstructor) { 173 $.each(existingConstructor._childConstructors, function (i, child) { 174 var childPrototype = child.prototype; 175 176 // Redefine the child widget using the same prototype that was 177 // originally used, but inherit from the new version of the base 178 $.widget(childPrototype.namespace + "." + childPrototype.widgetName, constructor, 179 child._proto); 180 }); 181 182 // Remove the list of existing child constructors from the old constructor 183 // so the old child constructors can be garbage collected 184 delete existingConstructor._childConstructors; 185 } else { 186 base._childConstructors.push(constructor); 187 } 188 189 $.widget.bridge(name, constructor); 190 191 return constructor; 192 }; 193 194 $.widget.extend = function (target) { 195 var input = widgetSlice.call(arguments, 1); 196 var inputIndex = 0; 197 var inputLength = input.length; 198 var key; 199 var value; 200 201 for (; inputIndex < inputLength; inputIndex++) { 202 for (key in input[inputIndex]) { 203 value = input[inputIndex][key]; 204 if (widgetHasOwnProperty.call(input[inputIndex], key) && value !== undefined) { 205 206 // Clone objects 207 if ($.isPlainObject(value)) { 208 target[key] = $.isPlainObject(target[key]) ? 209 $.widget.extend({}, target[key], value) : 210 211 // Don't extend strings, arrays, etc. with objects 212 $.widget.extend({}, value); 213 214 // Copy everything else by reference 215 } else { 216 target[key] = value; 217 } 218 } 219 } 220 } 221 return target; 222 }; 223 224 $.widget.bridge = function (name, object) { 225 var fullName = object.prototype.widgetFullName || name; 226 $.fn[name] = function (options) { 227 var isMethodCall = typeof options === "string"; 228 var args = widgetSlice.call(arguments, 1); 229 var returnValue = this; 230 231 if (isMethodCall) { 232 233 // If this is an empty collection, we need to have the instance method 234 // return undefined instead of the jQuery instance 235 if (!this.length && options === "instance") { 236 returnValue = undefined; 237 } else { 238 this.each(function () { 239 var methodValue; 240 var instance = $.data(this, fullName); 241 242 if (options === "instance") { 243 returnValue = instance; 244 return false; 245 } 246 247 if (!instance) { 248 return $.error("cannot call methods on " + name + 249 " prior to initialization; " + 250 "attempted to call method '" + options + "'"); 251 } 252 253 if (typeof instance[options] !== "function" || 254 options.charAt(0) === "_") { 255 return $.error("no such method '" + options + "' for " + name + 256 " widget instance"); 257 } 258 259 methodValue = instance[options].apply(instance, args); 260 261 if (methodValue !== instance && methodValue !== undefined) { 262 returnValue = methodValue && methodValue.jquery ? 263 returnValue.pushStack(methodValue.get()) : 264 methodValue; 265 return false; 266 } 267 }); 268 } 269 } else { 270 271 // Allow multiple hashes to be passed on init 272 if (args.length) { 273 options = $.widget.extend.apply(null, [options].concat(args)); 274 } 275 276 this.each(function () { 277 var instance = $.data(this, fullName); 278 if (instance) { 279 instance.option(options || {}); 280 if (instance._init) { 281 instance._init(); 282 } 283 } else { 284 $.data(this, fullName, new object(options, this)); 285 } 286 }); 287 } 288 289 return returnValue; 290 }; 291 }; 292 293 $.Widget = function ( /* options, element */) { }; 294 $.Widget._childConstructors = []; 295 296 $.Widget.prototype = { 297 widgetName: "widget", 298 widgetEventPrefix: "", 299 defaultElement: "<div>", 300 301 options: { 302 classes: {}, 303 disabled: false, 304 305 // Callbacks 306 create: null 307 }, 308 309 _createWidget: function (options, element) { 310 element = $(element || this.defaultElement || this)[0]; 311 this.element = $(element); 312 this.uuid = widgetUuid++; 313 this.eventNamespace = "." + this.widgetName + this.uuid; 314 315 this.bindings = $(); 316 this.hoverable = $(); 317 this.focusable = $(); 318 this.classesElementLookup = {}; 319 320 if (element !== this) { 321 $.data(element, this.widgetFullName, this); 322 this._on(true, this.element, { 323 remove: function (event) { 324 if (event.target === element) { 325 this.destroy(); 326 } 327 } 328 }); 329 this.document = $(element.style ? 330 331 // Element within the document 332 element.ownerDocument : 333 334 // Element is window or document 335 element.document || element); 336 this.window = $(this.document[0].defaultView || this.document[0].parentWindow); 337 } 338 339 this.options = $.widget.extend({}, 340 this.options, 341 this._getCreateOptions(), 342 options); 343 344 this._create(); 345 346 if (this.options.disabled) { 347 this._setOptionDisabled(this.options.disabled); 348 } 349 350 this._trigger("create", null, this._getCreateEventData()); 351 this._init(); 352 }, 353 354 _getCreateOptions: function () { 355 return {}; 356 }, 357 358 _getCreateEventData: $.noop, 359 360 _create: $.noop, 361 362 _init: $.noop, 363 364 destroy: function () { 365 var that = this; 366 367 this._destroy(); 368 $.each(this.classesElementLookup, function (key, value) { 369 that._removeClass(value, key); 370 }); 371 372 // We can probably remove the unbind calls in 2.0 373 // all event bindings should go through this._on() 374 this.element 375 .off(this.eventNamespace) 376 .removeData(this.widgetFullName); 377 this.widget() 378 .off(this.eventNamespace) 379 .removeAttr("aria-disabled"); 380 381 // Clean up events and states 382 this.bindings.off(this.eventNamespace); 383 }, 384 385 _destroy: $.noop, 386 387 widget: function () { 388 return this.element; 389 }, 390 391 option: function (key, value) { 392 var options = key; 393 var parts; 394 var curOption; 395 var i; 396 397 if (arguments.length === 0) { 398 399 // Don't return a reference to the internal hash 400 return $.widget.extend({}, this.options); 401 } 402 403 if (typeof key === "string") { 404 405 // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } 406 options = {}; 407 parts = key.split("."); 408 key = parts.shift(); 409 if (parts.length) { 410 curOption = options[key] = $.widget.extend({}, this.options[key]); 411 for (i = 0; i < parts.length - 1; i++) { 412 curOption[parts[i]] = curOption[parts[i]] || {}; 413 curOption = curOption[parts[i]]; 414 } 415 key = parts.pop(); 416 if (arguments.length === 1) { 417 return curOption[key] === undefined ? null : curOption[key]; 418 } 419 curOption[key] = value; 420 } else { 421 if (arguments.length === 1) { 422 return this.options[key] === undefined ? null : this.options[key]; 423 } 424 options[key] = value; 425 } 426 } 427 428 this._setOptions(options); 429 430 return this; 431 }, 432 433 _setOptions: function (options) { 434 var key; 435 436 for (key in options) { 437 this._setOption(key, options[key]); 438 } 439 440 return this; 441 }, 442 443 _setOption: function (key, value) { 444 if (key === "classes") { 445 this._setOptionClasses(value); 446 } 447 448 this.options[key] = value; 449 450 if (key === "disabled") { 451 this._setOptionDisabled(value); 452 } 453 454 return this; 455 }, 456 457 _setOptionClasses: function (value) { 458 var classKey, elements, currentElements; 459 460 for (classKey in value) { 461 currentElements = this.classesElementLookup[classKey]; 462 if (value[classKey] === this.options.classes[classKey] || 463 !currentElements || 464 !currentElements.length) { 465 continue; 466 } 467 468 // We are doing this to create a new jQuery object because the _removeClass() call 469 // on the next line is going to destroy the reference to the current elements being 470 // tracked. We need to save a copy of this collection so that we can add the new classes 471 // below. 472 elements = $(currentElements.get()); 473 this._removeClass(currentElements, classKey); 474 475 // We don't use _addClass() here, because that uses this.options.classes 476 // for generating the string of classes. We want to use the value passed in from 477 // _setOption(), this is the new value of the classes option which was passed to 478 // _setOption(). We pass this value directly to _classes(). 479 elements.addClass(this._classes({ 480 element: elements, 481 keys: classKey, 482 classes: value, 483 add: true 484 })); 485 } 486 }, 487 488 _setOptionDisabled: function (value) { 489 this._toggleClass(this.widget(), this.widgetFullName + "-disabled", null, !!value); 490 491 // If the widget is becoming disabled, then nothing is interactive 492 if (value) { 493 this._removeClass(this.hoverable, null, "ui-state-hover"); 494 this._removeClass(this.focusable, null, "ui-state-focus"); 495 } 496 }, 497 498 enable: function () { 499 return this._setOptions({ disabled: false }); 500 }, 501 502 disable: function () { 503 return this._setOptions({ disabled: true }); 504 }, 505 506 _classes: function (options) { 507 var full = []; 508 var that = this; 509 510 options = $.extend({ 511 element: this.element, 512 classes: this.options.classes || {} 513 }, options); 514 515 function bindRemoveEvent() { 516 var nodesToBind = []; 517 518 options.element.each(function (_, element) { 519 var isTracked = $.map(that.classesElementLookup, function (elements) { 520 return elements; 521 }) 522 .some(function (elements) { 523 return elements.is(element); 524 }); 525 526 if (!isTracked) { 527 nodesToBind.push(element); 528 } 529 }); 530 531 that._on($(nodesToBind), { 532 remove: "_untrackClassesElement" 533 }); 534 } 535 536 function processClassString(classes, checkOption) { 537 var current, i; 538 for (i = 0; i < classes.length; i++) { 539 current = that.classesElementLookup[classes[i]] || $(); 540 if (options.add) { 541 bindRemoveEvent(); 542 current = $($.uniqueSort(current.get().concat(options.element.get()))); 543 } else { 544 current = $(current.not(options.element).get()); 545 } 546 that.classesElementLookup[classes[i]] = current; 547 full.push(classes[i]); 548 if (checkOption && options.classes[classes[i]]) { 549 full.push(options.classes[classes[i]]); 550 } 551 } 552 } 553 554 if (options.keys) { 555 processClassString(options.keys.match(/\S+/g) || [], true); 556 } 557 if (options.extra) { 558 processClassString(options.extra.match(/\S+/g) || []); 559 } 560 561 return full.join(" "); 562 }, 563 564 _untrackClassesElement: function (event) { 565 var that = this; 566 $.each(that.classesElementLookup, function (key, value) { 567 if ($.inArray(event.target, value) !== -1) { 568 that.classesElementLookup[key] = $(value.not(event.target).get()); 569 } 570 }); 571 572 this._off($(event.target)); 573 }, 574 575 _removeClass: function (element, keys, extra) { 576 return this._toggleClass(element, keys, extra, false); 577 }, 578 579 _addClass: function (element, keys, extra) { 580 return this._toggleClass(element, keys, extra, true); 581 }, 582 583 _toggleClass: function (element, keys, extra, add) { 584 add = (typeof add === "boolean") ? add : extra; 585 var shift = (typeof element === "string" || element === null), 586 options = { 587 extra: shift ? keys : extra, 588 keys: shift ? element : keys, 589 element: shift ? this.element : element, 590 add: add 591 }; 592 options.element.toggleClass(this._classes(options), add); 593 return this; 594 }, 595 596 _on: function (suppressDisabledCheck, element, handlers) { 597 var delegateElement; 598 var instance = this; 599 600 // No suppressDisabledCheck flag, shuffle arguments 601 if (typeof suppressDisabledCheck !== "boolean") { 602 handlers = element; 603 element = suppressDisabledCheck; 604 suppressDisabledCheck = false; 605 } 606 607 // No element argument, shuffle and use this.element 608 if (!handlers) { 609 handlers = element; 610 element = this.element; 611 delegateElement = this.widget(); 612 } else { 613 element = delegateElement = $(element); 614 this.bindings = this.bindings.add(element); 615 } 616 617 $.each(handlers, function (event, handler) { 618 function handlerProxy() { 619 620 // Allow widgets to customize the disabled handling 621 // - disabled as an array instead of boolean 622 // - disabled class as method for disabling individual parts 623 if (!suppressDisabledCheck && 624 (instance.options.disabled === true || 625 $(this).hasClass("ui-state-disabled"))) { 626 return; 627 } 628 return (typeof handler === "string" ? instance[handler] : handler) 629 .apply(instance, arguments); 630 } 631 632 // Copy the guid so direct unbinding works 633 if (typeof handler !== "string") { 634 handlerProxy.guid = handler.guid = 635 handler.guid || handlerProxy.guid || $.guid++; 636 } 637 638 var match = event.match(/^([\w:-]*)\s*(.*)$/); 639 var eventName = match[1] + instance.eventNamespace; 640 var selector = match[2]; 641 642 if (selector) { 643 delegateElement.on(eventName, selector, handlerProxy); 644 } else { 645 element.on(eventName, handlerProxy); 646 } 647 }); 648 }, 649 650 _off: function (element, eventName) { 651 eventName = (eventName || "").split(" ").join(this.eventNamespace + " ") + 652 this.eventNamespace; 653 element.off(eventName); 654 655 // Clear the stack to avoid memory leaks (#10056) 656 this.bindings = $(this.bindings.not(element).get()); 657 this.focusable = $(this.focusable.not(element).get()); 658 this.hoverable = $(this.hoverable.not(element).get()); 659 }, 660 661 _delay: function (handler, delay) { 662 function handlerProxy() { 663 return (typeof handler === "string" ? instance[handler] : handler) 664 .apply(instance, arguments); 665 } 666 var instance = this; 667 return setTimeout(handlerProxy, delay || 0); 668 }, 669 670 _hoverable: function (element) { 671 this.hoverable = this.hoverable.add(element); 672 this._on(element, { 673 mouseenter: function (event) { 674 this._addClass($(event.currentTarget), null, "ui-state-hover"); 675 }, 676 mouseleave: function (event) { 677 this._removeClass($(event.currentTarget), null, "ui-state-hover"); 678 } 679 }); 680 }, 681 682 _focusable: function (element) { 683 this.focusable = this.focusable.add(element); 684 this._on(element, { 685 focusin: function (event) { 686 this._addClass($(event.currentTarget), null, "ui-state-focus"); 687 }, 688 focusout: function (event) { 689 this._removeClass($(event.currentTarget), null, "ui-state-focus"); 690 } 691 }); 692 }, 693 694 _trigger: function (type, event, data) { 695 var prop, orig; 696 var callback = this.options[type]; 697 698 data = data || {}; 699 event = $.Event(event); 700 event.type = (type === this.widgetEventPrefix ? 701 type : 702 this.widgetEventPrefix + type).toLowerCase(); 703 704 // The original event may come from any element 705 // so we need to reset the target on the new event 706 event.target = this.element[0]; 707 708 // Copy original event properties over to the new event 709 orig = event.originalEvent; 710 if (orig) { 711 for (prop in orig) { 712 if (!(prop in event)) { 713 event[prop] = orig[prop]; 714 } 715 } 716 } 717 718 this.element.trigger(event, data); 719 return !(typeof callback === "function" && 720 callback.apply(this.element[0], [event].concat(data)) === false || 721 event.isDefaultPrevented()); 722 } 723 }; 724 725 $.each({ show: "fadeIn", hide: "fadeOut" }, function (method, defaultEffect) { 726 $.Widget.prototype["_" + method] = function (element, options, callback) { 727 if (typeof options === "string") { 728 options = { effect: options }; 729 } 730 731 var hasOptions; 732 var effectName = !options ? 733 method : 734 options === true || typeof options === "number" ? 735 defaultEffect : 736 options.effect || defaultEffect; 737 738 options = options || {}; 739 if (typeof options === "number") { 740 options = { duration: options }; 741 } else if (options === true) { 742 options = {}; 743 } 744 745 hasOptions = !$.isEmptyObject(options); 746 options.complete = callback; 747 748 if (options.delay) { 749 element.delay(options.delay); 750 } 751 752 if (hasOptions && $.effects && $.effects.effect[effectName]) { 753 element[method](options); 754 } else if (effectName !== method && element[effectName]) { 755 element[effectName](options.duration, options.easing, callback); 756 } else { 757 element.queue(function (next) { 758 $(this)[method](); 759 if (callback) { 760 callback.call(element[0]); 761 } 762 next(); 763 }); 764 } 765 }; 766 }); 767 768 var widget = $.widget; 769 770 771 /*! 772 * jQuery UI Position 1.14.1 773 * https://jqueryui.com 774 * 775 * Copyright OpenJS Foundation and other contributors 776 * Released under the MIT license. 777 * https://jquery.org/license 778 * 779 * https://api.jqueryui.com/position/ 780 */ 781 782 //>>label: Position 783 //>>group: Core 784 //>>description: Positions elements relative to other elements. 785 //>>docs: https://api.jqueryui.com/position/ 786 //>>demos: https://jqueryui.com/position/ 787 788 789 (function () { 790 var cachedScrollbarWidth, 791 max = Math.max, 792 abs = Math.abs, 793 rhorizontal = /left|center|right/, 794 rvertical = /top|center|bottom/, 795 roffset = /[\+\-]\d+(\.[\d]+)?%?/, 796 rposition = /^\w+/, 797 rpercent = /%$/, 798 _position = $.fn.position; 799 800 function getOffsets(offsets, width, height) { 801 return [ 802 parseFloat(offsets[0]) * (rpercent.test(offsets[0]) ? width / 100 : 1), 803 parseFloat(offsets[1]) * (rpercent.test(offsets[1]) ? height / 100 : 1) 804 ]; 805 } 806 807 function parseCss(element, property) { 808 return parseInt($.css(element, property), 10) || 0; 809 } 810 811 function isWindow(obj) { 812 return obj != null && obj === obj.window; 813 } 814 815 function getDimensions(elem) { 816 var raw = elem[0]; 817 if (raw.nodeType === 9) { 818 return { 819 width: elem.width(), 820 height: elem.height(), 821 offset: { top: 0, left: 0 } 822 }; 823 } 824 if (isWindow(raw)) { 825 return { 826 width: elem.width(), 827 height: elem.height(), 828 offset: { top: elem.scrollTop(), left: elem.scrollLeft() } 829 }; 830 } 831 if (raw.preventDefault) { 832 return { 833 width: 0, 834 height: 0, 835 offset: { top: raw.pageY, left: raw.pageX } 836 }; 837 } 838 return { 839 width: elem.outerWidth(), 840 height: elem.outerHeight(), 841 offset: elem.offset() 842 }; 843 } 844 845 $.position = { 846 scrollbarWidth: function () { 847 if (cachedScrollbarWidth !== undefined) { 848 return cachedScrollbarWidth; 849 } 850 var w1, w2, 851 div = $("<div style=" + 852 "'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" + 853 "<div style='height:300px;width:auto;'></div></div>"), 854 innerDiv = div.children()[0]; 855 856 $("body").append(div); 857 w1 = innerDiv.offsetWidth; 858 div.css("overflow", "scroll"); 859 860 w2 = innerDiv.offsetWidth; 861 862 if (w1 === w2) { 863 w2 = div[0].clientWidth; 864 } 865 866 div.remove(); 867 868 return (cachedScrollbarWidth = w1 - w2); 869 }, 870 getScrollInfo: function (within) { 871 var overflowX = within.isWindow || within.isDocument ? "" : 872 within.element.css("overflow-x"), 873 overflowY = within.isWindow || within.isDocument ? "" : 874 within.element.css("overflow-y"), 875 hasOverflowX = overflowX === "scroll" || 876 (overflowX === "auto" && within.width < within.element[0].scrollWidth), 877 hasOverflowY = overflowY === "scroll" || 878 (overflowY === "auto" && within.height < within.element[0].scrollHeight); 879 return { 880 width: hasOverflowY ? $.position.scrollbarWidth() : 0, 881 height: hasOverflowX ? $.position.scrollbarWidth() : 0 882 }; 883 }, 884 getWithinInfo: function (element) { 885 var withinElement = $(element || window), 886 isElemWindow = isWindow(withinElement[0]), 887 isDocument = !!withinElement[0] && withinElement[0].nodeType === 9, 888 hasOffset = !isElemWindow && !isDocument; 889 return { 890 element: withinElement, 891 isWindow: isElemWindow, 892 isDocument: isDocument, 893 offset: hasOffset ? $(element).offset() : { left: 0, top: 0 }, 894 scrollLeft: withinElement.scrollLeft(), 895 scrollTop: withinElement.scrollTop(), 896 width: withinElement.outerWidth(), 897 height: withinElement.outerHeight() 898 }; 899 } 900 }; 901 902 $.fn.position = function (options) { 903 if (!options || !options.of) { 904 return _position.apply(this, arguments); 905 } 906 907 // Make a copy, we don't want to modify arguments 908 options = $.extend({}, options); 909 910 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, 911 912 // Make sure string options are treated as CSS selectors 913 target = typeof options.of === "string" ? 914 $(document).find(options.of) : 915 $(options.of), 916 917 within = $.position.getWithinInfo(options.within), 918 scrollInfo = $.position.getScrollInfo(within), 919 collision = (options.collision || "flip").split(" "), 920 offsets = {}; 921 922 dimensions = getDimensions(target); 923 if (target[0].preventDefault) { 924 925 // Force left top to allow flipping 926 options.at = "left top"; 927 } 928 targetWidth = dimensions.width; 929 targetHeight = dimensions.height; 930 targetOffset = dimensions.offset; 931 932 // Clone to reuse original targetOffset later 933 basePosition = $.extend({}, targetOffset); 934 935 // Force my and at to have valid horizontal and vertical positions 936 // if a value is missing or invalid, it will be converted to center 937 $.each(["my", "at"], function () { 938 var pos = (options[this] || "").split(" "), 939 horizontalOffset, 940 verticalOffset; 941 942 if (pos.length === 1) { 943 pos = rhorizontal.test(pos[0]) ? 944 pos.concat(["center"]) : 945 rvertical.test(pos[0]) ? 946 ["center"].concat(pos) : 947 ["center", "center"]; 948 } 949 pos[0] = rhorizontal.test(pos[0]) ? pos[0] : "center"; 950 pos[1] = rvertical.test(pos[1]) ? pos[1] : "center"; 951 952 // Calculate offsets 953 horizontalOffset = roffset.exec(pos[0]); 954 verticalOffset = roffset.exec(pos[1]); 955 offsets[this] = [ 956 horizontalOffset ? horizontalOffset[0] : 0, 957 verticalOffset ? verticalOffset[0] : 0 958 ]; 959 960 // Reduce to just the positions without the offsets 961 options[this] = [ 962 rposition.exec(pos[0])[0], 963 rposition.exec(pos[1])[0] 964 ]; 965 }); 966 967 // Normalize collision option 968 if (collision.length === 1) { 969 collision[1] = collision[0]; 970 } 971 972 if (options.at[0] === "right") { 973 basePosition.left += targetWidth; 974 } else if (options.at[0] === "center") { 975 basePosition.left += targetWidth / 2; 976 } 977 978 if (options.at[1] === "bottom") { 979 basePosition.top += targetHeight; 980 } else if (options.at[1] === "center") { 981 basePosition.top += targetHeight / 2; 982 } 983 984 atOffset = getOffsets(offsets.at, targetWidth, targetHeight); 985 basePosition.left += atOffset[0]; 986 basePosition.top += atOffset[1]; 987 988 return this.each(function () { 989 var collisionPosition, using, 990 elem = $(this), 991 elemWidth = elem.outerWidth(), 992 elemHeight = elem.outerHeight(), 993 marginLeft = parseCss(this, "marginLeft"), 994 marginTop = parseCss(this, "marginTop"), 995 collisionWidth = elemWidth + marginLeft + parseCss(this, "marginRight") + 996 scrollInfo.width, 997 collisionHeight = elemHeight + marginTop + parseCss(this, "marginBottom") + 998 scrollInfo.height, 999 position = $.extend({}, basePosition), 1000 myOffset = getOffsets(offsets.my, elem.outerWidth(), elem.outerHeight()); 1001 1002 if (options.my[0] === "right") { 1003 position.left -= elemWidth; 1004 } else if (options.my[0] === "center") { 1005 position.left -= elemWidth / 2; 1006 } 1007 1008 if (options.my[1] === "bottom") { 1009 position.top -= elemHeight; 1010 } else if (options.my[1] === "center") { 1011 position.top -= elemHeight / 2; 1012 } 1013 1014 position.left += myOffset[0]; 1015 position.top += myOffset[1]; 1016 1017 collisionPosition = { 1018 marginLeft: marginLeft, 1019 marginTop: marginTop 1020 }; 1021 1022 $.each(["left", "top"], function (i, dir) { 1023 if ($.ui.position[collision[i]]) { 1024 $.ui.position[collision[i]][dir](position, { 1025 targetWidth: targetWidth, 1026 targetHeight: targetHeight, 1027 elemWidth: elemWidth, 1028 elemHeight: elemHeight, 1029 collisionPosition: collisionPosition, 1030 collisionWidth: collisionWidth, 1031 collisionHeight: collisionHeight, 1032 offset: [atOffset[0] + myOffset[0], atOffset[1] + myOffset[1]], 1033 my: options.my, 1034 at: options.at, 1035 within: within, 1036 elem: elem 1037 }); 1038 } 1039 }); 1040 1041 if (options.using) { 1042 1043 // Adds feedback as second argument to using callback, if present 1044 using = function (props) { 1045 var left = targetOffset.left - position.left, 1046 right = left + targetWidth - elemWidth, 1047 top = targetOffset.top - position.top, 1048 bottom = top + targetHeight - elemHeight, 1049 feedback = { 1050 target: { 1051 element: target, 1052 left: targetOffset.left, 1053 top: targetOffset.top, 1054 width: targetWidth, 1055 height: targetHeight 1056 }, 1057 element: { 1058 element: elem, 1059 left: position.left, 1060 top: position.top, 1061 width: elemWidth, 1062 height: elemHeight 1063 }, 1064 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", 1065 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" 1066 }; 1067 if (targetWidth < elemWidth && abs(left + right) < targetWidth) { 1068 feedback.horizontal = "center"; 1069 } 1070 if (targetHeight < elemHeight && abs(top + bottom) < targetHeight) { 1071 feedback.vertical = "middle"; 1072 } 1073 if (max(abs(left), abs(right)) > max(abs(top), abs(bottom))) { 1074 feedback.important = "horizontal"; 1075 } else { 1076 feedback.important = "vertical"; 1077 } 1078 options.using.call(this, props, feedback); 1079 }; 1080 } 1081 1082 elem.offset($.extend(position, { using: using })); 1083 }); 1084 }; 1085 1086 $.ui.position = { 1087 fit: { 1088 left: function (position, data) { 1089 var within = data.within, 1090 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, 1091 outerWidth = within.width, 1092 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 1093 overLeft = withinOffset - collisionPosLeft, 1094 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, 1095 newOverRight; 1096 1097 // Element is wider than within 1098 if (data.collisionWidth > outerWidth) { 1099 1100 // Element is initially over the left side of within 1101 if (overLeft > 0 && overRight <= 0) { 1102 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - 1103 withinOffset; 1104 position.left += overLeft - newOverRight; 1105 1106 // Element is initially over right side of within 1107 } else if (overRight > 0 && overLeft <= 0) { 1108 position.left = withinOffset; 1109 1110 // Element is initially over both left and right sides of within 1111 } else { 1112 if (overLeft > overRight) { 1113 position.left = withinOffset + outerWidth - data.collisionWidth; 1114 } else { 1115 position.left = withinOffset; 1116 } 1117 } 1118 1119 // Too far left -> align with left edge 1120 } else if (overLeft > 0) { 1121 position.left += overLeft; 1122 1123 // Too far right -> align with right edge 1124 } else if (overRight > 0) { 1125 position.left -= overRight; 1126 1127 // Adjust based on position and margin 1128 } else { 1129 position.left = max(position.left - collisionPosLeft, position.left); 1130 } 1131 }, 1132 top: function (position, data) { 1133 var within = data.within, 1134 withinOffset = within.isWindow ? within.scrollTop : within.offset.top, 1135 outerHeight = data.within.height, 1136 collisionPosTop = position.top - data.collisionPosition.marginTop, 1137 overTop = withinOffset - collisionPosTop, 1138 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, 1139 newOverBottom; 1140 1141 // Element is taller than within 1142 if (data.collisionHeight > outerHeight) { 1143 1144 // Element is initially over the top of within 1145 if (overTop > 0 && overBottom <= 0) { 1146 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - 1147 withinOffset; 1148 position.top += overTop - newOverBottom; 1149 1150 // Element is initially over bottom of within 1151 } else if (overBottom > 0 && overTop <= 0) { 1152 position.top = withinOffset; 1153 1154 // Element is initially over both top and bottom of within 1155 } else { 1156 if (overTop > overBottom) { 1157 position.top = withinOffset + outerHeight - data.collisionHeight; 1158 } else { 1159 position.top = withinOffset; 1160 } 1161 } 1162 1163 // Too far up -> align with top 1164 } else if (overTop > 0) { 1165 position.top += overTop; 1166 1167 // Too far down -> align with bottom edge 1168 } else if (overBottom > 0) { 1169 position.top -= overBottom; 1170 1171 // Adjust based on position and margin 1172 } else { 1173 position.top = max(position.top - collisionPosTop, position.top); 1174 } 1175 } 1176 }, 1177 flip: { 1178 left: function (position, data) { 1179 var within = data.within, 1180 withinOffset = within.offset.left + within.scrollLeft, 1181 outerWidth = within.width, 1182 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, 1183 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 1184 overLeft = collisionPosLeft - offsetLeft, 1185 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, 1186 myOffset = data.my[0] === "left" ? 1187 -data.elemWidth : 1188 data.my[0] === "right" ? 1189 data.elemWidth : 1190 0, 1191 atOffset = data.at[0] === "left" ? 1192 data.targetWidth : 1193 data.at[0] === "right" ? 1194 -data.targetWidth : 1195 0, 1196 offset = -2 * data.offset[0], 1197 newOverRight, 1198 newOverLeft; 1199 1200 if (overLeft < 0) { 1201 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - 1202 outerWidth - withinOffset; 1203 if (newOverRight < 0 || newOverRight < abs(overLeft)) { 1204 position.left += myOffset + atOffset + offset; 1205 } 1206 } else if (overRight > 0) { 1207 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + 1208 atOffset + offset - offsetLeft; 1209 if (newOverLeft > 0 || abs(newOverLeft) < overRight) { 1210 position.left += myOffset + atOffset + offset; 1211 } 1212 } 1213 }, 1214 top: function (position, data) { 1215 var within = data.within, 1216 withinOffset = within.offset.top + within.scrollTop, 1217 outerHeight = within.height, 1218 offsetTop = within.isWindow ? within.scrollTop : within.offset.top, 1219 collisionPosTop = position.top - data.collisionPosition.marginTop, 1220 overTop = collisionPosTop - offsetTop, 1221 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, 1222 top = data.my[1] === "top", 1223 myOffset = top ? 1224 -data.elemHeight : 1225 data.my[1] === "bottom" ? 1226 data.elemHeight : 1227 0, 1228 atOffset = data.at[1] === "top" ? 1229 data.targetHeight : 1230 data.at[1] === "bottom" ? 1231 -data.targetHeight : 1232 0, 1233 offset = -2 * data.offset[1], 1234 newOverTop, 1235 newOverBottom; 1236 if (overTop < 0) { 1237 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - 1238 outerHeight - withinOffset; 1239 if (newOverBottom < 0 || newOverBottom < abs(overTop)) { 1240 position.top += myOffset + atOffset + offset; 1241 } 1242 } else if (overBottom > 0) { 1243 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + 1244 offset - offsetTop; 1245 if (newOverTop > 0 || abs(newOverTop) < overBottom) { 1246 position.top += myOffset + atOffset + offset; 1247 } 1248 } 1249 } 1250 }, 1251 flipfit: { 1252 left: function () { 1253 $.ui.position.flip.left.apply(this, arguments); 1254 $.ui.position.fit.left.apply(this, arguments); 1255 }, 1256 top: function () { 1257 $.ui.position.flip.top.apply(this, arguments); 1258 $.ui.position.fit.top.apply(this, arguments); 1259 } 1260 } 1261 }; 1262 1263 })(); 1264 1265 var position = $.ui.position; 1266 1267 1268 /*! 1269 * jQuery UI :data 1.14.1 1270 * https://jqueryui.com 1271 * 1272 * Copyright OpenJS Foundation and other contributors 1273 * Released under the MIT license. 1274 * https://jquery.org/license 1275 */ 1276 1277 //>>label: :data Selector 1278 //>>group: Core 1279 //>>description: Selects elements which have data stored under the specified key. 1280 //>>docs: https://api.jqueryui.com/data-selector/ 1281 1282 1283 var data = $.extend($.expr.pseudos, { 1284 data: $.expr.createPseudo(function (dataName) { 1285 return function (elem) { 1286 return !!$.data(elem, dataName); 1287 }; 1288 }) 1289 }); 1290 1291 /*! 1292 * jQuery UI Disable Selection 1.14.1 1293 * https://jqueryui.com 1294 * 1295 * Copyright OpenJS Foundation and other contributors 1296 * Released under the MIT license. 1297 * https://jquery.org/license 1298 */ 1299 1300 //>>label: disableSelection 1301 //>>group: Core 1302 //>>description: Disable selection of text content within the set of matched elements. 1303 //>>docs: https://api.jqueryui.com/disableSelection/ 1304 1305 // This file is deprecated 1306 1307 var disableSelection = $.fn.extend({ 1308 disableSelection: (function () { 1309 var eventType = "onselectstart" in document.createElement("div") ? 1310 "selectstart" : 1311 "mousedown"; 1312 1313 return function () { 1314 return this.on(eventType + ".ui-disableSelection", function (event) { 1315 event.preventDefault(); 1316 }); 1317 }; 1318 })(), 1319 1320 enableSelection: function () { 1321 return this.off(".ui-disableSelection"); 1322 } 1323 }); 1324 1325 1326 1327 // Create a local jQuery because jQuery Color relies on it and the 1328 // global may not exist with AMD and a custom build (#10199). 1329 // This module is a noop if used as a regular AMD module. 1330 // eslint-disable-next-line no-unused-vars 1331 var jQuery = $; 1332 1333 1334 /*! 1335 * jQuery Color Animations v3.0.0 1336 * https://github.com/jquery/jquery-color 1337 * 1338 * Copyright OpenJS Foundation and other contributors 1339 * Released under the MIT license. 1340 * https://jquery.org/license 1341 * 1342 * Date: Wed May 15 16:49:44 2024 +0200 1343 */ 1344 1345 1346 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " + 1347 "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", 1348 1349 class2type = {}, 1350 toString = class2type.toString, 1351 1352 // plusequals test for += 100 -= 100 1353 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, 1354 1355 // a set of RE's that can match strings and generate color tuples. 1356 stringParsers = [{ 1357 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 1358 parse: function (execResult) { 1359 return [ 1360 execResult[1], 1361 execResult[2], 1362 execResult[3], 1363 execResult[4] 1364 ]; 1365 } 1366 }, { 1367 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 1368 parse: function (execResult) { 1369 return [ 1370 execResult[1] * 2.55, 1371 execResult[2] * 2.55, 1372 execResult[3] * 2.55, 1373 execResult[4] 1374 ]; 1375 } 1376 }, { 1377 1378 // this regex ignores A-F because it's compared against an already lowercased string 1379 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/, 1380 parse: function (execResult) { 1381 return [ 1382 parseInt(execResult[1], 16), 1383 parseInt(execResult[2], 16), 1384 parseInt(execResult[3], 16), 1385 execResult[4] ? 1386 (parseInt(execResult[4], 16) / 255).toFixed(2) : 1387 1 1388 ]; 1389 } 1390 }, { 1391 1392 // this regex ignores A-F because it's compared against an already lowercased string 1393 re: /#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/, 1394 parse: function (execResult) { 1395 return [ 1396 parseInt(execResult[1] + execResult[1], 16), 1397 parseInt(execResult[2] + execResult[2], 16), 1398 parseInt(execResult[3] + execResult[3], 16), 1399 execResult[4] ? 1400 (parseInt(execResult[4] + execResult[4], 16) / 255) 1401 .toFixed(2) : 1402 1 1403 ]; 1404 } 1405 }, { 1406 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 1407 space: "hsla", 1408 parse: function (execResult) { 1409 return [ 1410 execResult[1], 1411 execResult[2] / 100, 1412 execResult[3] / 100, 1413 execResult[4] 1414 ]; 1415 } 1416 }], 1417 1418 // jQuery.Color( ) 1419 color = jQuery.Color = function (color, green, blue, alpha) { 1420 return new jQuery.Color.fn.parse(color, green, blue, alpha); 1421 }, 1422 spaces = { 1423 rgba: { 1424 props: { 1425 red: { 1426 idx: 0, 1427 type: "byte" 1428 }, 1429 green: { 1430 idx: 1, 1431 type: "byte" 1432 }, 1433 blue: { 1434 idx: 2, 1435 type: "byte" 1436 } 1437 } 1438 }, 1439 1440 hsla: { 1441 props: { 1442 hue: { 1443 idx: 0, 1444 type: "degrees" 1445 }, 1446 saturation: { 1447 idx: 1, 1448 type: "percent" 1449 }, 1450 lightness: { 1451 idx: 2, 1452 type: "percent" 1453 } 1454 } 1455 } 1456 }, 1457 propTypes = { 1458 "byte": { 1459 floor: true, 1460 max: 255 1461 }, 1462 "percent": { 1463 max: 1 1464 }, 1465 "degrees": { 1466 mod: 360, 1467 floor: true 1468 } 1469 }, 1470 1471 // colors = jQuery.Color.names 1472 colors, 1473 1474 // local aliases of functions called often 1475 each = jQuery.each; 1476 1477 // define cache name and alpha properties 1478 // for rgba and hsla spaces 1479 each(spaces, function (spaceName, space) { 1480 space.cache = "_" + spaceName; 1481 space.props.alpha = { 1482 idx: 3, 1483 type: "percent", 1484 def: 1 1485 }; 1486 }); 1487 1488 // Populate the class2type map 1489 jQuery.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "), 1490 function (_i, name) { 1491 class2type["[object " + name + "]"] = name.toLowerCase(); 1492 }); 1493 1494 function getType(obj) { 1495 if (obj == null) { 1496 return obj + ""; 1497 } 1498 1499 return typeof obj === "object" ? 1500 class2type[toString.call(obj)] || "object" : 1501 typeof obj; 1502 } 1503 1504 function clamp(value, prop, allowEmpty) { 1505 var type = propTypes[prop.type] || {}; 1506 1507 if (value == null) { 1508 return (allowEmpty || !prop.def) ? null : prop.def; 1509 } 1510 1511 // ~~ is an short way of doing floor for positive numbers 1512 value = type.floor ? ~~value : parseFloat(value); 1513 1514 if (type.mod) { 1515 1516 // we add mod before modding to make sure that negatives values 1517 // get converted properly: -10 -> 350 1518 return (value + type.mod) % type.mod; 1519 } 1520 1521 // for now all property types without mod have min and max 1522 return Math.min(type.max, Math.max(0, value)); 1523 } 1524 1525 function stringParse(string) { 1526 var inst = color(), 1527 rgba = inst._rgba = []; 1528 1529 string = string.toLowerCase(); 1530 1531 each(stringParsers, function (_i, parser) { 1532 var parsed, 1533 match = parser.re.exec(string), 1534 values = match && parser.parse(match), 1535 spaceName = parser.space || "rgba"; 1536 1537 if (values) { 1538 parsed = inst[spaceName](values); 1539 1540 // if this was an rgba parse the assignment might happen twice 1541 // oh well.... 1542 inst[spaces[spaceName].cache] = parsed[spaces[spaceName].cache]; 1543 rgba = inst._rgba = parsed._rgba; 1544 1545 // exit each( stringParsers ) here because we matched 1546 return false; 1547 } 1548 }); 1549 1550 // Found a stringParser that handled it 1551 if (rgba.length) { 1552 1553 // if this came from a parsed string, force "transparent" when alpha is 0 1554 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) 1555 if (rgba.join() === "0,0,0,0") { 1556 jQuery.extend(rgba, colors.transparent); 1557 } 1558 return inst; 1559 } 1560 1561 // named colors 1562 return colors[string]; 1563 } 1564 1565 color.fn = jQuery.extend(color.prototype, { 1566 parse: function (red, green, blue, alpha) { 1567 if (red === undefined) { 1568 this._rgba = [null, null, null, null]; 1569 return this; 1570 } 1571 if (red.jquery || red.nodeType) { 1572 red = jQuery(red).css(green); 1573 green = undefined; 1574 } 1575 1576 var inst = this, 1577 type = getType(red), 1578 rgba = this._rgba = []; 1579 1580 // more than 1 argument specified - assume ( red, green, blue, alpha ) 1581 if (green !== undefined) { 1582 red = [red, green, blue, alpha]; 1583 type = "array"; 1584 } 1585 1586 if (type === "string") { 1587 return this.parse(stringParse(red) || colors._default); 1588 } 1589 1590 if (type === "array") { 1591 each(spaces.rgba.props, function (_key, prop) { 1592 rgba[prop.idx] = clamp(red[prop.idx], prop); 1593 }); 1594 return this; 1595 } 1596 1597 if (type === "object") { 1598 if (red instanceof color) { 1599 each(spaces, function (_spaceName, space) { 1600 if (red[space.cache]) { 1601 inst[space.cache] = red[space.cache].slice(); 1602 } 1603 }); 1604 } else { 1605 each(spaces, function (_spaceName, space) { 1606 var cache = space.cache; 1607 each(space.props, function (key, prop) { 1608 1609 // if the cache doesn't exist, and we know how to convert 1610 if (!inst[cache] && space.to) { 1611 1612 // if the value was null, we don't need to copy it 1613 // if the key was alpha, we don't need to copy it either 1614 if (key === "alpha" || red[key] == null) { 1615 return; 1616 } 1617 inst[cache] = space.to(inst._rgba); 1618 } 1619 1620 // this is the only case where we allow nulls for ALL properties. 1621 // call clamp with alwaysAllowEmpty 1622 inst[cache][prop.idx] = clamp(red[key], prop, true); 1623 }); 1624 1625 // everything defined but alpha? 1626 if (inst[cache] && jQuery.inArray( 1627 null, 1628 inst[cache].slice(0, 3) 1629 ) < 0) { 1630 1631 // use the default of 1 1632 if (inst[cache][3] == null) { 1633 inst[cache][3] = 1; 1634 } 1635 1636 if (space.from) { 1637 inst._rgba = space.from(inst[cache]); 1638 } 1639 } 1640 }); 1641 } 1642 return this; 1643 } 1644 }, 1645 is: function (compare) { 1646 var is = color(compare), 1647 same = true, 1648 inst = this; 1649 1650 each(spaces, function (_, space) { 1651 var localCache, 1652 isCache = is[space.cache]; 1653 if (isCache) { 1654 localCache = inst[space.cache] || space.to && space.to(inst._rgba) || []; 1655 each(space.props, function (_, prop) { 1656 if (isCache[prop.idx] != null) { 1657 same = (isCache[prop.idx] === localCache[prop.idx]); 1658 return same; 1659 } 1660 }); 1661 } 1662 return same; 1663 }); 1664 return same; 1665 }, 1666 _space: function () { 1667 var used = [], 1668 inst = this; 1669 each(spaces, function (spaceName, space) { 1670 if (inst[space.cache]) { 1671 used.push(spaceName); 1672 } 1673 }); 1674 return used.pop(); 1675 }, 1676 transition: function (other, distance) { 1677 var end = color(other), 1678 spaceName = end._space(), 1679 space = spaces[spaceName], 1680 startColor = this.alpha() === 0 ? color("transparent") : this, 1681 start = startColor[space.cache] || space.to(startColor._rgba), 1682 result = start.slice(); 1683 1684 end = end[space.cache]; 1685 each(space.props, function (_key, prop) { 1686 var index = prop.idx, 1687 startValue = start[index], 1688 endValue = end[index], 1689 type = propTypes[prop.type] || {}; 1690 1691 // if null, don't override start value 1692 if (endValue === null) { 1693 return; 1694 } 1695 1696 // if null - use end 1697 if (startValue === null) { 1698 result[index] = endValue; 1699 } else { 1700 if (type.mod) { 1701 if (endValue - startValue > type.mod / 2) { 1702 startValue += type.mod; 1703 } else if (startValue - endValue > type.mod / 2) { 1704 startValue -= type.mod; 1705 } 1706 } 1707 result[index] = clamp((endValue - startValue) * distance + startValue, prop); 1708 } 1709 }); 1710 return this[spaceName](result); 1711 }, 1712 blend: function (opaque) { 1713 1714 // if we are already opaque - return ourself 1715 if (this._rgba[3] === 1) { 1716 return this; 1717 } 1718 1719 var rgb = this._rgba.slice(), 1720 a = rgb.pop(), 1721 blend = color(opaque)._rgba; 1722 1723 return color(jQuery.map(rgb, function (v, i) { 1724 return (1 - a) * blend[i] + a * v; 1725 })); 1726 }, 1727 toRgbaString: function () { 1728 var prefix = "rgba(", 1729 rgba = jQuery.map(this._rgba, function (v, i) { 1730 if (v != null) { 1731 return v; 1732 } 1733 return i > 2 ? 1 : 0; 1734 }); 1735 1736 if (rgba[3] === 1) { 1737 rgba.pop(); 1738 prefix = "rgb("; 1739 } 1740 1741 return prefix + rgba.join(", ") + ")"; 1742 }, 1743 toHslaString: function () { 1744 var prefix = "hsla(", 1745 hsla = jQuery.map(this.hsla(), function (v, i) { 1746 if (v == null) { 1747 v = i > 2 ? 1 : 0; 1748 } 1749 1750 // catch 1 and 2 1751 if (i && i < 3) { 1752 v = Math.round(v * 100) + "%"; 1753 } 1754 return v; 1755 }); 1756 1757 if (hsla[3] === 1) { 1758 hsla.pop(); 1759 prefix = "hsl("; 1760 } 1761 return prefix + hsla.join(", ") + ")"; 1762 }, 1763 toHexString: function (includeAlpha) { 1764 var rgba = this._rgba.slice(), 1765 alpha = rgba.pop(); 1766 1767 if (includeAlpha) { 1768 rgba.push(~~(alpha * 255)); 1769 } 1770 1771 return "#" + jQuery.map(rgba, function (v) { 1772 1773 // default to 0 when nulls exist 1774 return ("0" + (v || 0).toString(16)).substr(-2); 1775 }).join(""); 1776 }, 1777 toString: function () { 1778 return this.toRgbaString(); 1779 } 1780 }); 1781 color.fn.parse.prototype = color.fn; 1782 1783 // hsla conversions adapted from: 1784 // https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 1785 1786 function hue2rgb(p, q, h) { 1787 h = (h + 1) % 1; 1788 if (h * 6 < 1) { 1789 return p + (q - p) * h * 6; 1790 } 1791 if (h * 2 < 1) { 1792 return q; 1793 } 1794 if (h * 3 < 2) { 1795 return p + (q - p) * ((2 / 3) - h) * 6; 1796 } 1797 return p; 1798 } 1799 1800 spaces.hsla.to = function (rgba) { 1801 if (rgba[0] == null || rgba[1] == null || rgba[2] == null) { 1802 return [null, null, null, rgba[3]]; 1803 } 1804 var r = rgba[0] / 255, 1805 g = rgba[1] / 255, 1806 b = rgba[2] / 255, 1807 a = rgba[3], 1808 max = Math.max(r, g, b), 1809 min = Math.min(r, g, b), 1810 diff = max - min, 1811 add = max + min, 1812 l = add * 0.5, 1813 h, s; 1814 1815 if (min === max) { 1816 h = 0; 1817 } else if (r === max) { 1818 h = (60 * (g - b) / diff) + 360; 1819 } else if (g === max) { 1820 h = (60 * (b - r) / diff) + 120; 1821 } else { 1822 h = (60 * (r - g) / diff) + 240; 1823 } 1824 1825 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% 1826 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) 1827 if (diff === 0) { 1828 s = 0; 1829 } else if (l <= 0.5) { 1830 s = diff / add; 1831 } else { 1832 s = diff / (2 - add); 1833 } 1834 return [Math.round(h) % 360, s, l, a == null ? 1 : a]; 1835 }; 1836 1837 spaces.hsla.from = function (hsla) { 1838 if (hsla[0] == null || hsla[1] == null || hsla[2] == null) { 1839 return [null, null, null, hsla[3]]; 1840 } 1841 var h = hsla[0] / 360, 1842 s = hsla[1], 1843 l = hsla[2], 1844 a = hsla[3], 1845 q = l <= 0.5 ? l * (1 + s) : l + s - l * s, 1846 p = 2 * l - q; 1847 1848 return [ 1849 Math.round(hue2rgb(p, q, h + (1 / 3)) * 255), 1850 Math.round(hue2rgb(p, q, h) * 255), 1851 Math.round(hue2rgb(p, q, h - (1 / 3)) * 255), 1852 a 1853 ]; 1854 }; 1855 1856 1857 each(spaces, function (spaceName, space) { 1858 var props = space.props, 1859 cache = space.cache, 1860 to = space.to, 1861 from = space.from; 1862 1863 // makes rgba() and hsla() 1864 color.fn[spaceName] = function (value) { 1865 1866 // generate a cache for this space if it doesn't exist 1867 if (to && !this[cache]) { 1868 this[cache] = to(this._rgba); 1869 } 1870 if (value === undefined) { 1871 return this[cache].slice(); 1872 } 1873 1874 var ret, 1875 type = getType(value), 1876 arr = (type === "array" || type === "object") ? value : arguments, 1877 local = this[cache].slice(); 1878 1879 each(props, function (key, prop) { 1880 var val = arr[type === "object" ? key : prop.idx]; 1881 if (val == null) { 1882 val = local[prop.idx]; 1883 } 1884 local[prop.idx] = clamp(val, prop); 1885 }); 1886 1887 if (from) { 1888 ret = color(from(local)); 1889 ret[cache] = local; 1890 return ret; 1891 } else { 1892 return color(local); 1893 } 1894 }; 1895 1896 // makes red() green() blue() alpha() hue() saturation() lightness() 1897 each(props, function (key, prop) { 1898 1899 // alpha is included in more than one space 1900 if (color.fn[key]) { 1901 return; 1902 } 1903 color.fn[key] = function (value) { 1904 var local, cur, match, fn, 1905 vtype = getType(value); 1906 1907 if (key === "alpha") { 1908 fn = this._hsla ? "hsla" : "rgba"; 1909 } else { 1910 fn = spaceName; 1911 } 1912 local = this[fn](); 1913 cur = local[prop.idx]; 1914 1915 if (vtype === "undefined") { 1916 return cur; 1917 } 1918 1919 if (vtype === "function") { 1920 value = value.call(this, cur); 1921 vtype = getType(value); 1922 } 1923 if (value == null && prop.empty) { 1924 return this; 1925 } 1926 if (vtype === "string") { 1927 match = rplusequals.exec(value); 1928 if (match) { 1929 value = cur + parseFloat(match[2]) * (match[1] === "+" ? 1 : -1); 1930 } 1931 } 1932 local[prop.idx] = value; 1933 return this[fn](local); 1934 }; 1935 }); 1936 }); 1937 1938 // add cssHook and .fx.step function for each named hook. 1939 // accept a space separated string of properties 1940 color.hook = function (hook) { 1941 var hooks = hook.split(" "); 1942 each(hooks, function (_i, hook) { 1943 jQuery.cssHooks[hook] = { 1944 set: function (elem, value) { 1945 var parsed; 1946 1947 if (value !== "transparent" && 1948 (getType(value) !== "string" || 1949 (parsed = stringParse(value)))) { 1950 value = color(parsed || value); 1951 value = value.toRgbaString(); 1952 } 1953 elem.style[hook] = value; 1954 } 1955 }; 1956 jQuery.fx.step[hook] = function (fx) { 1957 if (!fx.colorInit) { 1958 fx.start = color(fx.elem, hook); 1959 fx.end = color(fx.end); 1960 fx.colorInit = true; 1961 } 1962 jQuery.cssHooks[hook].set(fx.elem, fx.start.transition(fx.end, fx.pos)); 1963 }; 1964 }); 1965 1966 }; 1967 1968 color.hook(stepHooks); 1969 1970 jQuery.cssHooks.borderColor = { 1971 expand: function (value) { 1972 var expanded = {}; 1973 1974 each(["Top", "Right", "Bottom", "Left"], function (_i, part) { 1975 expanded["border" + part + "Color"] = value; 1976 }); 1977 return expanded; 1978 } 1979 }; 1980 1981 // Basic color names only. 1982 // Usage of any of the other color names requires adding yourself or including 1983 // jquery.color.svg-names.js. 1984 colors = jQuery.Color.names = { 1985 1986 // 4.1. Basic color keywords 1987 aqua: "#00ffff", 1988 black: "#000000", 1989 blue: "#0000ff", 1990 fuchsia: "#ff00ff", 1991 gray: "#808080", 1992 green: "#008000", 1993 lime: "#00ff00", 1994 maroon: "#800000", 1995 navy: "#000080", 1996 olive: "#808000", 1997 purple: "#800080", 1998 red: "#ff0000", 1999 silver: "#c0c0c0", 2000 teal: "#008080", 2001 white: "#ffffff", 2002 yellow: "#ffff00", 2003 2004 // 4.2.3. "transparent" color keyword 2005 transparent: [null, null, null, 0], 2006 2007 _default: "#ffffff" 2008 }; 2009 2010 2011 /*! 2012 * jQuery UI Effects 1.14.1 2013 * https://jqueryui.com 2014 * 2015 * Copyright OpenJS Foundation and other contributors 2016 * Released under the MIT license. 2017 * https://jquery.org/license 2018 */ 2019 2020 //>>label: Effects Core 2021 //>>group: Effects 2022 /* eslint-disable max-len */ 2023 //>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects. 2024 /* eslint-enable max-len */ 2025 //>>docs: https://api.jqueryui.com/category/effects-core/ 2026 //>>demos: https://jqueryui.com/effect/ 2027 2028 2029 var dataSpace = "ui-effects-", 2030 dataSpaceStyle = "ui-effects-style", 2031 dataSpaceAnimated = "ui-effects-animated"; 2032 2033 $.effects = { 2034 effect: {} 2035 }; 2036 2037 /******************************************************************************/ 2038 /****************************** CLASS ANIMATIONS ******************************/ 2039 /******************************************************************************/ 2040 (function () { 2041 2042 var classAnimationActions = ["add", "remove", "toggle"], 2043 shorthandStyles = { 2044 border: 1, 2045 borderBottom: 1, 2046 borderColor: 1, 2047 borderLeft: 1, 2048 borderRight: 1, 2049 borderTop: 1, 2050 borderWidth: 1, 2051 margin: 1, 2052 padding: 1 2053 }; 2054 2055 $.each( 2056 ["borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle"], 2057 function (_, prop) { 2058 $.fx.step[prop] = function (fx) { 2059 if (fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr) { 2060 jQuery.style(fx.elem, prop, fx.end); 2061 fx.setAttr = true; 2062 } 2063 }; 2064 } 2065 ); 2066 2067 function camelCase(string) { 2068 return string.replace(/-([\da-z])/gi, function (all, letter) { 2069 return letter.toUpperCase(); 2070 }); 2071 } 2072 2073 function getElementStyles(elem) { 2074 var key, len, 2075 style = elem.ownerDocument.defaultView.getComputedStyle(elem), 2076 styles = {}; 2077 2078 len = style.length; 2079 while (len--) { 2080 key = style[len]; 2081 if (typeof style[key] === "string") { 2082 styles[camelCase(key)] = style[key]; 2083 } 2084 } 2085 2086 return styles; 2087 } 2088 2089 function styleDifference(oldStyle, newStyle) { 2090 var diff = {}, 2091 name, value; 2092 2093 for (name in newStyle) { 2094 value = newStyle[name]; 2095 if (oldStyle[name] !== value) { 2096 if (!shorthandStyles[name]) { 2097 if ($.fx.step[name] || !isNaN(parseFloat(value))) { 2098 diff[name] = value; 2099 } 2100 } 2101 } 2102 } 2103 2104 return diff; 2105 } 2106 2107 $.effects.animateClass = function (value, duration, easing, callback) { 2108 var o = $.speed(duration, easing, callback); 2109 2110 return this.queue(function () { 2111 var animated = $(this), 2112 baseClass = animated.attr("class") || "", 2113 applyClassChange, 2114 allAnimations = o.children ? animated.find("*").addBack() : animated; 2115 2116 // Map the animated objects to store the original styles. 2117 allAnimations = allAnimations.map(function () { 2118 var el = $(this); 2119 return { 2120 el: el, 2121 start: getElementStyles(this) 2122 }; 2123 }); 2124 2125 // Apply class change 2126 applyClassChange = function () { 2127 $.each(classAnimationActions, function (i, action) { 2128 if (value[action]) { 2129 animated[action + "Class"](value[action]); 2130 } 2131 }); 2132 }; 2133 applyClassChange(); 2134 2135 // Map all animated objects again - calculate new styles and diff 2136 allAnimations = allAnimations.map(function () { 2137 this.end = getElementStyles(this.el[0]); 2138 this.diff = styleDifference(this.start, this.end); 2139 return this; 2140 }); 2141 2142 // Apply original class 2143 animated.attr("class", baseClass); 2144 2145 // Map all animated objects again - this time collecting a promise 2146 allAnimations = allAnimations.map(function () { 2147 var styleInfo = this, 2148 dfd = $.Deferred(), 2149 opts = $.extend({}, o, { 2150 queue: false, 2151 complete: function () { 2152 dfd.resolve(styleInfo); 2153 } 2154 }); 2155 2156 this.el.animate(this.diff, opts); 2157 return dfd.promise(); 2158 }); 2159 2160 // Once all animations have completed: 2161 $.when.apply($, allAnimations.get()).done(function () { 2162 2163 // Set the final class 2164 applyClassChange(); 2165 2166 // For each animated element, 2167 // clear all css properties that were animated 2168 $.each(arguments, function () { 2169 var el = this.el; 2170 $.each(this.diff, function (key) { 2171 el.css(key, ""); 2172 }); 2173 }); 2174 2175 // This is guarnteed to be there if you use jQuery.speed() 2176 // it also handles dequeuing the next anim... 2177 o.complete.call(animated[0]); 2178 }); 2179 }); 2180 }; 2181 2182 $.fn.extend({ 2183 addClass: (function (orig) { 2184 return function (classNames, speed, easing, callback) { 2185 return speed ? 2186 $.effects.animateClass.call(this, 2187 { add: classNames }, speed, easing, callback) : 2188 orig.apply(this, arguments); 2189 }; 2190 })($.fn.addClass), 2191 2192 removeClass: (function (orig) { 2193 return function (classNames, speed, easing, callback) { 2194 return arguments.length > 1 ? 2195 $.effects.animateClass.call(this, 2196 { remove: classNames }, speed, easing, callback) : 2197 orig.apply(this, arguments); 2198 }; 2199 })($.fn.removeClass), 2200 2201 toggleClass: (function (orig) { 2202 return function (classNames, force, speed, easing, callback) { 2203 if (typeof force === "boolean" || force === undefined) { 2204 if (!speed) { 2205 2206 // Without speed parameter 2207 return orig.apply(this, arguments); 2208 } else { 2209 return $.effects.animateClass.call(this, 2210 (force ? { add: classNames } : { remove: classNames }), 2211 speed, easing, callback); 2212 } 2213 } else { 2214 2215 // Without force parameter 2216 return $.effects.animateClass.call(this, 2217 { toggle: classNames }, force, speed, easing); 2218 } 2219 }; 2220 })($.fn.toggleClass), 2221 2222 switchClass: function (remove, add, speed, easing, callback) { 2223 return $.effects.animateClass.call(this, { 2224 add: add, 2225 remove: remove 2226 }, speed, easing, callback); 2227 } 2228 }); 2229 2230 })(); 2231 2232 /******************************************************************************/ 2233 /*********************************** EFFECTS **********************************/ 2234 /******************************************************************************/ 2235 2236 (function () { 2237 2238 if ($.expr && $.expr.pseudos && $.expr.pseudos.animated) { 2239 $.expr.pseudos.animated = (function (orig) { 2240 return function (elem) { 2241 return !!$(elem).data(dataSpaceAnimated) || orig(elem); 2242 }; 2243 })($.expr.pseudos.animated); 2244 } 2245 2246 if ($.uiBackCompat === true) { 2247 $.extend($.effects, { 2248 2249 // Saves a set of properties in a data storage 2250 save: function (element, set) { 2251 var i = 0, length = set.length; 2252 for (; i < length; i++) { 2253 if (set[i] !== null) { 2254 element.data(dataSpace + set[i], element[0].style[set[i]]); 2255 } 2256 } 2257 }, 2258 2259 // Restores a set of previously saved properties from a data storage 2260 restore: function (element, set) { 2261 var val, i = 0, length = set.length; 2262 for (; i < length; i++) { 2263 if (set[i] !== null) { 2264 val = element.data(dataSpace + set[i]); 2265 element.css(set[i], val); 2266 } 2267 } 2268 }, 2269 2270 setMode: function (el, mode) { 2271 if (mode === "toggle") { 2272 mode = el.is(":hidden") ? "show" : "hide"; 2273 } 2274 return mode; 2275 }, 2276 2277 // Wraps the element around a wrapper that copies position properties 2278 createWrapper: function (element) { 2279 2280 // If the element is already wrapped, return it 2281 if (element.parent().is(".ui-effects-wrapper")) { 2282 return element.parent(); 2283 } 2284 2285 // Wrap the element 2286 var props = { 2287 width: element.outerWidth(true), 2288 height: element.outerHeight(true), 2289 "float": element.css("float") 2290 }, 2291 wrapper = $("<div></div>") 2292 .addClass("ui-effects-wrapper") 2293 .css({ 2294 fontSize: "100%", 2295 background: "transparent", 2296 border: "none", 2297 margin: 0, 2298 padding: 0 2299 }), 2300 2301 // Store the size in case width/height are defined in % - Fixes #5245 2302 size = { 2303 width: element.width(), 2304 height: element.height() 2305 }, 2306 active = document.activeElement; 2307 2308 // Support: Firefox 2309 // Firefox incorrectly exposes anonymous content 2310 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 2311 try { 2312 // eslint-disable-next-line no-unused-expressions 2313 active.id; 2314 } catch (e) { 2315 active = document.body; 2316 } 2317 2318 element.wrap(wrapper); 2319 2320 // Fixes #7595 - Elements lose focus when wrapped. 2321 if (element[0] === active || $.contains(element[0], active)) { 2322 $(active).trigger("focus"); 2323 } 2324 2325 // Hotfix for jQuery 1.4 since some change in wrap() seems to actually 2326 // lose the reference to the wrapped element 2327 wrapper = element.parent(); 2328 2329 // Transfer positioning properties to the wrapper 2330 if (element.css("position") === "static") { 2331 wrapper.css({ position: "relative" }); 2332 element.css({ position: "relative" }); 2333 } else { 2334 $.extend(props, { 2335 position: element.css("position"), 2336 zIndex: element.css("z-index") 2337 }); 2338 $.each(["top", "left", "bottom", "right"], function (i, pos) { 2339 props[pos] = element.css(pos); 2340 if (isNaN(parseInt(props[pos], 10))) { 2341 props[pos] = "auto"; 2342 } 2343 }); 2344 element.css({ 2345 position: "relative", 2346 top: 0, 2347 left: 0, 2348 right: "auto", 2349 bottom: "auto" 2350 }); 2351 } 2352 element.css(size); 2353 2354 return wrapper.css(props).show(); 2355 }, 2356 2357 removeWrapper: function (element) { 2358 var active = document.activeElement; 2359 2360 if (element.parent().is(".ui-effects-wrapper")) { 2361 element.parent().replaceWith(element); 2362 2363 // Fixes #7595 - Elements lose focus when wrapped. 2364 if (element[0] === active || $.contains(element[0], active)) { 2365 $(active).trigger("focus"); 2366 } 2367 } 2368 2369 return element; 2370 } 2371 }); 2372 } 2373 2374 $.extend($.effects, { 2375 version: "1.14.1", 2376 2377 define: function (name, mode, effect) { 2378 if (!effect) { 2379 effect = mode; 2380 mode = "effect"; 2381 } 2382 2383 $.effects.effect[name] = effect; 2384 $.effects.effect[name].mode = mode; 2385 2386 return effect; 2387 }, 2388 2389 scaledDimensions: function (element, percent, direction) { 2390 if (percent === 0) { 2391 return { 2392 height: 0, 2393 width: 0, 2394 outerHeight: 0, 2395 outerWidth: 0 2396 }; 2397 } 2398 2399 var x = direction !== "horizontal" ? ((percent || 100) / 100) : 1, 2400 y = direction !== "vertical" ? ((percent || 100) / 100) : 1; 2401 2402 return { 2403 height: element.height() * y, 2404 width: element.width() * x, 2405 outerHeight: element.outerHeight() * y, 2406 outerWidth: element.outerWidth() * x 2407 }; 2408 2409 }, 2410 2411 clipToBox: function (animation) { 2412 return { 2413 width: animation.clip.right - animation.clip.left, 2414 height: animation.clip.bottom - animation.clip.top, 2415 left: animation.clip.left, 2416 top: animation.clip.top 2417 }; 2418 }, 2419 2420 // Injects recently queued functions to be first in line (after "inprogress") 2421 unshift: function (element, queueLength, count) { 2422 var queue = element.queue(); 2423 2424 if (queueLength > 1) { 2425 queue.splice.apply(queue, 2426 [1, 0].concat(queue.splice(queueLength, count))); 2427 } 2428 element.dequeue(); 2429 }, 2430 2431 saveStyle: function (element) { 2432 element.data(dataSpaceStyle, element[0].style.cssText); 2433 }, 2434 2435 restoreStyle: function (element) { 2436 element[0].style.cssText = element.data(dataSpaceStyle) || ""; 2437 element.removeData(dataSpaceStyle); 2438 }, 2439 2440 mode: function (element, mode) { 2441 var hidden = element.is(":hidden"); 2442 2443 if (mode === "toggle") { 2444 mode = hidden ? "show" : "hide"; 2445 } 2446 if (hidden ? mode === "hide" : mode === "show") { 2447 mode = "none"; 2448 } 2449 return mode; 2450 }, 2451 2452 // Translates a [top,left] array into a baseline value 2453 getBaseline: function (origin, original) { 2454 var y, x; 2455 2456 switch (origin[0]) { 2457 case "top": 2458 y = 0; 2459 break; 2460 case "middle": 2461 y = 0.5; 2462 break; 2463 case "bottom": 2464 y = 1; 2465 break; 2466 default: 2467 y = origin[0] / original.height; 2468 } 2469 2470 switch (origin[1]) { 2471 case "left": 2472 x = 0; 2473 break; 2474 case "center": 2475 x = 0.5; 2476 break; 2477 case "right": 2478 x = 1; 2479 break; 2480 default: 2481 x = origin[1] / original.width; 2482 } 2483 2484 return { 2485 x: x, 2486 y: y 2487 }; 2488 }, 2489 2490 // Creates a placeholder element so that the original element can be made absolute 2491 createPlaceholder: function (element) { 2492 var placeholder, 2493 cssPosition = element.css("position"), 2494 position = element.position(); 2495 2496 // Lock in margins first to account for form elements, which 2497 // will change margin if you explicitly set height 2498 // see: https://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380 2499 // Support: Safari 2500 element.css({ 2501 marginTop: element.css("marginTop"), 2502 marginBottom: element.css("marginBottom"), 2503 marginLeft: element.css("marginLeft"), 2504 marginRight: element.css("marginRight") 2505 }) 2506 .outerWidth(element.outerWidth()) 2507 .outerHeight(element.outerHeight()); 2508 2509 if (/^(static|relative)/.test(cssPosition)) { 2510 cssPosition = "absolute"; 2511 2512 placeholder = $("<" + element[0].nodeName + ">").insertAfter(element).css({ 2513 2514 // Convert inline to inline block to account for inline elements 2515 // that turn to inline block based on content (like img) 2516 display: /^(inline|ruby)/.test(element.css("display")) ? 2517 "inline-block" : 2518 "block", 2519 visibility: "hidden", 2520 2521 // Margins need to be set to account for margin collapse 2522 marginTop: element.css("marginTop"), 2523 marginBottom: element.css("marginBottom"), 2524 marginLeft: element.css("marginLeft"), 2525 marginRight: element.css("marginRight"), 2526 "float": element.css("float") 2527 }) 2528 .outerWidth(element.outerWidth()) 2529 .outerHeight(element.outerHeight()) 2530 .addClass("ui-effects-placeholder"); 2531 2532 element.data(dataSpace + "placeholder", placeholder); 2533 } 2534 2535 element.css({ 2536 position: cssPosition, 2537 left: position.left, 2538 top: position.top 2539 }); 2540 2541 return placeholder; 2542 }, 2543 2544 removePlaceholder: function (element) { 2545 var dataKey = dataSpace + "placeholder", 2546 placeholder = element.data(dataKey); 2547 2548 if (placeholder) { 2549 placeholder.remove(); 2550 element.removeData(dataKey); 2551 } 2552 }, 2553 2554 // Removes a placeholder if it exists and restores 2555 // properties that were modified during placeholder creation 2556 cleanUp: function (element) { 2557 $.effects.restoreStyle(element); 2558 $.effects.removePlaceholder(element); 2559 }, 2560 2561 setTransition: function (element, list, factor, value) { 2562 value = value || {}; 2563 $.each(list, function (i, x) { 2564 var unit = element.cssUnit(x); 2565 if (unit[0] > 0) { 2566 value[x] = unit[0] * factor + unit[1]; 2567 } 2568 }); 2569 return value; 2570 } 2571 }); 2572 2573 // Return an effect options object for the given parameters: 2574 function _normalizeArguments(effect, options, speed, callback) { 2575 2576 // Allow passing all options as the first parameter 2577 if ($.isPlainObject(effect)) { 2578 options = effect; 2579 effect = effect.effect; 2580 } 2581 2582 // Convert to an object 2583 effect = { effect: effect }; 2584 2585 // Catch (effect, null, ...) 2586 if (options == null) { 2587 options = {}; 2588 } 2589 2590 // Catch (effect, callback) 2591 if (typeof options === "function") { 2592 callback = options; 2593 speed = null; 2594 options = {}; 2595 } 2596 2597 // Catch (effect, speed, ?) 2598 if (typeof options === "number" || $.fx.speeds[options]) { 2599 callback = speed; 2600 speed = options; 2601 options = {}; 2602 } 2603 2604 // Catch (effect, options, callback) 2605 if (typeof speed === "function") { 2606 callback = speed; 2607 speed = null; 2608 } 2609 2610 // Add options to effect 2611 if (options) { 2612 $.extend(effect, options); 2613 } 2614 2615 speed = speed || options.duration; 2616 effect.duration = $.fx.off ? 0 : 2617 typeof speed === "number" ? speed : 2618 speed in $.fx.speeds ? $.fx.speeds[speed] : 2619 $.fx.speeds._default; 2620 2621 effect.complete = callback || options.complete; 2622 2623 return effect; 2624 } 2625 2626 function standardAnimationOption(option) { 2627 2628 // Valid standard speeds (nothing, number, named speed) 2629 if (!option || typeof option === "number" || $.fx.speeds[option]) { 2630 return true; 2631 } 2632 2633 // Invalid strings - treat as "normal" speed 2634 if (typeof option === "string" && !$.effects.effect[option]) { 2635 return true; 2636 } 2637 2638 // Complete callback 2639 if (typeof option === "function") { 2640 return true; 2641 } 2642 2643 // Options hash (but not naming an effect) 2644 if (typeof option === "object" && !option.effect) { 2645 return true; 2646 } 2647 2648 // Didn't match any standard API 2649 return false; 2650 } 2651 2652 $.fn.extend({ 2653 effect: function ( /* effect, options, speed, callback */) { 2654 var args = _normalizeArguments.apply(this, arguments), 2655 effectMethod = $.effects.effect[args.effect], 2656 defaultMode = effectMethod.mode, 2657 queue = args.queue, 2658 queueName = queue || "fx", 2659 complete = args.complete, 2660 mode = args.mode, 2661 modes = [], 2662 prefilter = function (next) { 2663 var el = $(this), 2664 normalizedMode = $.effects.mode(el, mode) || defaultMode; 2665 2666 // Sentinel for duck-punching the :animated pseudo-selector 2667 el.data(dataSpaceAnimated, true); 2668 2669 // Save effect mode for later use, 2670 // we can't just call $.effects.mode again later, 2671 // as the .show() below destroys the initial state 2672 modes.push(normalizedMode); 2673 2674 // See $.uiBackCompat inside of run() for removal of defaultMode in 1.14 2675 if (defaultMode && (normalizedMode === "show" || 2676 (normalizedMode === defaultMode && normalizedMode === "hide"))) { 2677 el.show(); 2678 } 2679 2680 if (!defaultMode || normalizedMode !== "none") { 2681 $.effects.saveStyle(el); 2682 } 2683 2684 if (typeof next === "function") { 2685 next(); 2686 } 2687 }; 2688 2689 if ($.fx.off || !effectMethod) { 2690 2691 // Delegate to the original method (e.g., .show()) if possible 2692 if (mode) { 2693 return this[mode](args.duration, complete); 2694 } else { 2695 return this.each(function () { 2696 if (complete) { 2697 complete.call(this); 2698 } 2699 }); 2700 } 2701 } 2702 2703 function run(next) { 2704 var elem = $(this); 2705 2706 function cleanup() { 2707 elem.removeData(dataSpaceAnimated); 2708 2709 $.effects.cleanUp(elem); 2710 2711 if (args.mode === "hide") { 2712 elem.hide(); 2713 } 2714 2715 done(); 2716 } 2717 2718 function done() { 2719 if (typeof complete === "function") { 2720 complete.call(elem[0]); 2721 } 2722 2723 if (typeof next === "function") { 2724 next(); 2725 } 2726 } 2727 2728 // Override mode option on a per element basis, 2729 // as toggle can be either show or hide depending on element state 2730 args.mode = modes.shift(); 2731 2732 if ($.uiBackCompat === true && !defaultMode) { 2733 if (elem.is(":hidden") ? mode === "hide" : mode === "show") { 2734 2735 // Call the core method to track "olddisplay" properly 2736 elem[mode](); 2737 done(); 2738 } else { 2739 effectMethod.call(elem[0], args, done); 2740 } 2741 } else { 2742 if (args.mode === "none") { 2743 2744 // Call the core method to track "olddisplay" properly 2745 elem[mode](); 2746 done(); 2747 } else { 2748 effectMethod.call(elem[0], args, cleanup); 2749 } 2750 } 2751 } 2752 2753 // Run prefilter on all elements first to ensure that 2754 // any showing or hiding happens before placeholder creation, 2755 // which ensures that any layout changes are correctly captured. 2756 return queue === false ? 2757 this.each(prefilter).each(run) : 2758 this.queue(queueName, prefilter).queue(queueName, run); 2759 }, 2760 2761 show: (function (orig) { 2762 return function (option) { 2763 if (standardAnimationOption(option)) { 2764 return orig.apply(this, arguments); 2765 } else { 2766 var args = _normalizeArguments.apply(this, arguments); 2767 args.mode = "show"; 2768 return this.effect.call(this, args); 2769 } 2770 }; 2771 })($.fn.show), 2772 2773 hide: (function (orig) { 2774 return function (option) { 2775 if (standardAnimationOption(option)) { 2776 return orig.apply(this, arguments); 2777 } else { 2778 var args = _normalizeArguments.apply(this, arguments); 2779 args.mode = "hide"; 2780 return this.effect.call(this, args); 2781 } 2782 }; 2783 })($.fn.hide), 2784 2785 toggle: (function (orig) { 2786 return function (option) { 2787 if (standardAnimationOption(option) || typeof option === "boolean") { 2788 return orig.apply(this, arguments); 2789 } else { 2790 var args = _normalizeArguments.apply(this, arguments); 2791 args.mode = "toggle"; 2792 return this.effect.call(this, args); 2793 } 2794 }; 2795 })($.fn.toggle), 2796 2797 cssUnit: function (key) { 2798 var style = this.css(key), 2799 val = []; 2800 2801 $.each(["em", "px", "%", "pt"], function (i, unit) { 2802 if (style.indexOf(unit) > 0) { 2803 val = [parseFloat(style), unit]; 2804 } 2805 }); 2806 return val; 2807 }, 2808 2809 cssClip: function (clipObj) { 2810 if (clipObj) { 2811 return this.css("clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " + 2812 clipObj.bottom + "px " + clipObj.left + "px)"); 2813 } 2814 return parseClip(this.css("clip"), this); 2815 }, 2816 2817 transfer: function (options, done) { 2818 var element = $(this), 2819 target = $(options.to), 2820 targetFixed = target.css("position") === "fixed", 2821 body = $("body"), 2822 fixTop = targetFixed ? body.scrollTop() : 0, 2823 fixLeft = targetFixed ? body.scrollLeft() : 0, 2824 endPosition = target.offset(), 2825 animation = { 2826 top: endPosition.top - fixTop, 2827 left: endPosition.left - fixLeft, 2828 height: target.innerHeight(), 2829 width: target.innerWidth() 2830 }, 2831 startPosition = element.offset(), 2832 transfer = $("<div class='ui-effects-transfer'></div>"); 2833 2834 transfer 2835 .appendTo("body") 2836 .addClass(options.className) 2837 .css({ 2838 top: startPosition.top - fixTop, 2839 left: startPosition.left - fixLeft, 2840 height: element.innerHeight(), 2841 width: element.innerWidth(), 2842 position: targetFixed ? "fixed" : "absolute" 2843 }) 2844 .animate(animation, options.duration, options.easing, function () { 2845 transfer.remove(); 2846 if (typeof done === "function") { 2847 done(); 2848 } 2849 }); 2850 } 2851 }); 2852 2853 function parseClip(str, element) { 2854 var outerWidth = element.outerWidth(), 2855 outerHeight = element.outerHeight(), 2856 clipRegex = /^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/, 2857 values = clipRegex.exec(str) || ["", 0, outerWidth, outerHeight, 0]; 2858 2859 return { 2860 top: parseFloat(values[1]) || 0, 2861 right: values[2] === "auto" ? outerWidth : parseFloat(values[2]), 2862 bottom: values[3] === "auto" ? outerHeight : parseFloat(values[3]), 2863 left: parseFloat(values[4]) || 0 2864 }; 2865 } 2866 2867 $.fx.step.clip = function (fx) { 2868 if (!fx.clipInit) { 2869 fx.start = $(fx.elem).cssClip(); 2870 if (typeof fx.end === "string") { 2871 fx.end = parseClip(fx.end, fx.elem); 2872 } 2873 fx.clipInit = true; 2874 } 2875 2876 $(fx.elem).cssClip({ 2877 top: fx.pos * (fx.end.top - fx.start.top) + fx.start.top, 2878 right: fx.pos * (fx.end.right - fx.start.right) + fx.start.right, 2879 bottom: fx.pos * (fx.end.bottom - fx.start.bottom) + fx.start.bottom, 2880 left: fx.pos * (fx.end.left - fx.start.left) + fx.start.left 2881 }); 2882 }; 2883 2884 })(); 2885 2886 /******************************************************************************/ 2887 /*********************************** EASING ***********************************/ 2888 /******************************************************************************/ 2889 2890 (function () { 2891 2892 // Based on easing equations from Robert Penner (http://robertpenner.com/easing) 2893 2894 var baseEasings = {}; 2895 2896 $.each(["Quad", "Cubic", "Quart", "Quint", "Expo"], function (i, name) { 2897 baseEasings[name] = function (p) { 2898 return Math.pow(p, i + 2); 2899 }; 2900 }); 2901 2902 $.extend(baseEasings, { 2903 Sine: function (p) { 2904 return 1 - Math.cos(p * Math.PI / 2); 2905 }, 2906 Circ: function (p) { 2907 return 1 - Math.sqrt(1 - p * p); 2908 }, 2909 Elastic: function (p) { 2910 return p === 0 || p === 1 ? p : 2911 -Math.pow(2, 8 * (p - 1)) * Math.sin(((p - 1) * 80 - 7.5) * Math.PI / 15); 2912 }, 2913 Back: function (p) { 2914 return p * p * (3 * p - 2); 2915 }, 2916 Bounce: function (p) { 2917 var pow2, 2918 bounce = 4; 2919 2920 while (p < ((pow2 = Math.pow(2, --bounce)) - 1) / 11) { } 2921 return 1 / Math.pow(4, 3 - bounce) - 7.5625 * Math.pow((pow2 * 3 - 2) / 22 - p, 2); 2922 } 2923 }); 2924 2925 $.each(baseEasings, function (name, easeIn) { 2926 $.easing["easeIn" + name] = easeIn; 2927 $.easing["easeOut" + name] = function (p) { 2928 return 1 - easeIn(1 - p); 2929 }; 2930 $.easing["easeInOut" + name] = function (p) { 2931 return p < 0.5 ? 2932 easeIn(p * 2) / 2 : 2933 1 - easeIn(p * -2 + 2) / 2; 2934 }; 2935 }); 2936 2937 })(); 2938 2939 var effect = $.effects; 2940 2941 2942 /*! 2943 * jQuery UI Effects Blind 1.14.1 2944 * https://jqueryui.com 2945 * 2946 * Copyright OpenJS Foundation and other contributors 2947 * Released under the MIT license. 2948 * https://jquery.org/license 2949 */ 2950 2951 //>>label: Blind Effect 2952 //>>group: Effects 2953 //>>description: Blinds the element. 2954 //>>docs: https://api.jqueryui.com/blind-effect/ 2955 //>>demos: https://jqueryui.com/effect/ 2956 2957 2958 var effectsEffectBlind = $.effects.define("blind", "hide", function (options, done) { 2959 var map = { 2960 up: ["bottom", "top"], 2961 vertical: ["bottom", "top"], 2962 down: ["top", "bottom"], 2963 left: ["right", "left"], 2964 horizontal: ["right", "left"], 2965 right: ["left", "right"] 2966 }, 2967 element = $(this), 2968 direction = options.direction || "up", 2969 start = element.cssClip(), 2970 animate = { clip: $.extend({}, start) }, 2971 placeholder = $.effects.createPlaceholder(element); 2972 2973 animate.clip[map[direction][0]] = animate.clip[map[direction][1]]; 2974 2975 if (options.mode === "show") { 2976 element.cssClip(animate.clip); 2977 if (placeholder) { 2978 placeholder.css($.effects.clipToBox(animate)); 2979 } 2980 2981 animate.clip = start; 2982 } 2983 2984 if (placeholder) { 2985 placeholder.animate($.effects.clipToBox(animate), options.duration, options.easing); 2986 } 2987 2988 element.animate(animate, { 2989 queue: false, 2990 duration: options.duration, 2991 easing: options.easing, 2992 complete: done 2993 }); 2994 }); 2995 2996 2997 /*! 2998 * jQuery UI Effects Bounce 1.14.1 2999 * https://jqueryui.com 3000 * 3001 * Copyright OpenJS Foundation and other contributors 3002 * Released under the MIT license. 3003 * https://jquery.org/license 3004 */ 3005 3006 //>>label: Bounce Effect 3007 //>>group: Effects 3008 //>>description: Bounces an element horizontally or vertically n times. 3009 //>>docs: https://api.jqueryui.com/bounce-effect/ 3010 //>>demos: https://jqueryui.com/effect/ 3011 3012 3013 var effectsEffectBounce = $.effects.define("bounce", function (options, done) { 3014 var upAnim, downAnim, refValue, 3015 element = $(this), 3016 3017 // Defaults: 3018 mode = options.mode, 3019 hide = mode === "hide", 3020 show = mode === "show", 3021 direction = options.direction || "up", 3022 distance = options.distance, 3023 times = options.times || 5, 3024 3025 // Number of internal animations 3026 anims = times * 2 + (show || hide ? 1 : 0), 3027 speed = options.duration / anims, 3028 easing = options.easing, 3029 3030 // Utility: 3031 ref = (direction === "up" || direction === "down") ? "top" : "left", 3032 motion = (direction === "up" || direction === "left"), 3033 i = 0, 3034 3035 queuelen = element.queue().length; 3036 3037 $.effects.createPlaceholder(element); 3038 3039 refValue = element.css(ref); 3040 3041 // Default distance for the BIGGEST bounce is the outer Distance / 3 3042 if (!distance) { 3043 distance = element[ref === "top" ? "outerHeight" : "outerWidth"]() / 3; 3044 } 3045 3046 if (show) { 3047 downAnim = { opacity: 1 }; 3048 downAnim[ref] = refValue; 3049 3050 // If we are showing, force opacity 0 and set the initial position 3051 // then do the "first" animation 3052 element 3053 .css("opacity", 0) 3054 .css(ref, motion ? -distance * 2 : distance * 2) 3055 .animate(downAnim, speed, easing); 3056 } 3057 3058 // Start at the smallest distance if we are hiding 3059 if (hide) { 3060 distance = distance / Math.pow(2, times - 1); 3061 } 3062 3063 downAnim = {}; 3064 downAnim[ref] = refValue; 3065 3066 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here 3067 for (; i < times; i++) { 3068 upAnim = {}; 3069 upAnim[ref] = (motion ? "-=" : "+=") + distance; 3070 3071 element 3072 .animate(upAnim, speed, easing) 3073 .animate(downAnim, speed, easing); 3074 3075 distance = hide ? distance * 2 : distance / 2; 3076 } 3077 3078 // Last Bounce when Hiding 3079 if (hide) { 3080 upAnim = { opacity: 0 }; 3081 upAnim[ref] = (motion ? "-=" : "+=") + distance; 3082 3083 element.animate(upAnim, speed, easing); 3084 } 3085 3086 element.queue(done); 3087 3088 $.effects.unshift(element, queuelen, anims + 1); 3089 }); 3090 3091 3092 /*! 3093 * jQuery UI Effects Clip 1.14.1 3094 * https://jqueryui.com 3095 * 3096 * Copyright OpenJS Foundation and other contributors 3097 * Released under the MIT license. 3098 * https://jquery.org/license 3099 */ 3100 3101 //>>label: Clip Effect 3102 //>>group: Effects 3103 //>>description: Clips the element on and off like an old TV. 3104 //>>docs: https://api.jqueryui.com/clip-effect/ 3105 //>>demos: https://jqueryui.com/effect/ 3106 3107 3108 var effectsEffectClip = $.effects.define("clip", "hide", function (options, done) { 3109 var start, 3110 animate = {}, 3111 element = $(this), 3112 direction = options.direction || "vertical", 3113 both = direction === "both", 3114 horizontal = both || direction === "horizontal", 3115 vertical = both || direction === "vertical"; 3116 3117 start = element.cssClip(); 3118 animate.clip = { 3119 top: vertical ? (start.bottom - start.top) / 2 : start.top, 3120 right: horizontal ? (start.right - start.left) / 2 : start.right, 3121 bottom: vertical ? (start.bottom - start.top) / 2 : start.bottom, 3122 left: horizontal ? (start.right - start.left) / 2 : start.left 3123 }; 3124 3125 $.effects.createPlaceholder(element); 3126 3127 if (options.mode === "show") { 3128 element.cssClip(animate.clip); 3129 animate.clip = start; 3130 } 3131 3132 element.animate(animate, { 3133 queue: false, 3134 duration: options.duration, 3135 easing: options.easing, 3136 complete: done 3137 }); 3138 3139 }); 3140 3141 3142 /*! 3143 * jQuery UI Effects Drop 1.14.1 3144 * https://jqueryui.com 3145 * 3146 * Copyright OpenJS Foundation and other contributors 3147 * Released under the MIT license. 3148 * https://jquery.org/license 3149 */ 3150 3151 //>>label: Drop Effect 3152 //>>group: Effects 3153 //>>description: Moves an element in one direction and hides it at the same time. 3154 //>>docs: https://api.jqueryui.com/drop-effect/ 3155 //>>demos: https://jqueryui.com/effect/ 3156 3157 3158 var effectsEffectDrop = $.effects.define("drop", "hide", function (options, done) { 3159 3160 var distance, 3161 element = $(this), 3162 mode = options.mode, 3163 show = mode === "show", 3164 direction = options.direction || "left", 3165 ref = (direction === "up" || direction === "down") ? "top" : "left", 3166 motion = (direction === "up" || direction === "left") ? "-=" : "+=", 3167 oppositeMotion = (motion === "+=") ? "-=" : "+=", 3168 animation = { 3169 opacity: 0 3170 }; 3171 3172 $.effects.createPlaceholder(element); 3173 3174 distance = options.distance || 3175 element[ref === "top" ? "outerHeight" : "outerWidth"](true) / 2; 3176 3177 animation[ref] = motion + distance; 3178 3179 if (show) { 3180 element.css(animation); 3181 3182 animation[ref] = oppositeMotion + distance; 3183 animation.opacity = 1; 3184 } 3185 3186 // Animate 3187 element.animate(animation, { 3188 queue: false, 3189 duration: options.duration, 3190 easing: options.easing, 3191 complete: done 3192 }); 3193 }); 3194 3195 3196 /*! 3197 * jQuery UI Effects Explode 1.14.1 3198 * https://jqueryui.com 3199 * 3200 * Copyright OpenJS Foundation and other contributors 3201 * Released under the MIT license. 3202 * https://jquery.org/license 3203 */ 3204 3205 //>>label: Explode Effect 3206 //>>group: Effects 3207 /* eslint-disable max-len */ 3208 //>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness. 3209 /* eslint-enable max-len */ 3210 //>>docs: https://api.jqueryui.com/explode-effect/ 3211 //>>demos: https://jqueryui.com/effect/ 3212 3213 3214 var effectsEffectExplode = $.effects.define("explode", "hide", function (options, done) { 3215 3216 var i, j, left, top, mx, my, 3217 rows = options.pieces ? Math.round(Math.sqrt(options.pieces)) : 3, 3218 cells = rows, 3219 element = $(this), 3220 mode = options.mode, 3221 show = mode === "show", 3222 3223 // Show and then visibility:hidden the element before calculating offset 3224 offset = element.show().css("visibility", "hidden").offset(), 3225 3226 // Width and height of a piece 3227 width = Math.ceil(element.outerWidth() / cells), 3228 height = Math.ceil(element.outerHeight() / rows), 3229 pieces = []; 3230 3231 // Children animate complete: 3232 function childComplete() { 3233 pieces.push(this); 3234 if (pieces.length === rows * cells) { 3235 animComplete(); 3236 } 3237 } 3238 3239 // Clone the element for each row and cell. 3240 for (i = 0; i < rows; i++) { // ===> 3241 top = offset.top + i * height; 3242 my = i - (rows - 1) / 2; 3243 3244 for (j = 0; j < cells; j++) { // ||| 3245 left = offset.left + j * width; 3246 mx = j - (cells - 1) / 2; 3247 3248 // Create a clone of the now hidden main element that will be absolute positioned 3249 // within a wrapper div off the -left and -top equal to size of our pieces 3250 element 3251 .clone() 3252 .appendTo("body") 3253 .wrap("<div></div>") 3254 .css({ 3255 position: "absolute", 3256 visibility: "visible", 3257 left: -j * width, 3258 top: -i * height 3259 }) 3260 3261 // Select the wrapper - make it overflow: hidden and absolute positioned based on 3262 // where the original was located +left and +top equal to the size of pieces 3263 .parent() 3264 .addClass("ui-effects-explode") 3265 .css({ 3266 position: "absolute", 3267 overflow: "hidden", 3268 width: width, 3269 height: height, 3270 left: left + (show ? mx * width : 0), 3271 top: top + (show ? my * height : 0), 3272 opacity: show ? 0 : 1 3273 }) 3274 .animate({ 3275 left: left + (show ? 0 : mx * width), 3276 top: top + (show ? 0 : my * height), 3277 opacity: show ? 1 : 0 3278 }, options.duration || 500, options.easing, childComplete); 3279 } 3280 } 3281 3282 function animComplete() { 3283 element.css({ 3284 visibility: "visible" 3285 }); 3286 $(pieces).remove(); 3287 done(); 3288 } 3289 }); 3290 3291 3292 /*! 3293 * jQuery UI Effects Fade 1.14.1 3294 * https://jqueryui.com 3295 * 3296 * Copyright OpenJS Foundation and other contributors 3297 * Released under the MIT license. 3298 * https://jquery.org/license 3299 */ 3300 3301 //>>label: Fade Effect 3302 //>>group: Effects 3303 //>>description: Fades the element. 3304 //>>docs: https://api.jqueryui.com/fade-effect/ 3305 //>>demos: https://jqueryui.com/effect/ 3306 3307 3308 var effectsEffectFade = $.effects.define("fade", "toggle", function (options, done) { 3309 var show = options.mode === "show"; 3310 3311 $(this) 3312 .css("opacity", show ? 0 : 1) 3313 .animate({ 3314 opacity: show ? 1 : 0 3315 }, { 3316 queue: false, 3317 duration: options.duration, 3318 easing: options.easing, 3319 complete: done 3320 }); 3321 }); 3322 3323 3324 /*! 3325 * jQuery UI Effects Fold 1.14.1 3326 * https://jqueryui.com 3327 * 3328 * Copyright OpenJS Foundation and other contributors 3329 * Released under the MIT license. 3330 * https://jquery.org/license 3331 */ 3332 3333 //>>label: Fold Effect 3334 //>>group: Effects 3335 //>>description: Folds an element first horizontally and then vertically. 3336 //>>docs: https://api.jqueryui.com/fold-effect/ 3337 //>>demos: https://jqueryui.com/effect/ 3338 3339 3340 var effectsEffectFold = $.effects.define("fold", "hide", function (options, done) { 3341 3342 // Create element 3343 var element = $(this), 3344 mode = options.mode, 3345 show = mode === "show", 3346 hide = mode === "hide", 3347 size = options.size || 15, 3348 percent = /([0-9]+)%/.exec(size), 3349 horizFirst = !!options.horizFirst, 3350 ref = horizFirst ? ["right", "bottom"] : ["bottom", "right"], 3351 duration = options.duration / 2, 3352 3353 placeholder = $.effects.createPlaceholder(element), 3354 3355 start = element.cssClip(), 3356 animation1 = { clip: $.extend({}, start) }, 3357 animation2 = { clip: $.extend({}, start) }, 3358 3359 distance = [start[ref[0]], start[ref[1]]], 3360 3361 queuelen = element.queue().length; 3362 3363 if (percent) { 3364 size = parseInt(percent[1], 10) / 100 * distance[hide ? 0 : 1]; 3365 } 3366 animation1.clip[ref[0]] = size; 3367 animation2.clip[ref[0]] = size; 3368 animation2.clip[ref[1]] = 0; 3369 3370 if (show) { 3371 element.cssClip(animation2.clip); 3372 if (placeholder) { 3373 placeholder.css($.effects.clipToBox(animation2)); 3374 } 3375 3376 animation2.clip = start; 3377 } 3378 3379 // Animate 3380 element 3381 .queue(function (next) { 3382 if (placeholder) { 3383 placeholder 3384 .animate($.effects.clipToBox(animation1), duration, options.easing) 3385 .animate($.effects.clipToBox(animation2), duration, options.easing); 3386 } 3387 3388 next(); 3389 }) 3390 .animate(animation1, duration, options.easing) 3391 .animate(animation2, duration, options.easing) 3392 .queue(done); 3393 3394 $.effects.unshift(element, queuelen, 4); 3395 }); 3396 3397 3398 /*! 3399 * jQuery UI Effects Highlight 1.14.1 3400 * https://jqueryui.com 3401 * 3402 * Copyright OpenJS Foundation and other contributors 3403 * Released under the MIT license. 3404 * https://jquery.org/license 3405 */ 3406 3407 //>>label: Highlight Effect 3408 //>>group: Effects 3409 //>>description: Highlights the background of an element in a defined color for a custom duration. 3410 //>>docs: https://api.jqueryui.com/highlight-effect/ 3411 //>>demos: https://jqueryui.com/effect/ 3412 3413 3414 var effectsEffectHighlight = $.effects.define("highlight", "show", function (options, done) { 3415 var element = $(this), 3416 animation = { 3417 backgroundColor: element.css("backgroundColor") 3418 }; 3419 3420 if (options.mode === "hide") { 3421 animation.opacity = 0; 3422 } 3423 3424 $.effects.saveStyle(element); 3425 3426 element 3427 .css({ 3428 backgroundImage: "none", 3429 backgroundColor: options.color || "#ffff99" 3430 }) 3431 .animate(animation, { 3432 queue: false, 3433 duration: options.duration, 3434 easing: options.easing, 3435 complete: done 3436 }); 3437 }); 3438 3439 3440 /*! 3441 * jQuery UI Effects Size 1.14.1 3442 * https://jqueryui.com 3443 * 3444 * Copyright OpenJS Foundation and other contributors 3445 * Released under the MIT license. 3446 * https://jquery.org/license 3447 */ 3448 3449 //>>label: Size Effect 3450 //>>group: Effects 3451 //>>description: Resize an element to a specified width and height. 3452 //>>docs: https://api.jqueryui.com/size-effect/ 3453 //>>demos: https://jqueryui.com/effect/ 3454 3455 3456 var effectsEffectSize = $.effects.define("size", function (options, done) { 3457 3458 // Create element 3459 var baseline, factor, temp, 3460 element = $(this), 3461 3462 // Copy for children 3463 cProps = ["fontSize"], 3464 vProps = ["borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom"], 3465 hProps = ["borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight"], 3466 3467 // Set options 3468 mode = options.mode, 3469 restore = mode !== "effect", 3470 scale = options.scale || "both", 3471 origin = options.origin || ["middle", "center"], 3472 position = element.css("position"), 3473 pos = element.position(), 3474 original = $.effects.scaledDimensions(element), 3475 from = options.from || original, 3476 to = options.to || $.effects.scaledDimensions(element, 0); 3477 3478 $.effects.createPlaceholder(element); 3479 3480 if (mode === "show") { 3481 temp = from; 3482 from = to; 3483 to = temp; 3484 } 3485 3486 // Set scaling factor 3487 factor = { 3488 from: { 3489 y: from.height / original.height, 3490 x: from.width / original.width 3491 }, 3492 to: { 3493 y: to.height / original.height, 3494 x: to.width / original.width 3495 } 3496 }; 3497 3498 // Scale the css box 3499 if (scale === "box" || scale === "both") { 3500 3501 // Vertical props scaling 3502 if (factor.from.y !== factor.to.y) { 3503 from = $.effects.setTransition(element, vProps, factor.from.y, from); 3504 to = $.effects.setTransition(element, vProps, factor.to.y, to); 3505 } 3506 3507 // Horizontal props scaling 3508 if (factor.from.x !== factor.to.x) { 3509 from = $.effects.setTransition(element, hProps, factor.from.x, from); 3510 to = $.effects.setTransition(element, hProps, factor.to.x, to); 3511 } 3512 } 3513 3514 // Scale the content 3515 if (scale === "content" || scale === "both") { 3516 3517 // Vertical props scaling 3518 if (factor.from.y !== factor.to.y) { 3519 from = $.effects.setTransition(element, cProps, factor.from.y, from); 3520 to = $.effects.setTransition(element, cProps, factor.to.y, to); 3521 } 3522 } 3523 3524 // Adjust the position properties based on the provided origin points 3525 if (origin) { 3526 baseline = $.effects.getBaseline(origin, original); 3527 from.top = (original.outerHeight - from.outerHeight) * baseline.y + pos.top; 3528 from.left = (original.outerWidth - from.outerWidth) * baseline.x + pos.left; 3529 to.top = (original.outerHeight - to.outerHeight) * baseline.y + pos.top; 3530 to.left = (original.outerWidth - to.outerWidth) * baseline.x + pos.left; 3531 } 3532 delete from.outerHeight; 3533 delete from.outerWidth; 3534 element.css(from); 3535 3536 // Animate the children if desired 3537 if (scale === "content" || scale === "both") { 3538 3539 vProps = vProps.concat(["marginTop", "marginBottom"]).concat(cProps); 3540 hProps = hProps.concat(["marginLeft", "marginRight"]); 3541 3542 // Only animate children with width attributes specified 3543 // TODO: is this right? should we include anything with css width specified as well 3544 element.find("*[width]").each(function () { 3545 var child = $(this), 3546 childOriginal = $.effects.scaledDimensions(child), 3547 childFrom = { 3548 height: childOriginal.height * factor.from.y, 3549 width: childOriginal.width * factor.from.x, 3550 outerHeight: childOriginal.outerHeight * factor.from.y, 3551 outerWidth: childOriginal.outerWidth * factor.from.x 3552 }, 3553 childTo = { 3554 height: childOriginal.height * factor.to.y, 3555 width: childOriginal.width * factor.to.x, 3556 outerHeight: childOriginal.height * factor.to.y, 3557 outerWidth: childOriginal.width * factor.to.x 3558 }; 3559 3560 // Vertical props scaling 3561 if (factor.from.y !== factor.to.y) { 3562 childFrom = $.effects.setTransition(child, vProps, factor.from.y, childFrom); 3563 childTo = $.effects.setTransition(child, vProps, factor.to.y, childTo); 3564 } 3565 3566 // Horizontal props scaling 3567 if (factor.from.x !== factor.to.x) { 3568 childFrom = $.effects.setTransition(child, hProps, factor.from.x, childFrom); 3569 childTo = $.effects.setTransition(child, hProps, factor.to.x, childTo); 3570 } 3571 3572 if (restore) { 3573 $.effects.saveStyle(child); 3574 } 3575 3576 // Animate children 3577 child.css(childFrom); 3578 child.animate(childTo, options.duration, options.easing, function () { 3579 3580 // Restore children 3581 if (restore) { 3582 $.effects.restoreStyle(child); 3583 } 3584 }); 3585 }); 3586 } 3587 3588 // Animate 3589 element.animate(to, { 3590 queue: false, 3591 duration: options.duration, 3592 easing: options.easing, 3593 complete: function () { 3594 3595 var offset = element.offset(); 3596 3597 if (to.opacity === 0) { 3598 element.css("opacity", from.opacity); 3599 } 3600 3601 if (!restore) { 3602 element 3603 .css("position", position === "static" ? "relative" : position) 3604 .offset(offset); 3605 3606 // Need to save style here so that automatic style restoration 3607 // doesn't restore to the original styles from before the animation. 3608 $.effects.saveStyle(element); 3609 } 3610 3611 done(); 3612 } 3613 }); 3614 3615 }); 3616 3617 3618 /*! 3619 * jQuery UI Effects Scale 1.14.1 3620 * https://jqueryui.com 3621 * 3622 * Copyright OpenJS Foundation and other contributors 3623 * Released under the MIT license. 3624 * https://jquery.org/license 3625 */ 3626 3627 //>>label: Scale Effect 3628 //>>group: Effects 3629 //>>description: Grows or shrinks an element and its content. 3630 //>>docs: https://api.jqueryui.com/scale-effect/ 3631 //>>demos: https://jqueryui.com/effect/ 3632 3633 3634 var effectsEffectScale = $.effects.define("scale", function (options, done) { 3635 3636 // Create element 3637 var el = $(this), 3638 mode = options.mode, 3639 percent = parseInt(options.percent, 10) || 3640 (parseInt(options.percent, 10) === 0 ? 0 : (mode !== "effect" ? 0 : 100)), 3641 3642 newOptions = $.extend(true, { 3643 from: $.effects.scaledDimensions(el), 3644 to: $.effects.scaledDimensions(el, percent, options.direction || "both"), 3645 origin: options.origin || ["middle", "center"] 3646 }, options); 3647 3648 // Fade option to support puff 3649 if (options.fade) { 3650 newOptions.from.opacity = 1; 3651 newOptions.to.opacity = 0; 3652 } 3653 3654 $.effects.effect.size.call(this, newOptions, done); 3655 }); 3656 3657 3658 /*! 3659 * jQuery UI Effects Puff 1.14.1 3660 * https://jqueryui.com 3661 * 3662 * Copyright OpenJS Foundation and other contributors 3663 * Released under the MIT license. 3664 * https://jquery.org/license 3665 */ 3666 3667 //>>label: Puff Effect 3668 //>>group: Effects 3669 //>>description: Creates a puff effect by scaling the element up and hiding it at the same time. 3670 //>>docs: https://api.jqueryui.com/puff-effect/ 3671 //>>demos: https://jqueryui.com/effect/ 3672 3673 3674 var effectsEffectPuff = $.effects.define("puff", "hide", function (options, done) { 3675 var newOptions = $.extend(true, {}, options, { 3676 fade: true, 3677 percent: parseInt(options.percent, 10) || 150 3678 }); 3679 3680 $.effects.effect.scale.call(this, newOptions, done); 3681 }); 3682 3683 3684 /*! 3685 * jQuery UI Effects Pulsate 1.14.1 3686 * https://jqueryui.com 3687 * 3688 * Copyright OpenJS Foundation and other contributors 3689 * Released under the MIT license. 3690 * https://jquery.org/license 3691 */ 3692 3693 //>>label: Pulsate Effect 3694 //>>group: Effects 3695 //>>description: Pulsates an element n times by changing the opacity to zero and back. 3696 //>>docs: https://api.jqueryui.com/pulsate-effect/ 3697 //>>demos: https://jqueryui.com/effect/ 3698 3699 3700 var effectsEffectPulsate = $.effects.define("pulsate", "show", function (options, done) { 3701 var element = $(this), 3702 mode = options.mode, 3703 show = mode === "show", 3704 hide = mode === "hide", 3705 showhide = show || hide, 3706 3707 // Showing or hiding leaves off the "last" animation 3708 anims = ((options.times || 5) * 2) + (showhide ? 1 : 0), 3709 duration = options.duration / anims, 3710 animateTo = 0, 3711 i = 1, 3712 queuelen = element.queue().length; 3713 3714 if (show || !element.is(":visible")) { 3715 element.css("opacity", 0).show(); 3716 animateTo = 1; 3717 } 3718 3719 // Anims - 1 opacity "toggles" 3720 for (; i < anims; i++) { 3721 element.animate({ opacity: animateTo }, duration, options.easing); 3722 animateTo = 1 - animateTo; 3723 } 3724 3725 element.animate({ opacity: animateTo }, duration, options.easing); 3726 3727 element.queue(done); 3728 3729 $.effects.unshift(element, queuelen, anims + 1); 3730 }); 3731 3732 3733 /*! 3734 * jQuery UI Effects Shake 1.14.1 3735 * https://jqueryui.com 3736 * 3737 * Copyright OpenJS Foundation and other contributors 3738 * Released under the MIT license. 3739 * https://jquery.org/license 3740 */ 3741 3742 //>>label: Shake Effect 3743 //>>group: Effects 3744 //>>description: Shakes an element horizontally or vertically n times. 3745 //>>docs: https://api.jqueryui.com/shake-effect/ 3746 //>>demos: https://jqueryui.com/effect/ 3747 3748 3749 var effectsEffectShake = $.effects.define("shake", function (options, done) { 3750 3751 var i = 1, 3752 element = $(this), 3753 direction = options.direction || "left", 3754 distance = options.distance || 20, 3755 times = options.times || 3, 3756 anims = times * 2 + 1, 3757 speed = Math.round(options.duration / anims), 3758 ref = (direction === "up" || direction === "down") ? "top" : "left", 3759 positiveMotion = (direction === "up" || direction === "left"), 3760 animation = {}, 3761 animation1 = {}, 3762 animation2 = {}, 3763 3764 queuelen = element.queue().length; 3765 3766 $.effects.createPlaceholder(element); 3767 3768 // Animation 3769 animation[ref] = (positiveMotion ? "-=" : "+=") + distance; 3770 animation1[ref] = (positiveMotion ? "+=" : "-=") + distance * 2; 3771 animation2[ref] = (positiveMotion ? "-=" : "+=") + distance * 2; 3772 3773 // Animate 3774 element.animate(animation, speed, options.easing); 3775 3776 // Shakes 3777 for (; i < times; i++) { 3778 element 3779 .animate(animation1, speed, options.easing) 3780 .animate(animation2, speed, options.easing); 3781 } 3782 3783 element 3784 .animate(animation1, speed, options.easing) 3785 .animate(animation, speed / 2, options.easing) 3786 .queue(done); 3787 3788 $.effects.unshift(element, queuelen, anims + 1); 3789 }); 3790 3791 3792 /*! 3793 * jQuery UI Effects Slide 1.14.1 3794 * https://jqueryui.com 3795 * 3796 * Copyright OpenJS Foundation and other contributors 3797 * Released under the MIT license. 3798 * https://jquery.org/license 3799 */ 3800 3801 //>>label: Slide Effect 3802 //>>group: Effects 3803 //>>description: Slides an element in and out of the viewport. 3804 //>>docs: https://api.jqueryui.com/slide-effect/ 3805 //>>demos: https://jqueryui.com/effect/ 3806 3807 3808 var effectsEffectSlide = $.effects.define("slide", "show", function (options, done) { 3809 var startClip, startRef, 3810 element = $(this), 3811 map = { 3812 up: ["bottom", "top"], 3813 down: ["top", "bottom"], 3814 left: ["right", "left"], 3815 right: ["left", "right"] 3816 }, 3817 mode = options.mode, 3818 direction = options.direction || "left", 3819 ref = (direction === "up" || direction === "down") ? "top" : "left", 3820 positiveMotion = (direction === "up" || direction === "left"), 3821 distance = options.distance || 3822 element[ref === "top" ? "outerHeight" : "outerWidth"](true), 3823 animation = {}; 3824 3825 $.effects.createPlaceholder(element); 3826 3827 startClip = element.cssClip(); 3828 startRef = element.position()[ref]; 3829 3830 // Define hide animation 3831 animation[ref] = (positiveMotion ? -1 : 1) * distance + startRef; 3832 animation.clip = element.cssClip(); 3833 animation.clip[map[direction][1]] = animation.clip[map[direction][0]]; 3834 3835 // Reverse the animation if we're showing 3836 if (mode === "show") { 3837 element.cssClip(animation.clip); 3838 element.css(ref, animation[ref]); 3839 animation.clip = startClip; 3840 animation[ref] = startRef; 3841 } 3842 3843 // Actually animate 3844 element.animate(animation, { 3845 queue: false, 3846 duration: options.duration, 3847 easing: options.easing, 3848 complete: done 3849 }); 3850 }); 3851 3852 3853 /*! 3854 * jQuery UI Effects Transfer 1.14.1 3855 * https://jqueryui.com 3856 * 3857 * Copyright OpenJS Foundation and other contributors 3858 * Released under the MIT license. 3859 * https://jquery.org/license 3860 */ 3861 3862 //>>label: Transfer Effect 3863 //>>group: Effects 3864 //>>description: Displays a transfer effect from one element to another. 3865 //>>docs: https://api.jqueryui.com/transfer-effect/ 3866 //>>demos: https://jqueryui.com/effect/ 3867 3868 3869 var effect; 3870 if ($.uiBackCompat === true) { 3871 effect = $.effects.define("transfer", function (options, done) { 3872 $(this).transfer(options, done); 3873 }); 3874 } 3875 var effectsEffectTransfer = effect; 3876 3877 3878 /*! 3879 * jQuery UI Focusable 1.14.1 3880 * https://jqueryui.com 3881 * 3882 * Copyright OpenJS Foundation and other contributors 3883 * Released under the MIT license. 3884 * https://jquery.org/license 3885 */ 3886 3887 //>>label: :focusable Selector 3888 //>>group: Core 3889 //>>description: Selects elements which can be focused. 3890 //>>docs: https://api.jqueryui.com/focusable-selector/ 3891 3892 3893 // Selectors 3894 $.ui.focusable = function (element, hasTabindex) { 3895 var map, mapName, img, focusableIfVisible, fieldset, 3896 nodeName = element.nodeName.toLowerCase(); 3897 3898 if ("area" === nodeName) { 3899 map = element.parentNode; 3900 mapName = map.name; 3901 if (!element.href || !mapName || map.nodeName.toLowerCase() !== "map") { 3902 return false; 3903 } 3904 img = $("img[usemap='#" + mapName + "']"); 3905 return img.length > 0 && img.is(":visible"); 3906 } 3907 3908 if (/^(input|select|textarea|button|object)$/.test(nodeName)) { 3909 focusableIfVisible = !element.disabled; 3910 3911 if (focusableIfVisible) { 3912 3913 // Form controls within a disabled fieldset are disabled. 3914 // However, controls within the fieldset's legend do not get disabled. 3915 // Since controls generally aren't placed inside legends, we skip 3916 // this portion of the check. 3917 fieldset = $(element).closest("fieldset")[0]; 3918 if (fieldset) { 3919 focusableIfVisible = !fieldset.disabled; 3920 } 3921 } 3922 } else if ("a" === nodeName) { 3923 focusableIfVisible = element.href || hasTabindex; 3924 } else { 3925 focusableIfVisible = hasTabindex; 3926 } 3927 3928 return focusableIfVisible && $(element).is(":visible") && 3929 $(element).css("visibility") === "visible"; 3930 }; 3931 3932 $.extend($.expr.pseudos, { 3933 focusable: function (element) { 3934 return $.ui.focusable(element, $.attr(element, "tabindex") != null); 3935 } 3936 }); 3937 3938 var focusable = $.ui.focusable; 3939 3940 3941 /*! 3942 * jQuery UI Form Reset Mixin 1.14.1 3943 * https://jqueryui.com 3944 * 3945 * Copyright OpenJS Foundation and other contributors 3946 * Released under the MIT license. 3947 * https://jquery.org/license 3948 */ 3949 3950 //>>label: Form Reset Mixin 3951 //>>group: Core 3952 //>>description: Refresh input widgets when their form is reset 3953 //>>docs: https://api.jqueryui.com/form-reset-mixin/ 3954 3955 3956 var formResetMixin = $.ui.formResetMixin = { 3957 _formResetHandler: function () { 3958 var form = $(this); 3959 3960 // Wait for the form reset to actually happen before refreshing 3961 setTimeout(function () { 3962 var instances = form.data("ui-form-reset-instances"); 3963 $.each(instances, function () { 3964 this.refresh(); 3965 }); 3966 }); 3967 }, 3968 3969 _bindFormResetHandler: function () { 3970 this.form = $(this.element.prop("form")); 3971 if (!this.form.length) { 3972 return; 3973 } 3974 3975 var instances = this.form.data("ui-form-reset-instances") || []; 3976 if (!instances.length) { 3977 3978 // We don't use _on() here because we use a single event handler per form 3979 this.form.on("reset.ui-form-reset", this._formResetHandler); 3980 } 3981 instances.push(this); 3982 this.form.data("ui-form-reset-instances", instances); 3983 }, 3984 3985 _unbindFormResetHandler: function () { 3986 if (!this.form.length) { 3987 return; 3988 } 3989 3990 var instances = this.form.data("ui-form-reset-instances"); 3991 instances.splice($.inArray(this, instances), 1); 3992 if (instances.length) { 3993 this.form.data("ui-form-reset-instances", instances); 3994 } else { 3995 this.form 3996 .removeData("ui-form-reset-instances") 3997 .off("reset.ui-form-reset"); 3998 } 3999 } 4000 }; 4001 4002 4003 /*! 4004 * jQuery UI Legacy jQuery Core patches 1.14.1 4005 * https://jqueryui.com 4006 * 4007 * Copyright OpenJS Foundation and other contributors 4008 * Released under the MIT license. 4009 * https://jquery.org/license 4010 * 4011 */ 4012 4013 //>>label: Legacy jQuery Core patches 4014 //>>group: Core 4015 //>>description: Backport `.even()`, `.odd()` and `$.escapeSelector` to older jQuery Core versions (deprecated) 4016 4017 4018 // Support: jQuery 2.2.x or older. 4019 // This method has been defined in jQuery 3.0.0. 4020 // Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js 4021 if (!$.escapeSelector) { 4022 $.escapeSelector = function (id) { 4023 return CSS.escape(id + ""); 4024 }; 4025 } 4026 4027 // Support: jQuery 3.4.x or older 4028 // These methods have been defined in jQuery 3.5.0. 4029 if (!$.fn.even || !$.fn.odd) { 4030 $.fn.extend({ 4031 even: function () { 4032 return this.filter(function (i) { 4033 return i % 2 === 0; 4034 }); 4035 }, 4036 odd: function () { 4037 return this.filter(function (i) { 4038 return i % 2 === 1; 4039 }); 4040 } 4041 }); 4042 } 4043 4044 ; 4045 /*! 4046 * jQuery UI Keycode 1.14.1 4047 * https://jqueryui.com 4048 * 4049 * Copyright OpenJS Foundation and other contributors 4050 * Released under the MIT license. 4051 * https://jquery.org/license 4052 */ 4053 4054 //>>label: Keycode 4055 //>>group: Core 4056 //>>description: Provide keycodes as keynames 4057 //>>docs: https://api.jqueryui.com/jQuery.ui.keyCode/ 4058 4059 4060 var keycode = $.ui.keyCode = { 4061 BACKSPACE: 8, 4062 COMMA: 188, 4063 DELETE: 46, 4064 DOWN: 40, 4065 END: 35, 4066 ENTER: 13, 4067 ESCAPE: 27, 4068 HOME: 36, 4069 LEFT: 37, 4070 PAGE_DOWN: 34, 4071 PAGE_UP: 33, 4072 PERIOD: 190, 4073 RIGHT: 39, 4074 SPACE: 32, 4075 TAB: 9, 4076 UP: 38 4077 }; 4078 4079 4080 /*! 4081 * jQuery UI Labels 1.14.1 4082 * https://jqueryui.com 4083 * 4084 * Copyright OpenJS Foundation and other contributors 4085 * Released under the MIT license. 4086 * https://jquery.org/license 4087 */ 4088 4089 //>>label: labels 4090 //>>group: Core 4091 //>>description: Find all the labels associated with a given input 4092 //>>docs: https://api.jqueryui.com/labels/ 4093 4094 4095 var labels = $.fn.labels = function () { 4096 var ancestor, selector, id, labels, ancestors; 4097 4098 if (!this.length) { 4099 return this.pushStack([]); 4100 } 4101 4102 // Check control.labels first 4103 if (this[0].labels && this[0].labels.length) { 4104 return this.pushStack(this[0].labels); 4105 } 4106 4107 // If `control.labels` is empty - e.g. inside of document fragments - find 4108 // the labels manually 4109 labels = this.eq(0).parents("label"); 4110 4111 // Look for the label based on the id 4112 id = this.attr("id"); 4113 if (id) { 4114 4115 // We don't search against the document in case the element 4116 // is disconnected from the DOM 4117 ancestor = this.eq(0).parents().last(); 4118 4119 // Get a full set of top level ancestors 4120 ancestors = ancestor.add(ancestor.length ? ancestor.siblings() : this.siblings()); 4121 4122 // Create a selector for the label based on the id 4123 selector = "label[for='" + CSS.escape(id) + "']"; 4124 4125 labels = labels.add(ancestors.find(selector).addBack(selector)); 4126 4127 } 4128 4129 // Return whatever we have found for labels 4130 return this.pushStack(labels); 4131 }; 4132 4133 4134 /*! 4135 * jQuery UI Scroll Parent 1.14.1 4136 * https://jqueryui.com 4137 * 4138 * Copyright OpenJS Foundation and other contributors 4139 * Released under the MIT license. 4140 * https://jquery.org/license 4141 */ 4142 4143 //>>label: scrollParent 4144 //>>group: Core 4145 //>>description: Get the closest ancestor element that is scrollable. 4146 //>>docs: https://api.jqueryui.com/scrollParent/ 4147 4148 4149 var scrollParent = $.fn.scrollParent = function (includeHidden) { 4150 var position = this.css("position"), 4151 excludeStaticParent = position === "absolute", 4152 overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/, 4153 scrollParent = this.parents().filter(function () { 4154 var parent = $(this); 4155 if (excludeStaticParent && parent.css("position") === "static") { 4156 return false; 4157 } 4158 return overflowRegex.test(parent.css("overflow") + parent.css("overflow-y") + 4159 parent.css("overflow-x")); 4160 }).eq(0); 4161 4162 return position === "fixed" || !scrollParent.length ? 4163 $(this[0].ownerDocument || document) : 4164 scrollParent; 4165 }; 4166 4167 4168 /*! 4169 * jQuery UI Tabbable 1.14.1 4170 * https://jqueryui.com 4171 * 4172 * Copyright OpenJS Foundation and other contributors 4173 * Released under the MIT license. 4174 * https://jquery.org/license 4175 */ 4176 4177 //>>label: :tabbable Selector 4178 //>>group: Core 4179 //>>description: Selects elements which can be tabbed to. 4180 //>>docs: https://api.jqueryui.com/tabbable-selector/ 4181 4182 4183 var tabbable = $.extend($.expr.pseudos, { 4184 tabbable: function (element) { 4185 var tabIndex = $.attr(element, "tabindex"), 4186 hasTabindex = tabIndex != null; 4187 return (!hasTabindex || tabIndex >= 0) && $.ui.focusable(element, hasTabindex); 4188 } 4189 }); 4190 4191 4192 /*! 4193 * jQuery UI Unique ID 1.14.1 4194 * https://jqueryui.com 4195 * 4196 * Copyright OpenJS Foundation and other contributors 4197 * Released under the MIT license. 4198 * https://jquery.org/license 4199 */ 4200 4201 //>>label: uniqueId 4202 //>>group: Core 4203 //>>description: Functions to generate and remove uniqueId's 4204 //>>docs: https://api.jqueryui.com/uniqueId/ 4205 4206 4207 var uniqueId = $.fn.extend({ 4208 uniqueId: (function () { 4209 var uuid = 0; 4210 4211 return function () { 4212 return this.each(function () { 4213 if (!this.id) { 4214 this.id = "ui-id-" + (++uuid); 4215 } 4216 }); 4217 }; 4218 })(), 4219 4220 removeUniqueId: function () { 4221 return this.each(function () { 4222 if (/^ui-id-\d+$/.test(this.id)) { 4223 $(this).removeAttr("id"); 4224 } 4225 }); 4226 } 4227 }); 4228 4229 4230 /*! 4231 * jQuery UI Accordion 1.14.1 4232 * https://jqueryui.com 4233 * 4234 * Copyright OpenJS Foundation and other contributors 4235 * Released under the MIT license. 4236 * https://jquery.org/license 4237 */ 4238 4239 //>>label: Accordion 4240 //>>group: Widgets 4241 /* eslint-disable max-len */ 4242 //>>description: Displays collapsible content panels for presenting information in a limited amount of space. 4243 /* eslint-enable max-len */ 4244 //>>docs: https://api.jqueryui.com/accordion/ 4245 //>>demos: https://jqueryui.com/accordion/ 4246 //>>css.structure: ../../themes/base/core.css 4247 //>>css.structure: ../../themes/base/accordion.css 4248 //>>css.theme: ../../themes/base/theme.css 4249 4250 4251 var widgetsAccordion = $.widget("ui.accordion", { 4252 version: "1.14.1", 4253 options: { 4254 active: 0, 4255 animate: {}, 4256 classes: { 4257 "ui-accordion-header": "ui-corner-top", 4258 "ui-accordion-header-collapsed": "ui-corner-all", 4259 "ui-accordion-content": "ui-corner-bottom" 4260 }, 4261 collapsible: false, 4262 event: "click", 4263 header: function (elem) { 4264 return elem 4265 .find("> li > :first-child") 4266 .add( 4267 elem.find("> :not(li)") 4268 4269 // Support: jQuery <3.5 only 4270 // We could use `.even()` but that's unavailable in older jQuery. 4271 .filter(function (i) { 4272 return i % 2 === 0; 4273 }) 4274 ); 4275 }, 4276 heightStyle: "auto", 4277 icons: { 4278 activeHeader: "ui-icon-triangle-1-s", 4279 header: "ui-icon-triangle-1-e" 4280 }, 4281 4282 // Callbacks 4283 activate: null, 4284 beforeActivate: null 4285 }, 4286 4287 hideProps: { 4288 borderTopWidth: "hide", 4289 borderBottomWidth: "hide", 4290 paddingTop: "hide", 4291 paddingBottom: "hide", 4292 height: "hide" 4293 }, 4294 4295 showProps: { 4296 borderTopWidth: "show", 4297 borderBottomWidth: "show", 4298 paddingTop: "show", 4299 paddingBottom: "show", 4300 height: "show" 4301 }, 4302 4303 _create: function () { 4304 var options = this.options; 4305 4306 this.prevShow = this.prevHide = $(); 4307 this._addClass("ui-accordion", "ui-widget ui-helper-reset"); 4308 this.element.attr("role", "tablist"); 4309 4310 // Don't allow collapsible: false and active: false / null 4311 if (!options.collapsible && (options.active === false || options.active == null)) { 4312 options.active = 0; 4313 } 4314 4315 this._processPanels(); 4316 4317 // handle negative values 4318 if (options.active < 0) { 4319 options.active += this.headers.length; 4320 } 4321 this._refresh(); 4322 }, 4323 4324 _getCreateEventData: function () { 4325 return { 4326 header: this.active, 4327 panel: !this.active.length ? $() : this.active.next() 4328 }; 4329 }, 4330 4331 _createIcons: function () { 4332 var icon, children, 4333 icons = this.options.icons; 4334 4335 if (icons) { 4336 icon = $("<span>"); 4337 this._addClass(icon, "ui-accordion-header-icon", "ui-icon " + icons.header); 4338 icon.prependTo(this.headers); 4339 children = this.active.children(".ui-accordion-header-icon"); 4340 this._removeClass(children, icons.header) 4341 ._addClass(children, null, icons.activeHeader) 4342 ._addClass(this.headers, "ui-accordion-icons"); 4343 } 4344 }, 4345 4346 _destroyIcons: function () { 4347 this._removeClass(this.headers, "ui-accordion-icons"); 4348 this.headers.children(".ui-accordion-header-icon").remove(); 4349 }, 4350 4351 _destroy: function () { 4352 var contents; 4353 4354 // Clean up main element 4355 this.element.removeAttr("role"); 4356 4357 // Clean up headers 4358 this.headers 4359 .removeAttr("role aria-expanded aria-selected aria-controls tabIndex") 4360 .removeUniqueId(); 4361 4362 this._destroyIcons(); 4363 4364 // Clean up content panels 4365 contents = this.headers.next() 4366 .css("display", "") 4367 .removeAttr("role aria-hidden aria-labelledby") 4368 .removeUniqueId(); 4369 4370 if (this.options.heightStyle !== "content") { 4371 contents.css("height", ""); 4372 } 4373 }, 4374 4375 _setOption: function (key, value) { 4376 if (key === "active") { 4377 4378 // _activate() will handle invalid values and update this.options 4379 this._activate(value); 4380 return; 4381 } 4382 4383 if (key === "event") { 4384 if (this.options.event) { 4385 this._off(this.headers, this.options.event); 4386 } 4387 this._setupEvents(value); 4388 } 4389 4390 this._super(key, value); 4391 4392 // Setting collapsible: false while collapsed; open first panel 4393 if (key === "collapsible" && !value && this.options.active === false) { 4394 this._activate(0); 4395 } 4396 4397 if (key === "icons") { 4398 this._destroyIcons(); 4399 if (value) { 4400 this._createIcons(); 4401 } 4402 } 4403 }, 4404 4405 _setOptionDisabled: function (value) { 4406 this._super(value); 4407 4408 this.element.attr("aria-disabled", value); 4409 this._toggleClass(null, "ui-state-disabled", !!value); 4410 }, 4411 4412 _keydown: function (event) { 4413 if (event.altKey || event.ctrlKey) { 4414 return; 4415 } 4416 4417 var keyCode = $.ui.keyCode, 4418 length = this.headers.length, 4419 currentIndex = this.headers.index(event.target), 4420 toFocus = false; 4421 4422 switch (event.keyCode) { 4423 case keyCode.RIGHT: 4424 case keyCode.DOWN: 4425 toFocus = this.headers[(currentIndex + 1) % length]; 4426 break; 4427 case keyCode.LEFT: 4428 case keyCode.UP: 4429 toFocus = this.headers[(currentIndex - 1 + length) % length]; 4430 break; 4431 case keyCode.SPACE: 4432 case keyCode.ENTER: 4433 this._eventHandler(event); 4434 break; 4435 case keyCode.HOME: 4436 toFocus = this.headers[0]; 4437 break; 4438 case keyCode.END: 4439 toFocus = this.headers[length - 1]; 4440 break; 4441 } 4442 4443 if (toFocus) { 4444 $(event.target).attr("tabIndex", -1); 4445 $(toFocus).attr("tabIndex", 0); 4446 $(toFocus).trigger("focus"); 4447 event.preventDefault(); 4448 } 4449 }, 4450 4451 _panelKeyDown: function (event) { 4452 if (event.keyCode === $.ui.keyCode.UP && event.ctrlKey) { 4453 $(event.currentTarget).prev().trigger("focus"); 4454 } 4455 }, 4456 4457 refresh: function () { 4458 var options = this.options; 4459 this._processPanels(); 4460 4461 // Was collapsed or no panel 4462 if ((options.active === false && options.collapsible === true) || 4463 !this.headers.length) { 4464 options.active = false; 4465 this.active = $(); 4466 4467 // active false only when collapsible is true 4468 } else if (options.active === false) { 4469 this._activate(0); 4470 4471 // was active, but active panel is gone 4472 } else if (this.active.length && !$.contains(this.element[0], this.active[0])) { 4473 4474 // all remaining panel are disabled 4475 if (this.headers.length === this.headers.find(".ui-state-disabled").length) { 4476 options.active = false; 4477 this.active = $(); 4478 4479 // activate previous panel 4480 } else { 4481 this._activate(Math.max(0, options.active - 1)); 4482 } 4483 4484 // was active, active panel still exists 4485 } else { 4486 4487 // make sure active index is correct 4488 options.active = this.headers.index(this.active); 4489 } 4490 4491 this._destroyIcons(); 4492 4493 this._refresh(); 4494 }, 4495 4496 _processPanels: function () { 4497 var prevHeaders = this.headers, 4498 prevPanels = this.panels; 4499 4500 if (typeof this.options.header === "function") { 4501 this.headers = this.options.header(this.element); 4502 } else { 4503 this.headers = this.element.find(this.options.header); 4504 } 4505 this._addClass(this.headers, "ui-accordion-header ui-accordion-header-collapsed", 4506 "ui-state-default"); 4507 4508 this.panels = this.headers.next().filter(":not(.ui-accordion-content-active)").hide(); 4509 this._addClass(this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content"); 4510 4511 // Avoid memory leaks (#10056) 4512 if (prevPanels) { 4513 this._off(prevHeaders.not(this.headers)); 4514 this._off(prevPanels.not(this.panels)); 4515 } 4516 }, 4517 4518 _refresh: function () { 4519 var maxHeight, 4520 options = this.options, 4521 heightStyle = options.heightStyle, 4522 parent = this.element.parent(); 4523 4524 this.active = this._findActive(options.active); 4525 this._addClass(this.active, "ui-accordion-header-active", "ui-state-active") 4526 ._removeClass(this.active, "ui-accordion-header-collapsed"); 4527 this._addClass(this.active.next(), "ui-accordion-content-active"); 4528 this.active.next().show(); 4529 4530 this.headers 4531 .attr("role", "tab") 4532 .each(function () { 4533 var header = $(this), 4534 headerId = header.uniqueId().attr("id"), 4535 panel = header.next(), 4536 panelId = panel.uniqueId().attr("id"); 4537 header.attr("aria-controls", panelId); 4538 panel.attr("aria-labelledby", headerId); 4539 }) 4540 .next() 4541 .attr("role", "tabpanel"); 4542 4543 this.headers 4544 .not(this.active) 4545 .attr({ 4546 "aria-selected": "false", 4547 "aria-expanded": "false", 4548 tabIndex: -1 4549 }) 4550 .next() 4551 .attr({ 4552 "aria-hidden": "true" 4553 }) 4554 .hide(); 4555 4556 // Make sure at least one header is in the tab order 4557 if (!this.active.length) { 4558 this.headers.eq(0).attr("tabIndex", 0); 4559 } else { 4560 this.active.attr({ 4561 "aria-selected": "true", 4562 "aria-expanded": "true", 4563 tabIndex: 0 4564 }) 4565 .next() 4566 .attr({ 4567 "aria-hidden": "false" 4568 }); 4569 } 4570 4571 this._createIcons(); 4572 4573 this._setupEvents(options.event); 4574 4575 if (heightStyle === "fill") { 4576 maxHeight = parent.height(); 4577 this.element.siblings(":visible").each(function () { 4578 var elem = $(this), 4579 position = elem.css("position"); 4580 4581 if (position === "absolute" || position === "fixed") { 4582 return; 4583 } 4584 maxHeight -= elem.outerHeight(true); 4585 }); 4586 4587 this.headers.each(function () { 4588 maxHeight -= $(this).outerHeight(true); 4589 }); 4590 4591 this.headers.next() 4592 .each(function () { 4593 $(this).height(Math.max(0, maxHeight - 4594 $(this).innerHeight() + $(this).height())); 4595 }) 4596 .css("overflow", "auto"); 4597 } else if (heightStyle === "auto") { 4598 maxHeight = 0; 4599 this.headers.next() 4600 .each(function () { 4601 var isVisible = $(this).is(":visible"); 4602 if (!isVisible) { 4603 $(this).show(); 4604 } 4605 maxHeight = Math.max(maxHeight, $(this).css("height", "").height()); 4606 if (!isVisible) { 4607 $(this).hide(); 4608 } 4609 }) 4610 .height(maxHeight); 4611 } 4612 }, 4613 4614 _activate: function (index) { 4615 var active = this._findActive(index)[0]; 4616 4617 // Trying to activate the already active panel 4618 if (active === this.active[0]) { 4619 return; 4620 } 4621 4622 // Trying to collapse, simulate a click on the currently active header 4623 active = active || this.active[0]; 4624 4625 this._eventHandler({ 4626 target: active, 4627 currentTarget: active, 4628 preventDefault: $.noop 4629 }); 4630 }, 4631 4632 _findActive: function (selector) { 4633 return typeof selector === "number" ? this.headers.eq(selector) : $(); 4634 }, 4635 4636 _setupEvents: function (event) { 4637 var events = { 4638 keydown: "_keydown" 4639 }; 4640 if (event) { 4641 $.each(event.split(" "), function (index, eventName) { 4642 events[eventName] = "_eventHandler"; 4643 }); 4644 } 4645 4646 this._off(this.headers.add(this.headers.next())); 4647 this._on(this.headers, events); 4648 this._on(this.headers.next(), { keydown: "_panelKeyDown" }); 4649 this._hoverable(this.headers); 4650 this._focusable(this.headers); 4651 }, 4652 4653 _eventHandler: function (event) { 4654 var activeChildren, clickedChildren, 4655 options = this.options, 4656 active = this.active, 4657 clicked = $(event.currentTarget), 4658 clickedIsActive = clicked[0] === active[0], 4659 collapsing = clickedIsActive && options.collapsible, 4660 toShow = collapsing ? $() : clicked.next(), 4661 toHide = active.next(), 4662 eventData = { 4663 oldHeader: active, 4664 oldPanel: toHide, 4665 newHeader: collapsing ? $() : clicked, 4666 newPanel: toShow 4667 }; 4668 4669 event.preventDefault(); 4670 4671 if ( 4672 4673 // click on active header, but not collapsible 4674 (clickedIsActive && !options.collapsible) || 4675 4676 // allow canceling activation 4677 (this._trigger("beforeActivate", event, eventData) === false)) { 4678 return; 4679 } 4680 4681 options.active = collapsing ? false : this.headers.index(clicked); 4682 4683 // When the call to ._toggle() comes after the class changes 4684 // it causes a very odd bug in IE 8 (see #6720) 4685 this.active = clickedIsActive ? $() : clicked; 4686 this._toggle(eventData); 4687 4688 // Switch classes 4689 // corner classes on the previously active header stay after the animation 4690 this._removeClass(active, "ui-accordion-header-active", "ui-state-active"); 4691 if (options.icons) { 4692 activeChildren = active.children(".ui-accordion-header-icon"); 4693 this._removeClass(activeChildren, null, options.icons.activeHeader) 4694 ._addClass(activeChildren, null, options.icons.header); 4695 } 4696 4697 if (!clickedIsActive) { 4698 this._removeClass(clicked, "ui-accordion-header-collapsed") 4699 ._addClass(clicked, "ui-accordion-header-active", "ui-state-active"); 4700 if (options.icons) { 4701 clickedChildren = clicked.children(".ui-accordion-header-icon"); 4702 this._removeClass(clickedChildren, null, options.icons.header) 4703 ._addClass(clickedChildren, null, options.icons.activeHeader); 4704 } 4705 4706 this._addClass(clicked.next(), "ui-accordion-content-active"); 4707 } 4708 }, 4709 4710 _toggle: function (data) { 4711 var toShow = data.newPanel, 4712 toHide = this.prevShow.length ? this.prevShow : data.oldPanel; 4713 4714 // Handle activating a panel during the animation for another activation 4715 this.prevShow.add(this.prevHide).stop(true, true); 4716 this.prevShow = toShow; 4717 this.prevHide = toHide; 4718 4719 if (this.options.animate) { 4720 this._animate(toShow, toHide, data); 4721 } else { 4722 toHide.hide(); 4723 toShow.show(); 4724 this._toggleComplete(data); 4725 } 4726 4727 toHide.attr({ 4728 "aria-hidden": "true" 4729 }); 4730 toHide.prev().attr({ 4731 "aria-selected": "false", 4732 "aria-expanded": "false" 4733 }); 4734 4735 // if we're switching panels, remove the old header from the tab order 4736 // if we're opening from collapsed state, remove the previous header from the tab order 4737 // if we're collapsing, then keep the collapsing header in the tab order 4738 if (toShow.length && toHide.length) { 4739 toHide.prev().attr({ 4740 "tabIndex": -1, 4741 "aria-expanded": "false" 4742 }); 4743 } else if (toShow.length) { 4744 this.headers.filter(function () { 4745 return parseInt($(this).attr("tabIndex"), 10) === 0; 4746 }) 4747 .attr("tabIndex", -1); 4748 } 4749 4750 toShow 4751 .attr("aria-hidden", "false") 4752 .prev() 4753 .attr({ 4754 "aria-selected": "true", 4755 "aria-expanded": "true", 4756 tabIndex: 0 4757 }); 4758 }, 4759 4760 _animate: function (toShow, toHide, data) { 4761 var total, easing, duration, 4762 that = this, 4763 adjust = 0, 4764 boxSizing = toShow.css("box-sizing"), 4765 down = toShow.length && 4766 (!toHide.length || (toShow.index() < toHide.index())), 4767 animate = this.options.animate || {}, 4768 options = down && animate.down || animate, 4769 complete = function () { 4770 that._toggleComplete(data); 4771 }; 4772 4773 if (typeof options === "number") { 4774 duration = options; 4775 } 4776 if (typeof options === "string") { 4777 easing = options; 4778 } 4779 4780 // fall back from options to animation in case of partial down settings 4781 easing = easing || options.easing || animate.easing; 4782 duration = duration || options.duration || animate.duration; 4783 4784 if (!toHide.length) { 4785 return toShow.animate(this.showProps, duration, easing, complete); 4786 } 4787 if (!toShow.length) { 4788 return toHide.animate(this.hideProps, duration, easing, complete); 4789 } 4790 4791 total = toShow.show().outerHeight(); 4792 toHide.animate(this.hideProps, { 4793 duration: duration, 4794 easing: easing, 4795 step: function (now, fx) { 4796 fx.now = Math.round(now); 4797 } 4798 }); 4799 toShow 4800 .hide() 4801 .animate(this.showProps, { 4802 duration: duration, 4803 easing: easing, 4804 complete: complete, 4805 step: function (now, fx) { 4806 fx.now = Math.round(now); 4807 if (fx.prop !== "height") { 4808 if (boxSizing === "content-box") { 4809 adjust += fx.now; 4810 } 4811 } else if (that.options.heightStyle !== "content") { 4812 fx.now = Math.round(total - toHide.outerHeight() - adjust); 4813 adjust = 0; 4814 } 4815 } 4816 }); 4817 }, 4818 4819 _toggleComplete: function (data) { 4820 var toHide = data.oldPanel, 4821 prev = toHide.prev(); 4822 4823 this._removeClass(toHide, "ui-accordion-content-active"); 4824 this._removeClass(prev, "ui-accordion-header-active") 4825 ._addClass(prev, "ui-accordion-header-collapsed"); 4826 4827 this._trigger("activate", null, data); 4828 } 4829 }); 4830 4831 4832 /*! 4833 * jQuery UI Menu 1.14.1 4834 * https://jqueryui.com 4835 * 4836 * Copyright OpenJS Foundation and other contributors 4837 * Released under the MIT license. 4838 * https://jquery.org/license 4839 */ 4840 4841 //>>label: Menu 4842 //>>group: Widgets 4843 //>>description: Creates nestable menus. 4844 //>>docs: https://api.jqueryui.com/menu/ 4845 //>>demos: https://jqueryui.com/menu/ 4846 //>>css.structure: ../../themes/base/core.css 4847 //>>css.structure: ../../themes/base/menu.css 4848 //>>css.theme: ../../themes/base/theme.css 4849 4850 4851 var widgetsMenu = $.widget("ui.menu", { 4852 version: "1.14.1", 4853 defaultElement: "<ul>", 4854 delay: 300, 4855 options: { 4856 icons: { 4857 submenu: "ui-icon-caret-1-e" 4858 }, 4859 items: "> *", 4860 menus: "ul", 4861 position: { 4862 my: "left top", 4863 at: "right top" 4864 }, 4865 role: "menu", 4866 4867 // Callbacks 4868 blur: null, 4869 focus: null, 4870 select: null 4871 }, 4872 4873 _create: function () { 4874 this.activeMenu = this.element; 4875 4876 // Flag used to prevent firing of the click handler 4877 // as the event bubbles up through nested menus 4878 this.mouseHandled = false; 4879 this.lastMousePosition = { x: null, y: null }; 4880 this.element 4881 .uniqueId() 4882 .attr({ 4883 role: this.options.role, 4884 tabIndex: 0 4885 }); 4886 4887 this._addClass("ui-menu", "ui-widget ui-widget-content"); 4888 this._on({ 4889 4890 // Prevent focus from sticking to links inside menu after clicking 4891 // them (focus should always stay on UL during navigation). 4892 "mousedown .ui-menu-item": function (event) { 4893 event.preventDefault(); 4894 4895 this._activateItem(event); 4896 }, 4897 "click .ui-menu-item": function (event) { 4898 var target = $(event.target); 4899 var active = $(this.document[0].activeElement); 4900 if (!this.mouseHandled && target.not(".ui-state-disabled").length) { 4901 this.select(event); 4902 4903 // Only set the mouseHandled flag if the event will bubble, see #9469. 4904 if (!event.isPropagationStopped()) { 4905 this.mouseHandled = true; 4906 } 4907 4908 // Open submenu on click 4909 if (target.has(".ui-menu").length) { 4910 this.expand(event); 4911 } else if (!this.element.is(":focus") && 4912 active.closest(".ui-menu").length) { 4913 4914 // Redirect focus to the menu 4915 this.element.trigger("focus", [true]); 4916 4917 // If the active item is on the top level, let it stay active. 4918 // Otherwise, blur the active item since it is no longer visible. 4919 if (this.active && this.active.parents(".ui-menu").length === 1) { 4920 clearTimeout(this.timer); 4921 } 4922 } 4923 } 4924 }, 4925 "mouseenter .ui-menu-item": "_activateItem", 4926 "mousemove .ui-menu-item": "_activateItem", 4927 mouseleave: "collapseAll", 4928 "mouseleave .ui-menu": "collapseAll", 4929 focus: function (event, keepActiveItem) { 4930 4931 // If there's already an active item, keep it active 4932 // If not, activate the first item 4933 var item = this.active || this._menuItems().first(); 4934 4935 if (!keepActiveItem) { 4936 this.focus(event, item); 4937 } 4938 }, 4939 blur: function (event) { 4940 this._delay(function () { 4941 var notContained = !$.contains( 4942 this.element[0], 4943 this.document[0].activeElement 4944 ); 4945 if (notContained) { 4946 this.collapseAll(event); 4947 } 4948 }); 4949 }, 4950 keydown: "_keydown" 4951 }); 4952 4953 this.refresh(); 4954 4955 // Clicks outside of a menu collapse any open menus 4956 this._on(this.document, { 4957 click: function (event) { 4958 if (this._closeOnDocumentClick(event)) { 4959 this.collapseAll(event, true); 4960 } 4961 4962 // Reset the mouseHandled flag 4963 this.mouseHandled = false; 4964 } 4965 }); 4966 }, 4967 4968 _activateItem: function (event) { 4969 4970 // Ignore mouse events while typeahead is active, see #10458. 4971 // Prevents focusing the wrong item when typeahead causes a scroll while the mouse 4972 // is over an item in the menu 4973 if (this.previousFilter) { 4974 return; 4975 } 4976 4977 // If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356) 4978 if (event.clientX === this.lastMousePosition.x && 4979 event.clientY === this.lastMousePosition.y) { 4980 return; 4981 } 4982 4983 this.lastMousePosition = { 4984 x: event.clientX, 4985 y: event.clientY 4986 }; 4987 4988 var actualTarget = $(event.target).closest(".ui-menu-item"), 4989 target = $(event.currentTarget); 4990 4991 // Ignore bubbled events on parent items, see #11641 4992 if (actualTarget[0] !== target[0]) { 4993 return; 4994 } 4995 4996 // If the item is already active, there's nothing to do 4997 if (target.is(".ui-state-active")) { 4998 return; 4999 } 5000 5001 // Remove ui-state-active class from siblings of the newly focused menu item 5002 // to avoid a jump caused by adjacent elements both having a class with a border 5003 this._removeClass(target.siblings().children(".ui-state-active"), 5004 null, "ui-state-active"); 5005 this.focus(event, target); 5006 }, 5007 5008 _destroy: function () { 5009 var items = this.element.find(".ui-menu-item") 5010 .removeAttr("role aria-disabled"), 5011 submenus = items.children(".ui-menu-item-wrapper") 5012 .removeUniqueId() 5013 .removeAttr("tabIndex role aria-haspopup"); 5014 5015 // Destroy (sub)menus 5016 this.element 5017 .removeAttr("aria-activedescendant") 5018 .find(".ui-menu").addBack() 5019 .removeAttr("role aria-labelledby aria-expanded aria-hidden aria-disabled " + 5020 "tabIndex") 5021 .removeUniqueId() 5022 .show(); 5023 5024 submenus.children().each(function () { 5025 var elem = $(this); 5026 if (elem.data("ui-menu-submenu-caret")) { 5027 elem.remove(); 5028 } 5029 }); 5030 }, 5031 5032 _keydown: function (event) { 5033 var match, prev, character, skip, 5034 preventDefault = true; 5035 5036 switch (event.keyCode) { 5037 case $.ui.keyCode.PAGE_UP: 5038 this.previousPage(event); 5039 break; 5040 case $.ui.keyCode.PAGE_DOWN: 5041 this.nextPage(event); 5042 break; 5043 case $.ui.keyCode.HOME: 5044 this._move("first", "first", event); 5045 break; 5046 case $.ui.keyCode.END: 5047 this._move("last", "last", event); 5048 break; 5049 case $.ui.keyCode.UP: 5050 this.previous(event); 5051 break; 5052 case $.ui.keyCode.DOWN: 5053 this.next(event); 5054 break; 5055 case $.ui.keyCode.LEFT: 5056 this.collapse(event); 5057 break; 5058 case $.ui.keyCode.RIGHT: 5059 if (this.active && !this.active.is(".ui-state-disabled")) { 5060 this.expand(event); 5061 } 5062 break; 5063 case $.ui.keyCode.ENTER: 5064 case $.ui.keyCode.SPACE: 5065 this._activate(event); 5066 break; 5067 case $.ui.keyCode.ESCAPE: 5068 this.collapse(event); 5069 break; 5070 default: 5071 preventDefault = false; 5072 prev = this.previousFilter || ""; 5073 skip = false; 5074 5075 // Support number pad values 5076 character = event.keyCode >= 96 && event.keyCode <= 105 ? 5077 (event.keyCode - 96).toString() : String.fromCharCode(event.keyCode); 5078 5079 clearTimeout(this.filterTimer); 5080 5081 if (character === prev) { 5082 skip = true; 5083 } else { 5084 character = prev + character; 5085 } 5086 5087 match = this._filterMenuItems(character); 5088 match = skip && match.index(this.active.next()) !== -1 ? 5089 this.active.nextAll(".ui-menu-item") : 5090 match; 5091 5092 // If no matches on the current filter, reset to the last character pressed 5093 // to move down the menu to the first item that starts with that character 5094 if (!match.length) { 5095 character = String.fromCharCode(event.keyCode); 5096 match = this._filterMenuItems(character); 5097 } 5098 5099 if (match.length) { 5100 this.focus(event, match); 5101 this.previousFilter = character; 5102 this.filterTimer = this._delay(function () { 5103 delete this.previousFilter; 5104 }, 1000); 5105 } else { 5106 delete this.previousFilter; 5107 } 5108 } 5109 5110 if (preventDefault) { 5111 event.preventDefault(); 5112 } 5113 }, 5114 5115 _activate: function (event) { 5116 if (this.active && !this.active.is(".ui-state-disabled")) { 5117 if (this.active.children("[aria-haspopup='true']").length) { 5118 this.expand(event); 5119 } else { 5120 this.select(event); 5121 } 5122 } 5123 }, 5124 5125 refresh: function () { 5126 var menus, items, newSubmenus, newItems, newWrappers, 5127 that = this, 5128 icon = this.options.icons.submenu, 5129 submenus = this.element.find(this.options.menus); 5130 5131 this._toggleClass("ui-menu-icons", null, !!this.element.find(".ui-icon").length); 5132 5133 // Initialize nested menus 5134 newSubmenus = submenus.filter(":not(.ui-menu)") 5135 .hide() 5136 .attr({ 5137 role: this.options.role, 5138 "aria-hidden": "true", 5139 "aria-expanded": "false" 5140 }) 5141 .each(function () { 5142 var menu = $(this), 5143 item = menu.prev(), 5144 submenuCaret = $("<span>").data("ui-menu-submenu-caret", true); 5145 5146 that._addClass(submenuCaret, "ui-menu-icon", "ui-icon " + icon); 5147 item 5148 .attr("aria-haspopup", "true") 5149 .prepend(submenuCaret); 5150 menu.attr("aria-labelledby", item.attr("id")); 5151 }); 5152 5153 this._addClass(newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front"); 5154 5155 menus = submenus.add(this.element); 5156 items = menus.find(this.options.items); 5157 5158 // Initialize menu-items containing spaces and/or dashes only as dividers 5159 items.not(".ui-menu-item").each(function () { 5160 var item = $(this); 5161 if (that._isDivider(item)) { 5162 that._addClass(item, "ui-menu-divider", "ui-widget-content"); 5163 } 5164 }); 5165 5166 // Don't refresh list items that are already adapted 5167 newItems = items.not(".ui-menu-item, .ui-menu-divider"); 5168 newWrappers = newItems.children() 5169 .not(".ui-menu") 5170 .uniqueId() 5171 .attr({ 5172 tabIndex: -1, 5173 role: this._itemRole() 5174 }); 5175 this._addClass(newItems, "ui-menu-item") 5176 ._addClass(newWrappers, "ui-menu-item-wrapper"); 5177 5178 // Add aria-disabled attribute to any disabled menu item 5179 items.filter(".ui-state-disabled").attr("aria-disabled", "true"); 5180 5181 // If the active item has been removed, blur the menu 5182 if (this.active && !$.contains(this.element[0], this.active[0])) { 5183 this.blur(); 5184 } 5185 }, 5186 5187 _itemRole: function () { 5188 return { 5189 menu: "menuitem", 5190 listbox: "option" 5191 }[this.options.role]; 5192 }, 5193 5194 _setOption: function (key, value) { 5195 if (key === "icons") { 5196 var icons = this.element.find(".ui-menu-icon"); 5197 this._removeClass(icons, null, this.options.icons.submenu) 5198 ._addClass(icons, null, value.submenu); 5199 } 5200 this._super(key, value); 5201 }, 5202 5203 _setOptionDisabled: function (value) { 5204 this._super(value); 5205 5206 this.element.attr("aria-disabled", String(value)); 5207 this._toggleClass(null, "ui-state-disabled", !!value); 5208 }, 5209 5210 focus: function (event, item) { 5211 var nested, focused, activeParent; 5212 this.blur(event, event && event.type === "focus"); 5213 5214 this._scrollIntoView(item); 5215 5216 this.active = item.first(); 5217 5218 focused = this.active.children(".ui-menu-item-wrapper"); 5219 this._addClass(focused, null, "ui-state-active"); 5220 5221 // Only update aria-activedescendant if there's a role 5222 // otherwise we assume focus is managed elsewhere 5223 if (this.options.role) { 5224 this.element.attr("aria-activedescendant", focused.attr("id")); 5225 } 5226 5227 // Highlight active parent menu item, if any 5228 activeParent = this.active 5229 .parent() 5230 .closest(".ui-menu-item") 5231 .children(".ui-menu-item-wrapper"); 5232 this._addClass(activeParent, null, "ui-state-active"); 5233 5234 if (event && event.type === "keydown") { 5235 this._close(); 5236 } else { 5237 this.timer = this._delay(function () { 5238 this._close(); 5239 }, this.delay); 5240 } 5241 5242 nested = item.children(".ui-menu"); 5243 if (nested.length && event && (/^mouse/.test(event.type))) { 5244 this._startOpening(nested); 5245 } 5246 this.activeMenu = item.parent(); 5247 5248 this._trigger("focus", event, { item: item }); 5249 }, 5250 5251 _scrollIntoView: function (item) { 5252 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; 5253 if (this._hasScroll()) { 5254 borderTop = parseFloat($.css(this.activeMenu[0], "borderTopWidth")) || 0; 5255 paddingTop = parseFloat($.css(this.activeMenu[0], "paddingTop")) || 0; 5256 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; 5257 scroll = this.activeMenu.scrollTop(); 5258 elementHeight = this.activeMenu.height(); 5259 itemHeight = item.outerHeight(); 5260 5261 if (offset < 0) { 5262 this.activeMenu.scrollTop(scroll + offset); 5263 } else if (offset + itemHeight > elementHeight) { 5264 this.activeMenu.scrollTop(scroll + offset - elementHeight + itemHeight); 5265 } 5266 } 5267 }, 5268 5269 blur: function (event, fromFocus) { 5270 if (!fromFocus) { 5271 clearTimeout(this.timer); 5272 } 5273 5274 if (!this.active) { 5275 return; 5276 } 5277 5278 this._removeClass(this.active.children(".ui-menu-item-wrapper"), 5279 null, "ui-state-active"); 5280 5281 this._trigger("blur", event, { item: this.active }); 5282 this.active = null; 5283 }, 5284 5285 _startOpening: function (submenu) { 5286 clearTimeout(this.timer); 5287 5288 // Don't open if already open fixes a Firefox bug that caused a .5 pixel 5289 // shift in the submenu position when mousing over the caret icon 5290 if (submenu.attr("aria-hidden") !== "true") { 5291 return; 5292 } 5293 5294 this.timer = this._delay(function () { 5295 this._close(); 5296 this._open(submenu); 5297 }, this.delay); 5298 }, 5299 5300 _open: function (submenu) { 5301 var position = $.extend({ 5302 of: this.active 5303 }, this.options.position); 5304 5305 clearTimeout(this.timer); 5306 this.element.find(".ui-menu").not(submenu.parents(".ui-menu")) 5307 .hide() 5308 .attr("aria-hidden", "true"); 5309 5310 submenu 5311 .show() 5312 .removeAttr("aria-hidden") 5313 .attr("aria-expanded", "true") 5314 .position(position); 5315 }, 5316 5317 collapseAll: function (event, all) { 5318 clearTimeout(this.timer); 5319 this.timer = this._delay(function () { 5320 5321 // If we were passed an event, look for the submenu that contains the event 5322 var currentMenu = all ? this.element : 5323 $(event && event.target).closest(this.element.find(".ui-menu")); 5324 5325 // If we found no valid submenu ancestor, use the main menu to close all 5326 // sub menus anyway 5327 if (!currentMenu.length) { 5328 currentMenu = this.element; 5329 } 5330 5331 this._close(currentMenu); 5332 5333 this.blur(event); 5334 5335 // Work around active item staying active after menu is blurred 5336 this._removeClass(currentMenu.find(".ui-state-active"), null, "ui-state-active"); 5337 5338 this.activeMenu = currentMenu; 5339 }, all ? 0 : this.delay); 5340 }, 5341 5342 // With no arguments, closes the currently active menu - if nothing is active 5343 // it closes all menus. If passed an argument, it will search for menus BELOW 5344 _close: function (startMenu) { 5345 if (!startMenu) { 5346 startMenu = this.active ? this.active.parent() : this.element; 5347 } 5348 5349 startMenu.find(".ui-menu") 5350 .hide() 5351 .attr("aria-hidden", "true") 5352 .attr("aria-expanded", "false"); 5353 }, 5354 5355 _closeOnDocumentClick: function (event) { 5356 return !$(event.target).closest(".ui-menu").length; 5357 }, 5358 5359 _isDivider: function (item) { 5360 5361 // Match hyphen, em dash, en dash 5362 return !/[^\-\u2014\u2013\s]/.test(item.text()); 5363 }, 5364 5365 collapse: function (event) { 5366 var newItem = this.active && 5367 this.active.parent().closest(".ui-menu-item", this.element); 5368 if (newItem && newItem.length) { 5369 this._close(); 5370 this.focus(event, newItem); 5371 } 5372 }, 5373 5374 expand: function (event) { 5375 var newItem = this.active && this._menuItems(this.active.children(".ui-menu")).first(); 5376 5377 if (newItem && newItem.length) { 5378 this._open(newItem.parent()); 5379 5380 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT 5381 this._delay(function () { 5382 this.focus(event, newItem); 5383 }); 5384 } 5385 }, 5386 5387 next: function (event) { 5388 this._move("next", "first", event); 5389 }, 5390 5391 previous: function (event) { 5392 this._move("prev", "last", event); 5393 }, 5394 5395 isFirstItem: function () { 5396 return this.active && !this.active.prevAll(".ui-menu-item").length; 5397 }, 5398 5399 isLastItem: function () { 5400 return this.active && !this.active.nextAll(".ui-menu-item").length; 5401 }, 5402 5403 _menuItems: function (menu) { 5404 return (menu || this.element) 5405 .find(this.options.items) 5406 .filter(".ui-menu-item"); 5407 }, 5408 5409 _move: function (direction, filter, event) { 5410 var next; 5411 if (this.active) { 5412 if (direction === "first" || direction === "last") { 5413 next = this.active 5414 [direction === "first" ? "prevAll" : "nextAll"](".ui-menu-item") 5415 .last(); 5416 } else { 5417 next = this.active 5418 [direction + "All"](".ui-menu-item") 5419 .first(); 5420 } 5421 } 5422 if (!next || !next.length || !this.active) { 5423 next = this._menuItems(this.activeMenu)[filter](); 5424 } 5425 5426 this.focus(event, next); 5427 }, 5428 5429 nextPage: function (event) { 5430 var item, base, height; 5431 5432 if (!this.active) { 5433 this.next(event); 5434 return; 5435 } 5436 if (this.isLastItem()) { 5437 return; 5438 } 5439 if (this._hasScroll()) { 5440 base = this.active.offset().top; 5441 height = this.element.innerHeight(); 5442 5443 // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back. 5444 if ($.fn.jquery.indexOf("3.2.") === 0) { 5445 height += this.element[0].offsetHeight - this.element.outerHeight(); 5446 } 5447 5448 this.active.nextAll(".ui-menu-item").each(function () { 5449 item = $(this); 5450 return item.offset().top - base - height < 0; 5451 }); 5452 5453 this.focus(event, item); 5454 } else { 5455 this.focus(event, this._menuItems(this.activeMenu) 5456 [!this.active ? "first" : "last"]()); 5457 } 5458 }, 5459 5460 previousPage: function (event) { 5461 var item, base, height; 5462 if (!this.active) { 5463 this.next(event); 5464 return; 5465 } 5466 if (this.isFirstItem()) { 5467 return; 5468 } 5469 if (this._hasScroll()) { 5470 base = this.active.offset().top; 5471 height = this.element.innerHeight(); 5472 5473 // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back. 5474 if ($.fn.jquery.indexOf("3.2.") === 0) { 5475 height += this.element[0].offsetHeight - this.element.outerHeight(); 5476 } 5477 5478 this.active.prevAll(".ui-menu-item").each(function () { 5479 item = $(this); 5480 return item.offset().top - base + height > 0; 5481 }); 5482 5483 this.focus(event, item); 5484 } else { 5485 this.focus(event, this._menuItems(this.activeMenu).first()); 5486 } 5487 }, 5488 5489 _hasScroll: function () { 5490 return this.element.outerHeight() < this.element.prop("scrollHeight"); 5491 }, 5492 5493 select: function (event) { 5494 5495 // TODO: It should never be possible to not have an active item at this 5496 // point, but the tests don't trigger mouseenter before click. 5497 this.active = this.active || $(event.target).closest(".ui-menu-item"); 5498 var ui = { item: this.active }; 5499 if (!this.active.has(".ui-menu").length) { 5500 this.collapseAll(event, true); 5501 } 5502 this._trigger("select", event, ui); 5503 }, 5504 5505 _filterMenuItems: function (character) { 5506 var escapedCharacter = character.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"), 5507 regex = new RegExp("^" + escapedCharacter, "i"); 5508 5509 return this.activeMenu 5510 .find(this.options.items) 5511 5512 // Only match on items, not dividers or other content (#10571) 5513 .filter(".ui-menu-item") 5514 .filter(function () { 5515 return regex.test( 5516 String.prototype.trim.call( 5517 $(this).children(".ui-menu-item-wrapper").text())); 5518 }); 5519 } 5520 }); 5521 5522 5523 /*! 5524 * jQuery UI Autocomplete 1.14.1 5525 * https://jqueryui.com 5526 * 5527 * Copyright OpenJS Foundation and other contributors 5528 * Released under the MIT license. 5529 * https://jquery.org/license 5530 */ 5531 5532 //>>label: Autocomplete 5533 //>>group: Widgets 5534 //>>description: Lists suggested words as the user is typing. 5535 //>>docs: https://api.jqueryui.com/autocomplete/ 5536 //>>demos: https://jqueryui.com/autocomplete/ 5537 //>>css.structure: ../../themes/base/core.css 5538 //>>css.structure: ../../themes/base/autocomplete.css 5539 //>>css.theme: ../../themes/base/theme.css 5540 5541 5542 $.widget("ui.autocomplete", { 5543 version: "1.14.1", 5544 defaultElement: "<input>", 5545 options: { 5546 appendTo: null, 5547 autoFocus: false, 5548 delay: 300, 5549 minLength: 1, 5550 position: { 5551 my: "left top", 5552 at: "left bottom", 5553 collision: "none" 5554 }, 5555 source: null, 5556 5557 // Callbacks 5558 change: null, 5559 close: null, 5560 focus: null, 5561 open: null, 5562 response: null, 5563 search: null, 5564 select: null 5565 }, 5566 5567 requestIndex: 0, 5568 pending: 0, 5569 liveRegionTimer: null, 5570 5571 _create: function () { 5572 5573 // Some browsers only repeat keydown events, not keypress events, 5574 // so we use the suppressKeyPress flag to determine if we've already 5575 // handled the keydown event. #7269 5576 // Unfortunately the code for & in keypress is the same as the up arrow, 5577 // so we use the suppressKeyPressRepeat flag to avoid handling keypress 5578 // events when we know the keydown event was used to modify the 5579 // search term. #7799 5580 var suppressKeyPress, suppressKeyPressRepeat, suppressInput, 5581 nodeName = this.element[0].nodeName.toLowerCase(), 5582 isTextarea = nodeName === "textarea", 5583 isInput = nodeName === "input"; 5584 5585 // Textareas are always multi-line 5586 // Inputs are always single-line, even if inside a contentEditable element 5587 // All other element types are determined by whether they're contentEditable 5588 this.isMultiLine = isTextarea || 5589 !isInput && this.element.prop("contentEditable") === "true"; 5590 5591 this.valueMethod = this.element[isTextarea || isInput ? "val" : "text"]; 5592 this.isNewMenu = true; 5593 5594 this._addClass("ui-autocomplete-input"); 5595 this.element.attr("autocomplete", "off"); 5596 5597 this._on(this.element, { 5598 keydown: function (event) { 5599 if (this.element.prop("readOnly")) { 5600 suppressKeyPress = true; 5601 suppressInput = true; 5602 suppressKeyPressRepeat = true; 5603 return; 5604 } 5605 5606 suppressKeyPress = false; 5607 suppressInput = false; 5608 suppressKeyPressRepeat = false; 5609 var keyCode = $.ui.keyCode; 5610 switch (event.keyCode) { 5611 case keyCode.PAGE_UP: 5612 suppressKeyPress = true; 5613 this._move("previousPage", event); 5614 break; 5615 case keyCode.PAGE_DOWN: 5616 suppressKeyPress = true; 5617 this._move("nextPage", event); 5618 break; 5619 case keyCode.UP: 5620 suppressKeyPress = true; 5621 this._keyEvent("previous", event); 5622 break; 5623 case keyCode.DOWN: 5624 suppressKeyPress = true; 5625 this._keyEvent("next", event); 5626 break; 5627 case keyCode.ENTER: 5628 5629 // when menu is open and has focus 5630 if (this.menu.active) { 5631 5632 // #6055 - Opera still allows the keypress to occur 5633 // which causes forms to submit 5634 suppressKeyPress = true; 5635 event.preventDefault(); 5636 this.menu.select(event); 5637 } 5638 break; 5639 case keyCode.TAB: 5640 if (this.menu.active) { 5641 this.menu.select(event); 5642 } 5643 break; 5644 case keyCode.ESCAPE: 5645 if (this.menu.element.is(":visible")) { 5646 if (!this.isMultiLine) { 5647 this._value(this.term); 5648 } 5649 this.close(event); 5650 5651 // Different browsers have different default behavior for escape 5652 // Single press can mean undo or clear 5653 event.preventDefault(); 5654 } 5655 break; 5656 default: 5657 suppressKeyPressRepeat = true; 5658 5659 // search timeout should be triggered before the input value is changed 5660 this._searchTimeout(event); 5661 break; 5662 } 5663 }, 5664 keypress: function (event) { 5665 if (suppressKeyPress) { 5666 suppressKeyPress = false; 5667 if (!this.isMultiLine || this.menu.element.is(":visible")) { 5668 event.preventDefault(); 5669 } 5670 return; 5671 } 5672 if (suppressKeyPressRepeat) { 5673 return; 5674 } 5675 5676 // Replicate some key handlers to allow them to repeat in Firefox and Opera 5677 var keyCode = $.ui.keyCode; 5678 switch (event.keyCode) { 5679 case keyCode.PAGE_UP: 5680 this._move("previousPage", event); 5681 break; 5682 case keyCode.PAGE_DOWN: 5683 this._move("nextPage", event); 5684 break; 5685 case keyCode.UP: 5686 this._keyEvent("previous", event); 5687 break; 5688 case keyCode.DOWN: 5689 this._keyEvent("next", event); 5690 break; 5691 } 5692 }, 5693 input: function (event) { 5694 if (suppressInput) { 5695 suppressInput = false; 5696 event.preventDefault(); 5697 return; 5698 } 5699 this._searchTimeout(event); 5700 }, 5701 focus: function () { 5702 this.selectedItem = null; 5703 this.previous = this._value(); 5704 }, 5705 blur: function (event) { 5706 clearTimeout(this.searching); 5707 this.close(event); 5708 this._change(event); 5709 } 5710 }); 5711 5712 this._initSource(); 5713 this.menu = $("<ul>") 5714 .appendTo(this._appendTo()) 5715 .menu({ 5716 5717 // disable ARIA support, the live region takes care of that 5718 role: null 5719 }) 5720 .hide() 5721 .menu("instance"); 5722 5723 this._addClass(this.menu.element, "ui-autocomplete", "ui-front"); 5724 this._on(this.menu.element, { 5725 mousedown: function (event) { 5726 5727 // Prevent moving focus out of the text field 5728 event.preventDefault(); 5729 }, 5730 menufocus: function (event, ui) { 5731 var label, item; 5732 5733 // Support: Firefox 5734 // Prevent accidental activation of menu items in Firefox (#7024 #9118) 5735 if (this.isNewMenu) { 5736 this.isNewMenu = false; 5737 if (event.originalEvent && /^mouse/.test(event.originalEvent.type)) { 5738 this.menu.blur(); 5739 5740 this.document.one("mousemove", function () { 5741 $(event.target).trigger(event.originalEvent); 5742 }); 5743 5744 return; 5745 } 5746 } 5747 5748 item = ui.item.data("ui-autocomplete-item"); 5749 if (false !== this._trigger("focus", event, { item: item })) { 5750 5751 // use value to match what will end up in the input, if it was a key event 5752 if (event.originalEvent && /^key/.test(event.originalEvent.type)) { 5753 this._value(item.value); 5754 } 5755 } 5756 5757 // Announce the value in the liveRegion 5758 label = ui.item.attr("aria-label") || item.value; 5759 if (label && String.prototype.trim.call(label).length) { 5760 clearTimeout(this.liveRegionTimer); 5761 this.liveRegionTimer = this._delay(function () { 5762 this.liveRegion.html($("<div>").text(label)); 5763 }, 100); 5764 } 5765 }, 5766 menuselect: function (event, ui) { 5767 var item = ui.item.data("ui-autocomplete-item"), 5768 previous = this.previous; 5769 5770 // Only trigger when focus was lost (click on menu) 5771 if (this.element[0] !== this.document[0].activeElement) { 5772 this.element.trigger("focus"); 5773 this.previous = previous; 5774 } 5775 5776 if (false !== this._trigger("select", event, { item: item })) { 5777 this._value(item.value); 5778 } 5779 5780 // reset the term after the select event 5781 // this allows custom select handling to work properly 5782 this.term = this._value(); 5783 5784 this.close(event); 5785 this.selectedItem = item; 5786 } 5787 }); 5788 5789 this.liveRegion = $("<div>", { 5790 role: "status", 5791 "aria-live": "assertive", 5792 "aria-relevant": "additions" 5793 }) 5794 .appendTo(this.document[0].body); 5795 5796 this._addClass(this.liveRegion, null, "ui-helper-hidden-accessible"); 5797 5798 // Turning off autocomplete prevents the browser from remembering the 5799 // value when navigating through history, so we re-enable autocomplete 5800 // if the page is unloaded before the widget is destroyed. #7790 5801 this._on(this.window, { 5802 beforeunload: function () { 5803 this.element.removeAttr("autocomplete"); 5804 } 5805 }); 5806 }, 5807 5808 _destroy: function () { 5809 clearTimeout(this.searching); 5810 this.element.removeAttr("autocomplete"); 5811 this.menu.element.remove(); 5812 this.liveRegion.remove(); 5813 }, 5814 5815 _setOption: function (key, value) { 5816 this._super(key, value); 5817 if (key === "source") { 5818 this._initSource(); 5819 } 5820 if (key === "appendTo") { 5821 this.menu.element.appendTo(this._appendTo()); 5822 } 5823 if (key === "disabled" && value && this.xhr) { 5824 this.xhr.abort(); 5825 } 5826 }, 5827 5828 _isEventTargetInWidget: function (event) { 5829 var menuElement = this.menu.element[0]; 5830 5831 return event.target === this.element[0] || 5832 event.target === menuElement || 5833 $.contains(menuElement, event.target); 5834 }, 5835 5836 _closeOnClickOutside: function (event) { 5837 if (!this._isEventTargetInWidget(event)) { 5838 this.close(); 5839 } 5840 }, 5841 5842 _appendTo: function () { 5843 var element = this.options.appendTo; 5844 5845 if (element) { 5846 element = element.jquery || element.nodeType ? 5847 $(element) : 5848 this.document.find(element).eq(0); 5849 } 5850 5851 if (!element || !element[0]) { 5852 element = this.element.closest(".ui-front, dialog"); 5853 } 5854 5855 if (!element.length) { 5856 element = this.document[0].body; 5857 } 5858 5859 return element; 5860 }, 5861 5862 _initSource: function () { 5863 var array, url, 5864 that = this; 5865 if (Array.isArray(this.options.source)) { 5866 array = this.options.source; 5867 this.source = function (request, response) { 5868 response($.ui.autocomplete.filter(array, request.term)); 5869 }; 5870 } else if (typeof this.options.source === "string") { 5871 url = this.options.source; 5872 this.source = function (request, response) { 5873 if (that.xhr) { 5874 that.xhr.abort(); 5875 } 5876 that.xhr = $.ajax({ 5877 url: url, 5878 data: request, 5879 dataType: "json", 5880 success: function (data) { 5881 response(data); 5882 }, 5883 error: function () { 5884 response([]); 5885 } 5886 }); 5887 }; 5888 } else { 5889 this.source = this.options.source; 5890 } 5891 }, 5892 5893 _searchTimeout: function (event) { 5894 clearTimeout(this.searching); 5895 this.searching = this._delay(function () { 5896 5897 // Search if the value has changed, or if the user retypes the same value (see #7434) 5898 var equalValues = this.term === this._value(), 5899 menuVisible = this.menu.element.is(":visible"), 5900 modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey; 5901 5902 if (!equalValues || (equalValues && !menuVisible && !modifierKey)) { 5903 this.selectedItem = null; 5904 this.search(null, event); 5905 } 5906 }, this.options.delay); 5907 }, 5908 5909 search: function (value, event) { 5910 value = value != null ? value : this._value(); 5911 5912 // Always save the actual value, not the one passed as an argument 5913 this.term = this._value(); 5914 5915 if (value.length < this.options.minLength) { 5916 return this.close(event); 5917 } 5918 5919 if (this._trigger("search", event) === false) { 5920 return; 5921 } 5922 5923 return this._search(value); 5924 }, 5925 5926 _search: function (value) { 5927 this.pending++; 5928 this._addClass("ui-autocomplete-loading"); 5929 this.cancelSearch = false; 5930 5931 this.source({ term: value }, this._response()); 5932 }, 5933 5934 _response: function () { 5935 var index = ++this.requestIndex; 5936 5937 return function (content) { 5938 if (index === this.requestIndex) { 5939 this.__response(content); 5940 } 5941 5942 this.pending--; 5943 if (!this.pending) { 5944 this._removeClass("ui-autocomplete-loading"); 5945 } 5946 }.bind(this); 5947 }, 5948 5949 __response: function (content) { 5950 if (content) { 5951 content = this._normalize(content); 5952 } 5953 this._trigger("response", null, { content: content }); 5954 if (!this.options.disabled && content && content.length && !this.cancelSearch) { 5955 this._suggest(content); 5956 this._trigger("open"); 5957 } else { 5958 5959 // use ._close() instead of .close() so we don't cancel future searches 5960 this._close(); 5961 } 5962 }, 5963 5964 close: function (event) { 5965 this.cancelSearch = true; 5966 this._close(event); 5967 }, 5968 5969 _close: function (event) { 5970 5971 // Remove the handler that closes the menu on outside clicks 5972 this._off(this.document, "mousedown"); 5973 5974 if (this.menu.element.is(":visible")) { 5975 this.menu.element.hide(); 5976 this.menu.blur(); 5977 this.isNewMenu = true; 5978 this._trigger("close", event); 5979 } 5980 }, 5981 5982 _change: function (event) { 5983 if (this.previous !== this._value()) { 5984 this._trigger("change", event, { item: this.selectedItem }); 5985 } 5986 }, 5987 5988 _normalize: function (items) { 5989 5990 // assume all items have the right format when the first item is complete 5991 if (items.length && items[0].label && items[0].value) { 5992 return items; 5993 } 5994 return $.map(items, function (item) { 5995 if (typeof item === "string") { 5996 return { 5997 label: item, 5998 value: item 5999 }; 6000 } 6001 return $.extend({}, item, { 6002 label: item.label || item.value, 6003 value: item.value || item.label 6004 }); 6005 }); 6006 }, 6007 6008 _suggest: function (items) { 6009 var ul = this.menu.element.empty(); 6010 this._renderMenu(ul, items); 6011 this.isNewMenu = true; 6012 this.menu.refresh(); 6013 6014 // Size and position menu 6015 ul.show(); 6016 this._resizeMenu(); 6017 ul.position($.extend({ 6018 of: this.element 6019 }, this.options.position)); 6020 6021 if (this.options.autoFocus) { 6022 this.menu.next(); 6023 } 6024 6025 // Listen for interactions outside of the widget (#6642) 6026 this._on(this.document, { 6027 mousedown: "_closeOnClickOutside" 6028 }); 6029 }, 6030 6031 _resizeMenu: function () { 6032 var ul = this.menu.element; 6033 ul.outerWidth(Math.max( 6034 6035 // Firefox wraps long text (possibly a rounding bug) 6036 // so we add 1px to avoid the wrapping (#7513) 6037 ul.width("").outerWidth() + 1, 6038 this.element.outerWidth() 6039 )); 6040 }, 6041 6042 _renderMenu: function (ul, items) { 6043 var that = this; 6044 $.each(items, function (index, item) { 6045 that._renderItemData(ul, item); 6046 }); 6047 }, 6048 6049 _renderItemData: function (ul, item) { 6050 return this._renderItem(ul, item).data("ui-autocomplete-item", item); 6051 }, 6052 6053 _renderItem: function (ul, item) { 6054 return $("<li>") 6055 .append($("<div>").text(item.label)) 6056 .appendTo(ul); 6057 }, 6058 6059 _move: function (direction, event) { 6060 if (!this.menu.element.is(":visible")) { 6061 this.search(null, event); 6062 return; 6063 } 6064 if (this.menu.isFirstItem() && /^previous/.test(direction) || 6065 this.menu.isLastItem() && /^next/.test(direction)) { 6066 6067 if (!this.isMultiLine) { 6068 this._value(this.term); 6069 } 6070 6071 this.menu.blur(); 6072 return; 6073 } 6074 this.menu[direction](event); 6075 }, 6076 6077 widget: function () { 6078 return this.menu.element; 6079 }, 6080 6081 _value: function () { 6082 return this.valueMethod.apply(this.element, arguments); 6083 }, 6084 6085 _keyEvent: function (keyEvent, event) { 6086 if (!this.isMultiLine || this.menu.element.is(":visible")) { 6087 this._move(keyEvent, event); 6088 6089 // Prevents moving cursor to beginning/end of the text field in some browsers 6090 event.preventDefault(); 6091 } 6092 } 6093 }); 6094 6095 $.extend($.ui.autocomplete, { 6096 escapeRegex: function (value) { 6097 return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); 6098 }, 6099 filter: function (array, term) { 6100 var matcher = new RegExp($.ui.autocomplete.escapeRegex(term), "i"); 6101 return $.grep(array, function (value) { 6102 return matcher.test(value.label || value.value || value); 6103 }); 6104 } 6105 }); 6106 6107 // Live region extension, adding a `messages` option 6108 // NOTE: This is an experimental API. We are still investigating 6109 // a full solution for string manipulation and internationalization. 6110 $.widget("ui.autocomplete", $.ui.autocomplete, { 6111 options: { 6112 messages: { 6113 noResults: "No search results.", 6114 results: function (amount) { 6115 return amount + (amount > 1 ? " results are" : " result is") + 6116 " available, use up and down arrow keys to navigate."; 6117 } 6118 } 6119 }, 6120 6121 __response: function (content) { 6122 var message; 6123 this._superApply(arguments); 6124 if (this.options.disabled || this.cancelSearch) { 6125 return; 6126 } 6127 if (content && content.length) { 6128 message = this.options.messages.results(content.length); 6129 } else { 6130 message = this.options.messages.noResults; 6131 } 6132 clearTimeout(this.liveRegionTimer); 6133 this.liveRegionTimer = this._delay(function () { 6134 this.liveRegion.html($("<div>").text(message)); 6135 }, 100); 6136 } 6137 }); 6138 6139 var widgetsAutocomplete = $.ui.autocomplete; 6140 6141 6142 /*! 6143 * jQuery UI Controlgroup 1.14.1 6144 * https://jqueryui.com 6145 * 6146 * Copyright OpenJS Foundation and other contributors 6147 * Released under the MIT license. 6148 * https://jquery.org/license 6149 */ 6150 6151 //>>label: Controlgroup 6152 //>>group: Widgets 6153 //>>description: Visually groups form control widgets 6154 //>>docs: https://api.jqueryui.com/controlgroup/ 6155 //>>demos: https://jqueryui.com/controlgroup/ 6156 //>>css.structure: ../../themes/base/core.css 6157 //>>css.structure: ../../themes/base/controlgroup.css 6158 //>>css.theme: ../../themes/base/theme.css 6159 6160 6161 var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g; 6162 6163 var widgetsControlgroup = $.widget("ui.controlgroup", { 6164 version: "1.14.1", 6165 defaultElement: "<div>", 6166 options: { 6167 direction: "horizontal", 6168 disabled: null, 6169 onlyVisible: true, 6170 items: { 6171 "button": "input[type=button], input[type=submit], input[type=reset], button, a", 6172 "controlgroupLabel": ".ui-controlgroup-label", 6173 "checkboxradio": "input[type='checkbox'], input[type='radio']", 6174 "selectmenu": "select", 6175 "spinner": ".ui-spinner-input" 6176 } 6177 }, 6178 6179 _create: function () { 6180 this._enhance(); 6181 }, 6182 6183 // To support the enhanced option in jQuery Mobile, we isolate DOM manipulation 6184 _enhance: function () { 6185 this.element.attr("role", "toolbar"); 6186 this.refresh(); 6187 }, 6188 6189 _destroy: function () { 6190 this._callChildMethod("destroy"); 6191 this.childWidgets.removeData("ui-controlgroup-data"); 6192 this.element.removeAttr("role"); 6193 if (this.options.items.controlgroupLabel) { 6194 this.element 6195 .find(this.options.items.controlgroupLabel) 6196 .find(".ui-controlgroup-label-contents") 6197 .contents().unwrap(); 6198 } 6199 }, 6200 6201 _initWidgets: function () { 6202 var that = this, 6203 childWidgets = []; 6204 6205 // First we iterate over each of the items options 6206 $.each(this.options.items, function (widget, selector) { 6207 var labels; 6208 var options = {}; 6209 6210 // Make sure the widget has a selector set 6211 if (!selector) { 6212 return; 6213 } 6214 6215 if (widget === "controlgroupLabel") { 6216 labels = that.element.find(selector); 6217 labels.each(function () { 6218 var element = $(this); 6219 6220 if (element.children(".ui-controlgroup-label-contents").length) { 6221 return; 6222 } 6223 element.contents() 6224 .wrapAll("<span class='ui-controlgroup-label-contents'></span>"); 6225 }); 6226 that._addClass(labels, null, "ui-widget ui-widget-content ui-state-default"); 6227 childWidgets = childWidgets.concat(labels.get()); 6228 return; 6229 } 6230 6231 // Make sure the widget actually exists 6232 if (!$.fn[widget]) { 6233 return; 6234 } 6235 6236 // We assume everything is in the middle to start because we can't determine 6237 // first / last elements until all enhancments are done. 6238 if (that["_" + widget + "Options"]) { 6239 options = that["_" + widget + "Options"]("middle"); 6240 } else { 6241 options = { classes: {} }; 6242 } 6243 6244 // Find instances of this widget inside controlgroup and init them 6245 that.element 6246 .find(selector) 6247 .each(function () { 6248 var element = $(this); 6249 var instance = element[widget]("instance"); 6250 6251 // We need to clone the default options for this type of widget to avoid 6252 // polluting the variable options which has a wider scope than a single widget. 6253 var instanceOptions = $.widget.extend({}, options); 6254 6255 // If the button is the child of a spinner ignore it 6256 // TODO: Find a more generic solution 6257 if (widget === "button" && element.parent(".ui-spinner").length) { 6258 return; 6259 } 6260 6261 // Create the widget if it doesn't exist 6262 if (!instance) { 6263 instance = element[widget]()[widget]("instance"); 6264 } 6265 if (instance) { 6266 instanceOptions.classes = 6267 that._resolveClassesValues(instanceOptions.classes, instance); 6268 } 6269 element[widget](instanceOptions); 6270 6271 // Store an instance of the controlgroup to be able to reference 6272 // from the outermost element for changing options and refresh 6273 var widgetElement = element[widget]("widget"); 6274 $.data(widgetElement[0], "ui-controlgroup-data", 6275 instance ? instance : element[widget]("instance")); 6276 6277 childWidgets.push(widgetElement[0]); 6278 }); 6279 }); 6280 6281 this.childWidgets = $($.uniqueSort(childWidgets)); 6282 this._addClass(this.childWidgets, "ui-controlgroup-item"); 6283 }, 6284 6285 _callChildMethod: function (method) { 6286 this.childWidgets.each(function () { 6287 var element = $(this), 6288 data = element.data("ui-controlgroup-data"); 6289 if (data && data[method]) { 6290 data[method](); 6291 } 6292 }); 6293 }, 6294 6295 _updateCornerClass: function (element, position) { 6296 var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all"; 6297 var add = this._buildSimpleOptions(position, "label").classes.label; 6298 6299 this._removeClass(element, null, remove); 6300 this._addClass(element, null, add); 6301 }, 6302 6303 _buildSimpleOptions: function (position, key) { 6304 var direction = this.options.direction === "vertical"; 6305 var result = { 6306 classes: {} 6307 }; 6308 result.classes[key] = { 6309 "middle": "", 6310 "first": "ui-corner-" + (direction ? "top" : "left"), 6311 "last": "ui-corner-" + (direction ? "bottom" : "right"), 6312 "only": "ui-corner-all" 6313 }[position]; 6314 6315 return result; 6316 }, 6317 6318 _spinnerOptions: function (position) { 6319 var options = this._buildSimpleOptions(position, "ui-spinner"); 6320 6321 options.classes["ui-spinner-up"] = ""; 6322 options.classes["ui-spinner-down"] = ""; 6323 6324 return options; 6325 }, 6326 6327 _buttonOptions: function (position) { 6328 return this._buildSimpleOptions(position, "ui-button"); 6329 }, 6330 6331 _checkboxradioOptions: function (position) { 6332 return this._buildSimpleOptions(position, "ui-checkboxradio-label"); 6333 }, 6334 6335 _selectmenuOptions: function (position) { 6336 var direction = this.options.direction === "vertical"; 6337 return { 6338 width: direction ? "auto" : false, 6339 classes: { 6340 middle: { 6341 "ui-selectmenu-button-open": "", 6342 "ui-selectmenu-button-closed": "" 6343 }, 6344 first: { 6345 "ui-selectmenu-button-open": "ui-corner-" + (direction ? "top" : "tl"), 6346 "ui-selectmenu-button-closed": "ui-corner-" + (direction ? "top" : "left") 6347 }, 6348 last: { 6349 "ui-selectmenu-button-open": direction ? "" : "ui-corner-tr", 6350 "ui-selectmenu-button-closed": "ui-corner-" + (direction ? "bottom" : "right") 6351 }, 6352 only: { 6353 "ui-selectmenu-button-open": "ui-corner-top", 6354 "ui-selectmenu-button-closed": "ui-corner-all" 6355 } 6356 6357 }[position] 6358 }; 6359 }, 6360 6361 _resolveClassesValues: function (classes, instance) { 6362 var result = {}; 6363 $.each(classes, function (key) { 6364 var current = instance.options.classes[key] || ""; 6365 current = String.prototype.trim.call(current.replace(controlgroupCornerRegex, "")); 6366 result[key] = (current + " " + classes[key]).replace(/\s+/g, " "); 6367 }); 6368 return result; 6369 }, 6370 6371 _setOption: function (key, value) { 6372 if (key === "direction") { 6373 this._removeClass("ui-controlgroup-" + this.options.direction); 6374 } 6375 6376 this._super(key, value); 6377 if (key === "disabled") { 6378 this._callChildMethod(value ? "disable" : "enable"); 6379 return; 6380 } 6381 6382 this.refresh(); 6383 }, 6384 6385 refresh: function () { 6386 var children, 6387 that = this; 6388 6389 this._addClass("ui-controlgroup ui-controlgroup-" + this.options.direction); 6390 6391 if (this.options.direction === "horizontal") { 6392 this._addClass(null, "ui-helper-clearfix"); 6393 } 6394 this._initWidgets(); 6395 6396 children = this.childWidgets; 6397 6398 // We filter here because we need to track all childWidgets not just the visible ones 6399 if (this.options.onlyVisible) { 6400 children = children.filter(":visible"); 6401 } 6402 6403 if (children.length) { 6404 6405 // We do this last because we need to make sure all enhancment is done 6406 // before determining first and last 6407 $.each(["first", "last"], function (index, value) { 6408 var instance = children[value]().data("ui-controlgroup-data"); 6409 6410 if (instance && that["_" + instance.widgetName + "Options"]) { 6411 var options = that["_" + instance.widgetName + "Options"]( 6412 children.length === 1 ? "only" : value 6413 ); 6414 options.classes = that._resolveClassesValues(options.classes, instance); 6415 instance.element[instance.widgetName](options); 6416 } else { 6417 that._updateCornerClass(children[value](), value); 6418 } 6419 }); 6420 6421 // Finally call the refresh method on each of the child widgets. 6422 this._callChildMethod("refresh"); 6423 } 6424 } 6425 }); 6426 6427 /*! 6428 * jQuery UI Checkboxradio 1.14.1 6429 * https://jqueryui.com 6430 * 6431 * Copyright OpenJS Foundation and other contributors 6432 * Released under the MIT license. 6433 * https://jquery.org/license 6434 */ 6435 6436 //>>label: Checkboxradio 6437 //>>group: Widgets 6438 //>>description: Enhances a form with multiple themeable checkboxes or radio buttons. 6439 //>>docs: https://api.jqueryui.com/checkboxradio/ 6440 //>>demos: https://jqueryui.com/checkboxradio/ 6441 //>>css.structure: ../../themes/base/core.css 6442 //>>css.structure: ../../themes/base/button.css 6443 //>>css.structure: ../../themes/base/checkboxradio.css 6444 //>>css.theme: ../../themes/base/theme.css 6445 6446 6447 $.widget("ui.checkboxradio", [$.ui.formResetMixin, { 6448 version: "1.14.1", 6449 options: { 6450 disabled: null, 6451 label: null, 6452 icon: true, 6453 classes: { 6454 "ui-checkboxradio-label": "ui-corner-all", 6455 "ui-checkboxradio-icon": "ui-corner-all" 6456 } 6457 }, 6458 6459 _getCreateOptions: function () { 6460 var disabled, labels, labelContents; 6461 var options = this._super() || {}; 6462 6463 // We read the type here, because it makes more sense to throw a element type error first, 6464 // rather then the error for lack of a label. Often if its the wrong type, it 6465 // won't have a label (e.g. calling on a div, btn, etc) 6466 this._readType(); 6467 6468 labels = this.element.labels(); 6469 6470 // If there are multiple labels, use the last one 6471 this.label = $(labels[labels.length - 1]); 6472 if (!this.label.length) { 6473 $.error("No label found for checkboxradio widget"); 6474 } 6475 6476 this.originalLabel = ""; 6477 6478 // We need to get the label text but this may also need to make sure it does not contain the 6479 // input itself. 6480 // The label contents could be text, html, or a mix. We wrap all elements 6481 // and read the wrapper's `innerHTML` to get a string representation of 6482 // the label, without the input as part of it. 6483 labelContents = this.label.contents().not(this.element[0]); 6484 6485 if (labelContents.length) { 6486 this.originalLabel += labelContents 6487 .clone() 6488 .wrapAll("<div></div>") 6489 .parent() 6490 .html(); 6491 } 6492 6493 // Set the label option if we found label text 6494 if (this.originalLabel) { 6495 options.label = this.originalLabel; 6496 } 6497 6498 disabled = this.element[0].disabled; 6499 if (disabled != null) { 6500 options.disabled = disabled; 6501 } 6502 return options; 6503 }, 6504 6505 _create: function () { 6506 var checked = this.element[0].checked; 6507 6508 this._bindFormResetHandler(); 6509 6510 if (this.options.disabled == null) { 6511 this.options.disabled = this.element[0].disabled; 6512 } 6513 6514 this._setOption("disabled", this.options.disabled); 6515 this._addClass("ui-checkboxradio", "ui-helper-hidden-accessible"); 6516 this._addClass(this.label, "ui-checkboxradio-label", "ui-button ui-widget"); 6517 6518 if (this.type === "radio") { 6519 this._addClass(this.label, "ui-checkboxradio-radio-label"); 6520 } 6521 6522 if (this.options.label && this.options.label !== this.originalLabel) { 6523 this._updateLabel(); 6524 } else if (this.originalLabel) { 6525 this.options.label = this.originalLabel; 6526 } 6527 6528 this._enhance(); 6529 6530 if (checked) { 6531 this._addClass(this.label, "ui-checkboxradio-checked", "ui-state-active"); 6532 } 6533 6534 this._on({ 6535 change: "_toggleClasses", 6536 focus: function () { 6537 this._addClass(this.label, null, "ui-state-focus ui-visual-focus"); 6538 }, 6539 blur: function () { 6540 this._removeClass(this.label, null, "ui-state-focus ui-visual-focus"); 6541 } 6542 }); 6543 }, 6544 6545 _readType: function () { 6546 var nodeName = this.element[0].nodeName.toLowerCase(); 6547 this.type = this.element[0].type; 6548 if (nodeName !== "input" || !/radio|checkbox/.test(this.type)) { 6549 $.error("Can't create checkboxradio on element.nodeName=" + nodeName + 6550 " and element.type=" + this.type); 6551 } 6552 }, 6553 6554 // Support jQuery Mobile enhanced option 6555 _enhance: function () { 6556 this._updateIcon(this.element[0].checked); 6557 }, 6558 6559 widget: function () { 6560 return this.label; 6561 }, 6562 6563 _getRadioGroup: function () { 6564 var group; 6565 var name = this.element[0].name; 6566 var nameSelector = "input[name='" + CSS.escape(name) + "']"; 6567 6568 if (!name) { 6569 return $([]); 6570 } 6571 6572 if (this.form.length) { 6573 group = $(this.form[0].elements).filter(nameSelector); 6574 } else { 6575 6576 // Not inside a form, check all inputs that also are not inside a form 6577 group = $(nameSelector).filter(function () { 6578 return $($(this).prop("form")).length === 0; 6579 }); 6580 } 6581 6582 return group.not(this.element); 6583 }, 6584 6585 _toggleClasses: function () { 6586 var checked = this.element[0].checked; 6587 this._toggleClass(this.label, "ui-checkboxradio-checked", "ui-state-active", checked); 6588 6589 if (this.options.icon && this.type === "checkbox") { 6590 this._toggleClass(this.icon, null, "ui-icon-check ui-state-checked", checked) 6591 ._toggleClass(this.icon, null, "ui-icon-blank", !checked); 6592 } 6593 6594 if (this.type === "radio") { 6595 this._getRadioGroup() 6596 .each(function () { 6597 var instance = $(this).checkboxradio("instance"); 6598 6599 if (instance) { 6600 instance._removeClass(instance.label, 6601 "ui-checkboxradio-checked", "ui-state-active"); 6602 } 6603 }); 6604 } 6605 }, 6606 6607 _destroy: function () { 6608 this._unbindFormResetHandler(); 6609 6610 if (this.icon) { 6611 this.icon.remove(); 6612 this.iconSpace.remove(); 6613 } 6614 }, 6615 6616 _setOption: function (key, value) { 6617 6618 // We don't allow the value to be set to nothing 6619 if (key === "label" && !value) { 6620 return; 6621 } 6622 6623 this._super(key, value); 6624 6625 if (key === "disabled") { 6626 this._toggleClass(this.label, null, "ui-state-disabled", value); 6627 this.element[0].disabled = value; 6628 6629 // Don't refresh when setting disabled 6630 return; 6631 } 6632 this.refresh(); 6633 }, 6634 6635 _updateIcon: function (checked) { 6636 var toAdd = "ui-icon ui-icon-background "; 6637 6638 if (this.options.icon) { 6639 if (!this.icon) { 6640 this.icon = $("<span>"); 6641 this.iconSpace = $("<span> </span>"); 6642 this._addClass(this.iconSpace, "ui-checkboxradio-icon-space"); 6643 } 6644 6645 if (this.type === "checkbox") { 6646 toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank"; 6647 this._removeClass(this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check"); 6648 } else { 6649 toAdd += "ui-icon-blank"; 6650 } 6651 this._addClass(this.icon, "ui-checkboxradio-icon", toAdd); 6652 if (!checked) { 6653 this._removeClass(this.icon, null, "ui-icon-check ui-state-checked"); 6654 } 6655 this.icon.prependTo(this.label).after(this.iconSpace); 6656 } else if (this.icon !== undefined) { 6657 this.icon.remove(); 6658 this.iconSpace.remove(); 6659 delete this.icon; 6660 } 6661 }, 6662 6663 _updateLabel: function () { 6664 6665 // Remove the contents of the label ( minus the icon, icon space, and input ) 6666 var contents = this.label.contents().not(this.element[0]); 6667 if (this.icon) { 6668 contents = contents.not(this.icon[0]); 6669 } 6670 if (this.iconSpace) { 6671 contents = contents.not(this.iconSpace[0]); 6672 } 6673 contents.remove(); 6674 6675 this.label.append(this.options.label); 6676 }, 6677 6678 refresh: function () { 6679 var checked = this.element[0].checked, 6680 isDisabled = this.element[0].disabled; 6681 6682 this._updateIcon(checked); 6683 this._toggleClass(this.label, "ui-checkboxradio-checked", "ui-state-active", checked); 6684 if (this.options.label !== null) { 6685 this._updateLabel(); 6686 } 6687 6688 if (isDisabled !== this.options.disabled) { 6689 this._setOptions({ "disabled": isDisabled }); 6690 } 6691 } 6692 6693 }]); 6694 6695 var widgetsCheckboxradio = $.ui.checkboxradio; 6696 6697 6698 /*! 6699 * jQuery UI Button 1.14.1 6700 * https://jqueryui.com 6701 * 6702 * Copyright OpenJS Foundation and other contributors 6703 * Released under the MIT license. 6704 * https://jquery.org/license 6705 */ 6706 6707 //>>label: Button 6708 //>>group: Widgets 6709 //>>description: Enhances a form with themeable buttons. 6710 //>>docs: https://api.jqueryui.com/button/ 6711 //>>demos: https://jqueryui.com/button/ 6712 //>>css.structure: ../../themes/base/core.css 6713 //>>css.structure: ../../themes/base/button.css 6714 //>>css.theme: ../../themes/base/theme.css 6715 6716 6717 $.widget("ui.button", { 6718 version: "1.14.1", 6719 defaultElement: "<button>", 6720 options: { 6721 classes: { 6722 "ui-button": "ui-corner-all" 6723 }, 6724 disabled: null, 6725 icon: null, 6726 iconPosition: "beginning", 6727 label: null, 6728 showLabel: true 6729 }, 6730 6731 _getCreateOptions: function () { 6732 var disabled, 6733 6734 // This is to support cases like in jQuery Mobile where the base widget does have 6735 // an implementation of _getCreateOptions 6736 options = this._super() || {}; 6737 6738 this.isInput = this.element.is("input"); 6739 6740 disabled = this.element[0].disabled; 6741 if (disabled != null) { 6742 options.disabled = disabled; 6743 } 6744 6745 this.originalLabel = this.isInput ? this.element.val() : this.element.html(); 6746 if (this.originalLabel) { 6747 options.label = this.originalLabel; 6748 } 6749 6750 return options; 6751 }, 6752 6753 _create: function () { 6754 if (!this.option.showLabel & !this.options.icon) { 6755 this.options.showLabel = true; 6756 } 6757 6758 // We have to check the option again here even though we did in _getCreateOptions, 6759 // because null may have been passed on init which would override what was set in 6760 // _getCreateOptions 6761 if (this.options.disabled == null) { 6762 this.options.disabled = this.element[0].disabled || false; 6763 } 6764 6765 this.hasTitle = !!this.element.attr("title"); 6766 6767 // Check to see if the label needs to be set or if its already correct 6768 if (this.options.label && this.options.label !== this.originalLabel) { 6769 if (this.isInput) { 6770 this.element.val(this.options.label); 6771 } else { 6772 this.element.html(this.options.label); 6773 } 6774 } 6775 this._addClass("ui-button", "ui-widget"); 6776 this._setOption("disabled", this.options.disabled); 6777 this._enhance(); 6778 6779 if (this.element.is("a")) { 6780 this._on({ 6781 "keyup": function (event) { 6782 if (event.keyCode === $.ui.keyCode.SPACE) { 6783 event.preventDefault(); 6784 6785 // If a native click is available use it, so we 6786 // actually cause navigation. Otherwise, just trigger 6787 // a click event. 6788 if (this.element[0].click) { 6789 this.element[0].click(); 6790 } else { 6791 this.element.trigger("click"); 6792 } 6793 } 6794 } 6795 }); 6796 } 6797 }, 6798 6799 _enhance: function () { 6800 if (!this.element.is("button")) { 6801 this.element.attr("role", "button"); 6802 } 6803 6804 if (this.options.icon) { 6805 this._updateIcon("icon", this.options.icon); 6806 this._updateTooltip(); 6807 } 6808 }, 6809 6810 _updateTooltip: function () { 6811 this.title = this.element.attr("title"); 6812 6813 if (!this.options.showLabel && !this.title) { 6814 this.element.attr("title", this.options.label); 6815 } 6816 }, 6817 6818 _updateIcon: function (option, value) { 6819 var icon = option !== "iconPosition", 6820 position = icon ? this.options.iconPosition : value, 6821 displayBlock = position === "top" || position === "bottom"; 6822 6823 // Create icon 6824 if (!this.icon) { 6825 this.icon = $("<span>"); 6826 6827 this._addClass(this.icon, "ui-button-icon", "ui-icon"); 6828 6829 if (!this.options.showLabel) { 6830 this._addClass("ui-button-icon-only"); 6831 } 6832 } else if (icon) { 6833 6834 // If we are updating the icon remove the old icon class 6835 this._removeClass(this.icon, null, this.options.icon); 6836 } 6837 6838 // If we are updating the icon add the new icon class 6839 if (icon) { 6840 this._addClass(this.icon, null, value); 6841 } 6842 6843 this._attachIcon(position); 6844 6845 // If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove 6846 // the iconSpace if there is one. 6847 if (displayBlock) { 6848 this._addClass(this.icon, null, "ui-widget-icon-block"); 6849 if (this.iconSpace) { 6850 this.iconSpace.remove(); 6851 } 6852 } else { 6853 6854 // Position is beginning or end so remove the ui-widget-icon-block class and add the 6855 // space if it does not exist 6856 if (!this.iconSpace) { 6857 this.iconSpace = $("<span> </span>"); 6858 this._addClass(this.iconSpace, "ui-button-icon-space"); 6859 } 6860 this._removeClass(this.icon, null, "ui-wiget-icon-block"); 6861 this._attachIconSpace(position); 6862 } 6863 }, 6864 6865 _destroy: function () { 6866 this.element.removeAttr("role"); 6867 6868 if (this.icon) { 6869 this.icon.remove(); 6870 } 6871 if (this.iconSpace) { 6872 this.iconSpace.remove(); 6873 } 6874 if (!this.hasTitle) { 6875 this.element.removeAttr("title"); 6876 } 6877 }, 6878 6879 _attachIconSpace: function (iconPosition) { 6880 this.icon[/^(?:end|bottom)/.test(iconPosition) ? "before" : "after"](this.iconSpace); 6881 }, 6882 6883 _attachIcon: function (iconPosition) { 6884 this.element[/^(?:end|bottom)/.test(iconPosition) ? "append" : "prepend"](this.icon); 6885 }, 6886 6887 _setOptions: function (options) { 6888 var newShowLabel = options.showLabel === undefined ? 6889 this.options.showLabel : 6890 options.showLabel, 6891 newIcon = options.icon === undefined ? this.options.icon : options.icon; 6892 6893 if (!newShowLabel && !newIcon) { 6894 options.showLabel = true; 6895 } 6896 this._super(options); 6897 }, 6898 6899 _setOption: function (key, value) { 6900 if (key === "icon") { 6901 if (value) { 6902 this._updateIcon(key, value); 6903 } else if (this.icon) { 6904 this.icon.remove(); 6905 if (this.iconSpace) { 6906 this.iconSpace.remove(); 6907 } 6908 } 6909 } 6910 6911 if (key === "iconPosition") { 6912 this._updateIcon(key, value); 6913 } 6914 6915 // Make sure we can't end up with a button that has neither text nor icon 6916 if (key === "showLabel") { 6917 this._toggleClass("ui-button-icon-only", null, !value); 6918 this._updateTooltip(); 6919 } 6920 6921 if (key === "label") { 6922 if (this.isInput) { 6923 this.element.val(value); 6924 } else { 6925 6926 // If there is an icon, append it, else nothing then append the value 6927 // this avoids removal of the icon when setting label text 6928 this.element.html(value); 6929 if (this.icon) { 6930 this._attachIcon(this.options.iconPosition); 6931 this._attachIconSpace(this.options.iconPosition); 6932 } 6933 } 6934 } 6935 6936 this._super(key, value); 6937 6938 if (key === "disabled") { 6939 this._toggleClass(null, "ui-state-disabled", value); 6940 this.element[0].disabled = value; 6941 if (value) { 6942 this.element.trigger("blur"); 6943 } 6944 } 6945 }, 6946 6947 refresh: function () { 6948 6949 // Make sure to only check disabled if its an element that supports this otherwise 6950 // check for the disabled class to determine state 6951 var isDisabled = this.element.is("input, button") ? 6952 this.element[0].disabled : this.element.hasClass("ui-button-disabled"); 6953 6954 if (isDisabled !== this.options.disabled) { 6955 this._setOptions({ disabled: isDisabled }); 6956 } 6957 6958 this._updateTooltip(); 6959 } 6960 }); 6961 6962 // DEPRECATED 6963 if ($.uiBackCompat === true) { 6964 6965 // Text and Icons options 6966 $.widget("ui.button", $.ui.button, { 6967 options: { 6968 text: true, 6969 icons: { 6970 primary: null, 6971 secondary: null 6972 } 6973 }, 6974 6975 _create: function () { 6976 if (this.options.showLabel && !this.options.text) { 6977 this.options.showLabel = this.options.text; 6978 } 6979 if (!this.options.showLabel && this.options.text) { 6980 this.options.text = this.options.showLabel; 6981 } 6982 if (!this.options.icon && (this.options.icons.primary || 6983 this.options.icons.secondary)) { 6984 if (this.options.icons.primary) { 6985 this.options.icon = this.options.icons.primary; 6986 } else { 6987 this.options.icon = this.options.icons.secondary; 6988 this.options.iconPosition = "end"; 6989 } 6990 } else if (this.options.icon) { 6991 this.options.icons.primary = this.options.icon; 6992 } 6993 this._super(); 6994 }, 6995 6996 _setOption: function (key, value) { 6997 if (key === "text") { 6998 this._super("showLabel", value); 6999 return; 7000 } 7001 if (key === "showLabel") { 7002 this.options.text = value; 7003 } 7004 if (key === "icon") { 7005 this.options.icons.primary = value; 7006 } 7007 if (key === "icons") { 7008 if (value.primary) { 7009 this._super("icon", value.primary); 7010 this._super("iconPosition", "beginning"); 7011 } else if (value.secondary) { 7012 this._super("icon", value.secondary); 7013 this._super("iconPosition", "end"); 7014 } 7015 } 7016 this._superApply(arguments); 7017 } 7018 }); 7019 7020 $.fn.button = (function (orig) { 7021 return function (options) { 7022 var isMethodCall = typeof options === "string"; 7023 var args = Array.prototype.slice.call(arguments, 1); 7024 var returnValue = this; 7025 7026 if (isMethodCall) { 7027 7028 // If this is an empty collection, we need to have the instance method 7029 // return undefined instead of the jQuery instance 7030 if (!this.length && options === "instance") { 7031 returnValue = undefined; 7032 } else { 7033 this.each(function () { 7034 var methodValue; 7035 var type = $(this).attr("type"); 7036 var name = type !== "checkbox" && type !== "radio" ? 7037 "button" : 7038 "checkboxradio"; 7039 var instance = $.data(this, "ui-" + name); 7040 7041 if (options === "instance") { 7042 returnValue = instance; 7043 return false; 7044 } 7045 7046 if (!instance) { 7047 return $.error("cannot call methods on button" + 7048 " prior to initialization; " + 7049 "attempted to call method '" + options + "'"); 7050 } 7051 7052 if (typeof instance[options] !== "function" || 7053 options.charAt(0) === "_") { 7054 return $.error("no such method '" + options + "' for button" + 7055 " widget instance"); 7056 } 7057 7058 methodValue = instance[options].apply(instance, args); 7059 7060 if (methodValue !== instance && methodValue !== undefined) { 7061 returnValue = methodValue && methodValue.jquery ? 7062 returnValue.pushStack(methodValue.get()) : 7063 methodValue; 7064 return false; 7065 } 7066 }); 7067 } 7068 } else { 7069 7070 // Allow multiple hashes to be passed on init 7071 if (args.length) { 7072 options = $.widget.extend.apply(null, [options].concat(args)); 7073 } 7074 7075 this.each(function () { 7076 var type = $(this).attr("type"); 7077 var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio"; 7078 var instance = $.data(this, "ui-" + name); 7079 7080 if (instance) { 7081 instance.option(options || {}); 7082 if (instance._init) { 7083 instance._init(); 7084 } 7085 } else { 7086 if (name === "button") { 7087 orig.call($(this), options); 7088 return; 7089 } 7090 7091 $(this).checkboxradio($.extend({ icon: false }, options)); 7092 } 7093 }); 7094 } 7095 7096 return returnValue; 7097 }; 7098 })($.fn.button); 7099 7100 $.fn.buttonset = function () { 7101 if (!$.ui.controlgroup) { 7102 $.error("Controlgroup widget missing"); 7103 } 7104 if (arguments[0] === "option" && arguments[1] === "items" && arguments[2]) { 7105 return this.controlgroup.apply(this, 7106 [arguments[0], "items.button", arguments[2]]); 7107 } 7108 if (arguments[0] === "option" && arguments[1] === "items") { 7109 return this.controlgroup.apply(this, [arguments[0], "items.button"]); 7110 } 7111 if (typeof arguments[0] === "object" && arguments[0].items) { 7112 arguments[0].items = { 7113 button: arguments[0].items 7114 }; 7115 } 7116 return this.controlgroup.apply(this, arguments); 7117 }; 7118 } 7119 7120 var widgetsButton = $.ui.button; 7121 7122 7123 /* eslint-disable max-len, camelcase */ 7124 /*! 7125 * jQuery UI Datepicker 1.14.1 7126 * https://jqueryui.com 7127 * 7128 * Copyright OpenJS Foundation and other contributors 7129 * Released under the MIT license. 7130 * https://jquery.org/license 7131 */ 7132 7133 //>>label: Datepicker 7134 //>>group: Widgets 7135 //>>description: Displays a calendar from an input or inline for selecting dates. 7136 //>>docs: https://api.jqueryui.com/datepicker/ 7137 //>>demos: https://jqueryui.com/datepicker/ 7138 //>>css.structure: ../../themes/base/core.css 7139 //>>css.structure: ../../themes/base/datepicker.css 7140 //>>css.theme: ../../themes/base/theme.css 7141 7142 7143 $.extend($.ui, { datepicker: { version: "1.14.1" } }); 7144 7145 var datepicker_instActive; 7146 7147 function datepicker_getZindex(elem) { 7148 var position, value; 7149 while (elem.length && elem[0] !== document) { 7150 7151 // Ignore z-index if position is set to a value where z-index is ignored by the browser 7152 // This makes behavior of this function consistent across browsers 7153 // WebKit always returns auto if the element is positioned 7154 position = elem.css("position"); 7155 if (position === "absolute" || position === "relative" || position === "fixed") { 7156 7157 // IE returns 0 when zIndex is not specified 7158 // other browsers return a string 7159 // we ignore the case of nested elements with an explicit value of 0 7160 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 7161 value = parseInt(elem.css("zIndex"), 10); 7162 if (!isNaN(value) && value !== 0) { 7163 return value; 7164 } 7165 } 7166 elem = elem.parent(); 7167 } 7168 7169 return 0; 7170 } 7171 7172 /* Date picker manager. 7173 Use the singleton instance of this class, $.datepicker, to interact with the date picker. 7174 Settings for (groups of) date pickers are maintained in an instance object, 7175 allowing multiple different settings on the same page. */ 7176 7177 function Datepicker() { 7178 this._curInst = null; // The current instance in use 7179 this._keyEvent = false; // If the last event was a key event 7180 this._disabledInputs = []; // List of date picker inputs that have been disabled 7181 this._datepickerShowing = false; // True if the popup picker is showing , false if not 7182 this._inDialog = false; // True if showing within a "dialog", false if not 7183 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division 7184 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class 7185 this._appendClass = "ui-datepicker-append"; // The name of the append marker class 7186 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class 7187 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class 7188 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class 7189 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class 7190 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class 7191 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class 7192 this.regional = []; // Available regional settings, indexed by language code 7193 this.regional[""] = { // Default regional settings 7194 closeText: "Done", // Display text for close link 7195 prevText: "Prev", // Display text for previous month link 7196 nextText: "Next", // Display text for next month link 7197 currentText: "Today", // Display text for current month link 7198 monthNames: ["January", "February", "March", "April", "May", "June",
7199 "July", "August", "September", "October", "November", "December"], // Names of months for drop-down and formatting 7200 monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting 7201 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting 7202 dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting 7203 dayNamesMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"], // Column headings for days starting at Sunday 7204 weekHeader: "Wk", // Column header for week of the year 7205 dateFormat: "mm/dd/yy", // See format options on parseDate 7206 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... 7207 isRTL: false, // True if right-to-left language, false if left-to-right 7208 showMonthAfterYear: false, // True if the year select precedes month, false for month then year 7209 yearSuffix: "", // Additional text to append to the year in the month headers, 7210 selectMonthLabel: "Select month", // Invisible label for month selector 7211 selectYearLabel: "Select year" // Invisible label for year selector 7212 }; 7213 this._defaults = { // Global defaults for all the date picker instances 7214 showOn: "focus", // "focus" for popup on focus, 7215 // "button" for trigger button, or "both" for either 7216 showAnim: "fadeIn", // Name of jQuery animation for popup 7217 showOptions: {}, // Options for enhanced animations 7218 defaultDate: null, // Used when field is blank: actual date, 7219 // +/-number for offset from today, null for today 7220 appendText: "", // Display text following the input box, e.g. showing the format 7221 buttonText: "...", // Text for trigger button 7222 buttonImage: "", // URL for trigger button image 7223 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button 7224 hideIfNoPrevNext: false, // True to hide next/previous month links 7225 // if not applicable, false to just disable them 7226 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links 7227 gotoCurrent: false, // True if today link goes back to current selection instead 7228 changeMonth: false, // True if month can be selected directly, false if only prev/next 7229 changeYear: false, // True if year can be selected directly, false if only prev/next 7230 yearRange: "c-10:c+10", // Range of years to display in drop-down, 7231 // either relative to today's year (-nn:+nn), relative to currently displayed year 7232 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) 7233 showOtherMonths: false, // True to show dates in other months, false to leave blank 7234 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable 7235 showWeek: false, // True to show week of the year, false to not show it 7236 calculateWeek: this.iso8601Week, // How to calculate the week of the year, 7237 // takes a Date and returns the number of the week for it 7238 shortYearCutoff: "+10", // Short year values < this are in the current century, 7239 // > this are in the previous century, 7240 // string value starting with "+" for current year + value 7241 minDate: null, // The earliest selectable date, or null for no limit 7242 maxDate: null, // The latest selectable date, or null for no limit 7243 duration: "fast", // Duration of display/closure 7244 beforeShowDay: null, // Function that takes a date and returns an array with 7245 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "", 7246 // [2] = cell title (optional), e.g. $.datepicker.noWeekends 7247 beforeShow: null, // Function that takes an input field and 7248 // returns a set of custom settings for the date picker 7249 onSelect: null, // Define a callback function when a date is selected 7250 onChangeMonthYear: null, // Define a callback function when the month or year is changed 7251 onClose: null, // Define a callback function when the datepicker is closed
vendor: 295,800 bytes, lines 7252-17279
7252 onUpdateDatepicker: null, // Define a callback function when the datepicker is updated 7253 numberOfMonths: 1, // Number of months to show at a time 7254 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) 7255 stepMonths: 1, // Number of months to step back/forward 7256 stepBigMonths: 12, // Number of months to step back/forward for the big links 7257 altField: "", // Selector for an alternate field to store selected dates into 7258 altFormat: "", // The date format to use for the alternate field 7259 constrainInput: true, // The input is constrained by the current date format 7260 showButtonPanel: false, // True to show button panel, false to not show it 7261 autoSize: false, // True to size the input for the date format, false to leave as is 7262 disabled: false // The initial disabled state 7263 }; 7264 $.extend(this._defaults, this.regional[""]); 7265 this.regional.en = $.extend(true, {}, this.regional[""]); 7266 this.regional["en-US"] = $.extend(true, {}, this.regional.en); 7267 this.dpDiv = datepicker_bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")); 7268 } 7269 7270 $.extend(Datepicker.prototype, { 7271 7272 /* Class name added to elements to indicate already configured with a date picker. */ 7273 markerClassName: "hasDatepicker", 7274 7275 //Keep track of the maximum number of rows displayed (see #7043) 7276 maxRows: 4, 7277 7278 // TODO rename to "widget" when switching to widget factory 7279 _widgetDatepicker: function () { 7280 return this.dpDiv; 7281 }, 7282 7283 /* Override the default settings for all instances of the date picker. 7284 * @param settings object - the new settings to use as defaults (anonymous object) 7285 * @return the manager object 7286 */ 7287 setDefaults: function (settings) { 7288 datepicker_extendRemove(this._defaults, settings || {}); 7289 return this; 7290 }, 7291 7292 /* Attach the date picker to a jQuery selection. 7293 * @param target element - the target input field or division or span 7294 * @param settings object - the new settings to use for this date picker instance (anonymous) 7295 */ 7296 _attachDatepicker: function (target, settings) { 7297 var nodeName, inline, inst; 7298 nodeName = target.nodeName.toLowerCase(); 7299 inline = (nodeName === "div" || nodeName === "span"); 7300 if (!target.id) { 7301 this.uuid += 1; 7302 target.id = "dp" + this.uuid; 7303 } 7304 inst = this._newInst($(target), inline); 7305 inst.settings = $.extend({}, settings || {}); 7306 if (nodeName === "input") { 7307 this._connectDatepicker(target, inst); 7308 } else if (inline) { 7309 this._inlineDatepicker(target, inst); 7310 } 7311 }, 7312 7313 /* Create a new instance object. */ 7314 _newInst: function (target, inline) { 7315 var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars 7316 return { 7317 id: id, input: target, // associated target 7318 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection 7319 drawMonth: 0, drawYear: 0, // month being drawn 7320 inline: inline, // is datepicker inline or not 7321 dpDiv: (!inline ? this.dpDiv : // presentation div 7322 datepicker_bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))) 7323 }; 7324 }, 7325 7326 /* Attach the date picker to an input field. */ 7327 _connectDatepicker: function (target, inst) { 7328 var input = $(target); 7329 inst.append = $([]); 7330 inst.trigger = $([]); 7331 if (input.hasClass(this.markerClassName)) { 7332 return; 7333 } 7334 this._attachments(input, inst); 7335 input.addClass(this.markerClassName).on("keydown", this._doKeyDown). 7336 on("keypress", this._doKeyPress).on("keyup", this._doKeyUp); 7337 this._autoSize(inst); 7338 $.data(target, "datepicker", inst); 7339 7340 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) 7341 if (inst.settings.disabled) { 7342 this._disableDatepicker(target); 7343 } 7344 }, 7345 7346 /* Make attachments based on settings. */ 7347 _attachments: function (input, inst) { 7348 var showOn, buttonText, buttonImage, 7349 appendText = this._get(inst, "appendText"), 7350 isRTL = this._get(inst, "isRTL"); 7351 7352 if (inst.append) { 7353 inst.append.remove(); 7354 } 7355 if (appendText) { 7356 inst.append = $("<span>") 7357 .addClass(this._appendClass) 7358 .text(appendText); 7359 input[isRTL ? "before" : "after"](inst.append); 7360 } 7361 7362 input.off("focus", this._showDatepicker); 7363 7364 if (inst.trigger) { 7365 inst.trigger.remove(); 7366 } 7367 7368 showOn = this._get(inst, "showOn"); 7369 if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field 7370 input.on("focus", this._showDatepicker); 7371 } 7372 if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked 7373 buttonText = this._get(inst, "buttonText"); 7374 buttonImage = this._get(inst, "buttonImage"); 7375 7376 if (this._get(inst, "buttonImageOnly")) { 7377 inst.trigger = $("<img>") 7378 .addClass(this._triggerClass) 7379 .attr({ 7380 src: buttonImage, 7381 alt: buttonText, 7382 title: buttonText 7383 }); 7384 } else { 7385 inst.trigger = $("<button type='button'>") 7386 .addClass(this._triggerClass); 7387 if (buttonImage) { 7388 inst.trigger.html( 7389 $("<img>") 7390 .attr({ 7391 src: buttonImage, 7392 alt: buttonText, 7393 title: buttonText 7394 }) 7395 ); 7396 } else { 7397 inst.trigger.text(buttonText); 7398 } 7399 } 7400 7401 input[isRTL ? "before" : "after"](inst.trigger); 7402 inst.trigger.on("click", function () { 7403 if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) { 7404 $.datepicker._hideDatepicker(); 7405 } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) { 7406 $.datepicker._hideDatepicker(); 7407 $.datepicker._showDatepicker(input[0]); 7408 } else { 7409 $.datepicker._showDatepicker(input[0]); 7410 } 7411 return false; 7412 }); 7413 } 7414 }, 7415 7416 /* Apply the maximum length for the date format. */ 7417 _autoSize: function (inst) { 7418 if (this._get(inst, "autoSize") && !inst.inline) { 7419 var findMax, max, maxI, i, 7420 date = new Date(2009, 12 - 1, 20), // Ensure double digits 7421 dateFormat = this._get(inst, "dateFormat"); 7422 7423 if (dateFormat.match(/[DM]/)) { 7424 findMax = function (names) { 7425 max = 0; 7426 maxI = 0; 7427 for (i = 0; i < names.length; i++) { 7428 if (names[i].length > max) { 7429 max = names[i].length; 7430 maxI = i; 7431 } 7432 } 7433 return maxI; 7434 }; 7435 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? 7436 "monthNames" : "monthNamesShort")))); 7437 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? 7438 "dayNames" : "dayNamesShort"))) + 20 - date.getDay()); 7439 } 7440 inst.input.attr("size", this._formatDate(inst, date).length); 7441 } 7442 }, 7443 7444 /* Attach an inline date picker to a div. */ 7445 _inlineDatepicker: function (target, inst) { 7446 var divSpan = $(target); 7447 if (divSpan.hasClass(this.markerClassName)) { 7448 return; 7449 } 7450 divSpan.addClass(this.markerClassName).append(inst.dpDiv); 7451 $.data(target, "datepicker", inst); 7452 this._setDate(inst, this._getDefaultDate(inst), true); 7453 this._updateDatepicker(inst); 7454 this._updateAlternate(inst); 7455 7456 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) 7457 if (inst.settings.disabled) { 7458 this._disableDatepicker(target); 7459 } 7460 7461 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements 7462 // https://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height 7463 inst.dpDiv.css("display", "block"); 7464 }, 7465 7466 /* Pop-up the date picker in a "dialog" box. 7467 * @param input element - ignored 7468 * @param date string or Date - the initial date to display 7469 * @param onSelect function - the function to call when a date is selected 7470 * @param settings object - update the dialog date picker instance's settings (anonymous object) 7471 * @param pos int[2] - coordinates for the dialog's position within the screen or 7472 * event - with x/y coordinates or 7473 * leave empty for default (screen centre) 7474 * @return the manager object 7475 */ 7476 _dialogDatepicker: function (input, date, onSelect, settings, pos) { 7477 var id, browserWidth, browserHeight, scrollX, scrollY, 7478 inst = this._dialogInst; // internal instance 7479 7480 if (!inst) { 7481 this.uuid += 1; 7482 id = "dp" + this.uuid; 7483 this._dialogInput = $("<input type='text' id='" + id + 7484 "' style='position: absolute; top: -100px; width: 0px;'/>"); 7485 this._dialogInput.on("keydown", this._doKeyDown); 7486 $("body").append(this._dialogInput); 7487 inst = this._dialogInst = this._newInst(this._dialogInput, false); 7488 inst.settings = {}; 7489 $.data(this._dialogInput[0], "datepicker", inst); 7490 } 7491 datepicker_extendRemove(inst.settings, settings || {}); 7492 date = (date && date.constructor === Date ? this._formatDate(inst, date) : date); 7493 this._dialogInput.val(date); 7494 7495 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); 7496 if (!this._pos) { 7497 browserWidth = document.documentElement.clientWidth; 7498 browserHeight = document.documentElement.clientHeight; 7499 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; 7500 scrollY = document.documentElement.scrollTop || document.body.scrollTop; 7501 this._pos = // should use actual width/height below 7502 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; 7503 } 7504 7505 // Move input on screen for focus, but hidden behind dialog 7506 this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px"); 7507 inst.settings.onSelect = onSelect; 7508 this._inDialog = true; 7509 this.dpDiv.addClass(this._dialogClass); 7510 this._showDatepicker(this._dialogInput[0]); 7511 if ($.blockUI) { 7512 $.blockUI(this.dpDiv); 7513 } 7514 $.data(this._dialogInput[0], "datepicker", inst); 7515 return this; 7516 }, 7517 7518 /* Detach a datepicker from its control. 7519 * @param target element - the target input field or division or span 7520 */ 7521 _destroyDatepicker: function (target) { 7522 var nodeName, 7523 $target = $(target), 7524 inst = $.data(target, "datepicker"); 7525 7526 if (!$target.hasClass(this.markerClassName)) { 7527 return; 7528 } 7529 7530 nodeName = target.nodeName.toLowerCase(); 7531 $.removeData(target, "datepicker"); 7532 if (nodeName === "input") { 7533 inst.append.remove(); 7534 inst.trigger.remove(); 7535 $target.removeClass(this.markerClassName). 7536 off("focus", this._showDatepicker). 7537 off("keydown", this._doKeyDown). 7538 off("keypress", this._doKeyPress). 7539 off("keyup", this._doKeyUp); 7540 } else if (nodeName === "div" || nodeName === "span") { 7541 $target.removeClass(this.markerClassName).empty(); 7542 } 7543 7544 $.datepicker._hideDatepicker(); 7545 if (datepicker_instActive === inst) { 7546 datepicker_instActive = null; 7547 this._curInst = null; 7548 } 7549 }, 7550 7551 /* Enable the date picker to a jQuery selection. 7552 * @param target element - the target input field or division or span 7553 */ 7554 _enableDatepicker: function (target) { 7555 var nodeName, inline, 7556 $target = $(target), 7557 inst = $.data(target, "datepicker"); 7558 7559 if (!$target.hasClass(this.markerClassName)) { 7560 return; 7561 } 7562 7563 nodeName = target.nodeName.toLowerCase(); 7564 if (nodeName === "input") { 7565 target.disabled = false; 7566 inst.trigger.filter("button"). 7567 each(function () { 7568 this.disabled = false; 7569 }).end(). 7570 filter("img").css({ opacity: "1.0", cursor: "" }); 7571 } else if (nodeName === "div" || nodeName === "span") { 7572 inline = $target.children("." + this._inlineClass); 7573 inline.children().removeClass("ui-state-disabled"); 7574 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 7575 prop("disabled", false); 7576 } 7577 this._disabledInputs = $.map(this._disabledInputs, 7578 7579 // Delete entry 7580 function (value) { 7581 return (value === target ? null : value); 7582 }); 7583 }, 7584 7585 /* Disable the date picker to a jQuery selection. 7586 * @param target element - the target input field or division or span 7587 */ 7588 _disableDatepicker: function (target) { 7589 var nodeName, inline, 7590 $target = $(target), 7591 inst = $.data(target, "datepicker"); 7592 7593 if (!$target.hasClass(this.markerClassName)) { 7594 return; 7595 } 7596 7597 nodeName = target.nodeName.toLowerCase(); 7598 if (nodeName === "input") { 7599 target.disabled = true; 7600 inst.trigger.filter("button"). 7601 each(function () { 7602 this.disabled = true; 7603 }).end(). 7604 filter("img").css({ opacity: "0.5", cursor: "default" }); 7605 } else if (nodeName === "div" || nodeName === "span") { 7606 inline = $target.children("." + this._inlineClass); 7607 inline.children().addClass("ui-state-disabled"); 7608 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 7609 prop("disabled", true); 7610 } 7611 this._disabledInputs = $.map(this._disabledInputs, 7612 7613 // Delete entry 7614 function (value) { 7615 return (value === target ? null : value); 7616 }); 7617 this._disabledInputs[this._disabledInputs.length] = target; 7618 }, 7619 7620 /* Is the first field in a jQuery collection disabled as a datepicker? 7621 * @param target element - the target input field or division or span 7622 * @return boolean - true if disabled, false if enabled 7623 */ 7624 _isDisabledDatepicker: function (target) { 7625 if (!target) { 7626 return false; 7627 } 7628 for (var i = 0; i < this._disabledInputs.length; i++) { 7629 if (this._disabledInputs[i] === target) { 7630 return true; 7631 } 7632 } 7633 return false; 7634 }, 7635 7636 /* Retrieve the instance data for the target control. 7637 * @param target element - the target input field or division or span 7638 * @return object - the associated instance data 7639 * @throws error if a jQuery problem getting data 7640 */ 7641 _getInst: function (target) { 7642 try { 7643 return $.data(target, "datepicker"); 7644 } catch (err) { 7645 throw "Missing instance data for this datepicker"; 7646 } 7647 }, 7648 7649 /* Update or retrieve the settings for a date picker attached to an input field or division. 7650 * @param target element - the target input field or division or span 7651 * @param name object - the new settings to update or 7652 * string - the name of the setting to change or retrieve, 7653 * when retrieving also "all" for all instance settings or 7654 * "defaults" for all global defaults 7655 * @param value any - the new value for the setting 7656 * (omit if above is an object or to retrieve a value) 7657 */ 7658 _optionDatepicker: function (target, name, value) { 7659 var settings, date, minDate, maxDate, 7660 inst = this._getInst(target); 7661 7662 if (arguments.length === 2 && typeof name === "string") { 7663 return (name === "defaults" ? $.extend({}, $.datepicker._defaults) : 7664 (inst ? (name === "all" ? $.extend({}, inst.settings) : 7665 this._get(inst, name)) : null)); 7666 } 7667 7668 settings = name || {}; 7669 if (typeof name === "string") { 7670 settings = {}; 7671 settings[name] = value; 7672 } 7673 7674 if (inst) { 7675 if (this._curInst === inst) { 7676 this._hideDatepicker(); 7677 } 7678 7679 date = this._getDateDatepicker(target, true); 7680 minDate = this._getMinMaxDate(inst, "min"); 7681 maxDate = this._getMinMaxDate(inst, "max"); 7682 datepicker_extendRemove(inst.settings, settings); 7683 7684 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided 7685 if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) { 7686 inst.settings.minDate = this._formatDate(inst, minDate); 7687 } 7688 if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) { 7689 inst.settings.maxDate = this._formatDate(inst, maxDate); 7690 } 7691 if ("disabled" in settings) { 7692 if (settings.disabled) { 7693 this._disableDatepicker(target); 7694 } else { 7695 this._enableDatepicker(target); 7696 } 7697 } 7698 this._attachments($(target), inst); 7699 this._autoSize(inst); 7700 this._setDate(inst, date); 7701 this._updateAlternate(inst); 7702 this._updateDatepicker(inst); 7703 } 7704 }, 7705 7706 // Change method deprecated 7707 _changeDatepicker: function (target, name, value) { 7708 this._optionDatepicker(target, name, value); 7709 }, 7710 7711 /* Redraw the date picker attached to an input field or division. 7712 * @param target element - the target input field or division or span 7713 */ 7714 _refreshDatepicker: function (target) { 7715 var inst = this._getInst(target); 7716 if (inst) { 7717 this._updateDatepicker(inst); 7718 } 7719 }, 7720 7721 /* Set the dates for a jQuery selection. 7722 * @param target element - the target input field or division or span 7723 * @param date Date - the new date 7724 */ 7725 _setDateDatepicker: function (target, date) { 7726 var inst = this._getInst(target); 7727 if (inst) { 7728 this._setDate(inst, date); 7729 this._updateDatepicker(inst); 7730 this._updateAlternate(inst); 7731 } 7732 }, 7733 7734 /* Get the date(s) for the first entry in a jQuery selection. 7735 * @param target element - the target input field or division or span 7736 * @param noDefault boolean - true if no default date is to be used 7737 * @return Date - the current date 7738 */ 7739 _getDateDatepicker: function (target, noDefault) { 7740 var inst = this._getInst(target); 7741 if (inst && !inst.inline) { 7742 this._setDateFromField(inst, noDefault); 7743 } 7744 return (inst ? this._getDate(inst) : null); 7745 }, 7746 7747 /* Handle keystrokes. */ 7748 _doKeyDown: function (event) { 7749 var onSelect, dateStr, sel, 7750 inst = $.datepicker._getInst(event.target), 7751 handled = true, 7752 isRTL = inst.dpDiv.is(".ui-datepicker-rtl"); 7753 7754 inst._keyEvent = true; 7755 if ($.datepicker._datepickerShowing) { 7756 switch (event.keyCode) { 7757 case 9: $.datepicker._hideDatepicker(); 7758 handled = false; 7759 break; // hide on tab out 7760 case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." + 7761 $.datepicker._currentClass + ")", inst.dpDiv); 7762 if (sel[0]) { 7763 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); 7764 } 7765 7766 onSelect = $.datepicker._get(inst, "onSelect"); 7767 if (onSelect) { 7768 dateStr = $.datepicker._formatDate(inst); 7769 7770 // Trigger custom callback 7771 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); 7772 } else { 7773 $.datepicker._hideDatepicker(); 7774 } 7775 7776 return false; // don't submit the form 7777 case 27: $.datepicker._hideDatepicker(); 7778 break; // hide on escape 7779 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7780 -$.datepicker._get(inst, "stepBigMonths") : 7781 -$.datepicker._get(inst, "stepMonths")), "M"); 7782 break; // previous month/year on page up/+ ctrl 7783 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7784 +$.datepicker._get(inst, "stepBigMonths") : 7785 +$.datepicker._get(inst, "stepMonths")), "M"); 7786 break; // next month/year on page down/+ ctrl 7787 case 35: if (event.ctrlKey || event.metaKey) { 7788 $.datepicker._clearDate(event.target); 7789 } 7790 handled = event.ctrlKey || event.metaKey; 7791 break; // clear on ctrl or command +end 7792 case 36: if (event.ctrlKey || event.metaKey) { 7793 $.datepicker._gotoToday(event.target); 7794 } 7795 handled = event.ctrlKey || event.metaKey; 7796 break; // current on ctrl or command +home 7797 case 37: if (event.ctrlKey || event.metaKey) { 7798 $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D"); 7799 } 7800 handled = event.ctrlKey || event.metaKey; 7801 7802 // -1 day on ctrl or command +left 7803 if (event.originalEvent.altKey) { 7804 $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7805 -$.datepicker._get(inst, "stepBigMonths") : 7806 -$.datepicker._get(inst, "stepMonths")), "M"); 7807 } 7808 7809 // next month/year on alt +left on Mac 7810 break; 7811 case 38: if (event.ctrlKey || event.metaKey) { 7812 $.datepicker._adjustDate(event.target, -7, "D"); 7813 } 7814 handled = event.ctrlKey || event.metaKey; 7815 break; // -1 week on ctrl or command +up 7816 case 39: if (event.ctrlKey || event.metaKey) { 7817 $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D"); 7818 } 7819 handled = event.ctrlKey || event.metaKey; 7820 7821 // +1 day on ctrl or command +right 7822 if (event.originalEvent.altKey) { 7823 $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7824 +$.datepicker._get(inst, "stepBigMonths") : 7825 +$.datepicker._get(inst, "stepMonths")), "M"); 7826 } 7827 7828 // next month/year on alt +right 7829 break; 7830 case 40: if (event.ctrlKey || event.metaKey) { 7831 $.datepicker._adjustDate(event.target, +7, "D"); 7832 } 7833 handled = event.ctrlKey || event.metaKey; 7834 break; // +1 week on ctrl or command +down 7835 default: handled = false; 7836 } 7837 } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home 7838 $.datepicker._showDatepicker(this); 7839 } else { 7840 handled = false; 7841 } 7842 7843 if (handled) { 7844 event.preventDefault(); 7845 event.stopPropagation(); 7846 } 7847 }, 7848 7849 /* Filter entered characters - based on date format. */ 7850 _doKeyPress: function (event) { 7851 var chars, chr, 7852 inst = $.datepicker._getInst(event.target); 7853 7854 if ($.datepicker._get(inst, "constrainInput")) { 7855 chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat")); 7856 chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode); 7857 return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1); 7858 } 7859 }, 7860 7861 /* Synchronise manual entry and field/alternate field. */ 7862 _doKeyUp: function (event) { 7863 var date, 7864 inst = $.datepicker._getInst(event.target); 7865 7866 if (inst.input.val() !== inst.lastVal) { 7867 try { 7868 date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), 7869 (inst.input ? inst.input.val() : null), 7870 $.datepicker._getFormatConfig(inst)); 7871 7872 if (date) { // only if valid 7873 $.datepicker._setDateFromField(inst); 7874 $.datepicker._updateAlternate(inst); 7875 $.datepicker._updateDatepicker(inst); 7876 } 7877 } catch (err) { 7878 } 7879 } 7880 return true; 7881 }, 7882 7883 /* Pop-up the date picker for a given input field. 7884 * If false returned from beforeShow event handler do not show. 7885 * @param input element - the input field attached to the date picker or 7886 * event - if triggered by focus 7887 */ 7888 _showDatepicker: function (input) { 7889 input = input.target || input; 7890 if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger 7891 input = $("input", input.parentNode)[0]; 7892 } 7893 7894 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here 7895 return; 7896 } 7897 7898 var inst, beforeShow, beforeShowSettings, isFixed, 7899 offset, showAnim, duration; 7900 7901 inst = $.datepicker._getInst(input); 7902 if ($.datepicker._curInst && $.datepicker._curInst !== inst) { 7903 $.datepicker._curInst.dpDiv.stop(true, true); 7904 if (inst && $.datepicker._datepickerShowing) { 7905 $.datepicker._hideDatepicker($.datepicker._curInst.input[0]); 7906 } 7907 } 7908 7909 beforeShow = $.datepicker._get(inst, "beforeShow"); 7910 beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; 7911 if (beforeShowSettings === false) { 7912 return; 7913 } 7914 datepicker_extendRemove(inst.settings, beforeShowSettings); 7915 7916 inst.lastVal = null; 7917 $.datepicker._lastInput = input; 7918 $.datepicker._setDateFromField(inst); 7919 7920 if ($.datepicker._inDialog) { // hide cursor 7921 input.value = ""; 7922 } 7923 if (!$.datepicker._pos) { // position below input 7924 $.datepicker._pos = $.datepicker._findPos(input); 7925 $.datepicker._pos[1] += input.offsetHeight; // add the height 7926 } 7927 7928 isFixed = false; 7929 $(input).parents().each(function () { 7930 isFixed |= $(this).css("position") === "fixed"; 7931 return !isFixed; 7932 }); 7933 7934 offset = { left: $.datepicker._pos[0], top: $.datepicker._pos[1] }; 7935 $.datepicker._pos = null; 7936 7937 //to avoid flashes on Firefox 7938 inst.dpDiv.empty(); 7939 7940 // determine sizing offscreen 7941 inst.dpDiv.css({ position: "absolute", display: "block", top: "-1000px" }); 7942 $.datepicker._updateDatepicker(inst); 7943 7944 // fix width for dynamic number of date pickers 7945 // and adjust position before showing 7946 offset = $.datepicker._checkOffset(inst, offset, isFixed); 7947 inst.dpDiv.css({ 7948 position: ($.datepicker._inDialog && $.blockUI ? 7949 "static" : (isFixed ? "fixed" : "absolute")), display: "none", 7950 left: offset.left + "px", top: offset.top + "px" 7951 }); 7952 7953 if (!inst.inline) { 7954 showAnim = $.datepicker._get(inst, "showAnim"); 7955 duration = $.datepicker._get(inst, "duration"); 7956 inst.dpDiv.css("z-index", datepicker_getZindex($(input)) + 1); 7957 $.datepicker._datepickerShowing = true; 7958 7959 if ($.effects && $.effects.effect[showAnim]) { 7960 inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration); 7961 } else { 7962 inst.dpDiv[showAnim || "show"](showAnim ? duration : null); 7963 } 7964 7965 if ($.datepicker._shouldFocusInput(inst)) { 7966 inst.input.trigger("focus"); 7967 } 7968 7969 $.datepicker._curInst = inst; 7970 } 7971 }, 7972 7973 /* Generate the date picker content. */ 7974 _updateDatepicker: function (inst) { 7975 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) 7976 datepicker_instActive = inst; // for delegate hover events 7977 inst.dpDiv.empty().append(this._generateHTML(inst)); 7978 this._attachHandlers(inst); 7979 7980 var origyearshtml, 7981 numMonths = this._getNumberOfMonths(inst), 7982 cols = numMonths[1], 7983 width = 17, 7984 activeCell = inst.dpDiv.find("." + this._dayOverClass + " a"), 7985 onUpdateDatepicker = $.datepicker._get(inst, "onUpdateDatepicker"); 7986 7987 if (activeCell.length > 0) { 7988 datepicker_handleMouseover.apply(activeCell.get(0)); 7989 } 7990 7991 inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""); 7992 if (cols > 1) { 7993 inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em"); 7994 } 7995 inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") + 7996 "Class"]("ui-datepicker-multi"); 7997 inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") + 7998 "Class"]("ui-datepicker-rtl"); 7999 8000 if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput(inst)) { 8001 inst.input.trigger("focus"); 8002 } 8003 8004 // Deffered render of the years select (to avoid flashes on Firefox) 8005 if (inst.yearshtml) { 8006 origyearshtml = inst.yearshtml; 8007 setTimeout(function () { 8008 8009 //assure that inst.yearshtml didn't change. 8010 if (origyearshtml === inst.yearshtml && inst.yearshtml) { 8011 inst.dpDiv.find("select.ui-datepicker-year").first().replaceWith(inst.yearshtml); 8012 } 8013 origyearshtml = inst.yearshtml = null; 8014 }, 0); 8015 } 8016 8017 if (onUpdateDatepicker) { 8018 onUpdateDatepicker.apply((inst.input ? inst.input[0] : null), [inst]); 8019 } 8020 }, 8021 8022 _shouldFocusInput: function (inst) { 8023 return inst.input && inst.input.is(":visible") && !inst.input.is(":disabled"); 8024 }, 8025 8026 /* Check positioning to remain on screen. */ 8027 _checkOffset: function (inst, offset, isFixed) { 8028 var dpWidth = inst.dpDiv.outerWidth(), 8029 dpHeight = inst.dpDiv.outerHeight(), 8030 inputWidth = inst.input ? inst.input.outerWidth() : 0, 8031 inputHeight = inst.input ? inst.input.outerHeight() : 0, 8032 viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()), 8033 viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop()); 8034 8035 offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0); 8036 offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0; 8037 offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; 8038 8039 // Now check if datepicker is showing outside window viewport - move to a better place if so. 8040 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? 8041 Math.abs(offset.left + dpWidth - viewWidth) : 0); 8042 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? 8043 Math.abs(dpHeight + inputHeight) : 0); 8044 8045 return offset; 8046 }, 8047 8048 /* Find an object's position on the screen. */ 8049 _findPos: function (obj) { 8050 var position, 8051 inst = this._getInst(obj), 8052 isRTL = this._get(inst, "isRTL"); 8053 8054 while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden(obj))) { 8055 obj = obj[isRTL ? "previousSibling" : "nextSibling"]; 8056 } 8057 8058 position = $(obj).offset(); 8059 return [position.left, position.top]; 8060 }, 8061 8062 /* Hide the date picker from view. 8063 * @param input element - the input field attached to the date picker 8064 */ 8065 _hideDatepicker: function (input) { 8066 var showAnim, duration, postProcess, onClose, 8067 inst = this._curInst; 8068 8069 if (!inst || (input && inst !== $.data(input, "datepicker"))) { 8070 return; 8071 } 8072 8073 if (this._datepickerShowing) { 8074 showAnim = this._get(inst, "showAnim"); 8075 duration = this._get(inst, "duration"); 8076 postProcess = function () { 8077 $.datepicker._tidyDialog(inst); 8078 }; 8079 8080 if ($.effects && ($.effects.effect[showAnim])) { 8081 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess); 8082 } else { 8083 inst.dpDiv[(showAnim === "slideDown" ? "slideUp" : 8084 (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess); 8085 } 8086 8087 if (!showAnim) { 8088 postProcess(); 8089 } 8090 this._datepickerShowing = false; 8091 8092 onClose = this._get(inst, "onClose"); 8093 if (onClose) { 8094 onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]); 8095 } 8096 8097 this._lastInput = null; 8098 if (this._inDialog) { 8099 this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" }); 8100 if ($.blockUI) { 8101 $.unblockUI(); 8102 $("body").append(this.dpDiv); 8103 } 8104 } 8105 this._inDialog = false; 8106 } 8107 }, 8108 8109 /* Tidy up after a dialog display. */ 8110 _tidyDialog: function (inst) { 8111 inst.dpDiv.removeClass(this._dialogClass).off(".ui-datepicker-calendar"); 8112 }, 8113 8114 /* Close date picker if clicked elsewhere. */ 8115 _checkExternalClick: function (event) { 8116 if (!$.datepicker._curInst) { 8117 return; 8118 } 8119 8120 var $target = $(event.target), 8121 inst = $.datepicker._getInst($target[0]); 8122 8123 if ((($target[0].id !== $.datepicker._mainDivId && 8124 $target.parents("#" + $.datepicker._mainDivId).length === 0 && 8125 !$target.hasClass($.datepicker.markerClassName) && 8126 !$target.closest("." + $.datepicker._triggerClass).length && 8127 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))) || 8128 ($target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst)) { 8129 $.datepicker._hideDatepicker(); 8130 } 8131 }, 8132 8133 /* Adjust one of the date sub-fields. */ 8134 _adjustDate: function (id, offset, period) { 8135 var target = $(id), 8136 inst = this._getInst(target[0]); 8137 8138 if (this._isDisabledDatepicker(target[0])) { 8139 return; 8140 } 8141 this._adjustInstDate(inst, offset, period); 8142 this._updateDatepicker(inst); 8143 }, 8144 8145 /* Action for current link. */ 8146 _gotoToday: function (id) { 8147 var date, 8148 target = $(id), 8149 inst = this._getInst(target[0]); 8150 8151 if (this._get(inst, "gotoCurrent") && inst.currentDay) { 8152 inst.selectedDay = inst.currentDay; 8153 inst.drawMonth = inst.selectedMonth = inst.currentMonth; 8154 inst.drawYear = inst.selectedYear = inst.currentYear; 8155 } else { 8156 date = new Date(); 8157 inst.selectedDay = date.getDate(); 8158 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8159 inst.drawYear = inst.selectedYear = date.getFullYear(); 8160 } 8161 this._notifyChange(inst); 8162 this._adjustDate(target); 8163 }, 8164 8165 /* Action for selecting a new month/year. */ 8166 _selectMonthYear: function (id, select, period) { 8167 var target = $(id), 8168 inst = this._getInst(target[0]); 8169 8170 inst["selected" + (period === "M" ? "Month" : "Year")] = 8171 inst["draw" + (period === "M" ? "Month" : "Year")] = 8172 parseInt(select.options[select.selectedIndex].value, 10); 8173 8174 this._notifyChange(inst); 8175 this._adjustDate(target); 8176 }, 8177 8178 /* Action for selecting a day. */ 8179 _selectDay: function (id, month, year, td) { 8180 var inst, 8181 target = $(id); 8182 8183 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { 8184 return; 8185 } 8186 8187 inst = this._getInst(target[0]); 8188 inst.selectedDay = inst.currentDay = parseInt($("a", td).attr("data-date")); 8189 inst.selectedMonth = inst.currentMonth = month; 8190 inst.selectedYear = inst.currentYear = year; 8191 this._selectDate(id, this._formatDate(inst, 8192 inst.currentDay, inst.currentMonth, inst.currentYear)); 8193 }, 8194 8195 /* Erase the input field and hide the date picker. */ 8196 _clearDate: function (id) { 8197 var target = $(id); 8198 this._selectDate(target, ""); 8199 }, 8200 8201 /* Update the input field with the selected date. */ 8202 _selectDate: function (id, dateStr) { 8203 var onSelect, 8204 target = $(id), 8205 inst = this._getInst(target[0]); 8206 8207 dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); 8208 if (inst.input) { 8209 inst.input.val(dateStr); 8210 } 8211 this._updateAlternate(inst); 8212 8213 onSelect = this._get(inst, "onSelect"); 8214 if (onSelect) { 8215 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback 8216 } else if (inst.input) { 8217 inst.input.trigger("change"); // fire the change event 8218 } 8219 8220 if (inst.inline) { 8221 this._updateDatepicker(inst); 8222 } else { 8223 this._hideDatepicker(); 8224 this._lastInput = inst.input[0]; 8225 if (typeof (inst.input[0]) !== "object") { 8226 inst.input.trigger("focus"); // restore focus 8227 } 8228 this._lastInput = null; 8229 } 8230 }, 8231 8232 /* Update any alternate field to synchronise with the main field. */ 8233 _updateAlternate: function (inst) { 8234 var altFormat, date, dateStr, 8235 altField = this._get(inst, "altField"); 8236 8237 if (altField) { // update alternate field too 8238 altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat"); 8239 date = this._getDate(inst); 8240 dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); 8241 $(document).find(altField).val(dateStr); 8242 } 8243 }, 8244 8245 /* Set as beforeShowDay function to prevent selection of weekends. 8246 * @param date Date - the date to customise 8247 * @return [boolean, string] - is this date selectable?, what is its CSS class? 8248 */ 8249 noWeekends: function (date) { 8250 var day = date.getDay(); 8251 return [(day > 0 && day < 6), ""]; 8252 }, 8253 8254 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. 8255 * @param date Date - the date to get the week for 8256 * @return number - the number of the week within the year that contains this date 8257 */ 8258 iso8601Week: function (date) { 8259 var time, 8260 checkDate = new Date(date.getTime()); 8261 8262 // Find Thursday of this week starting on Monday 8263 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); 8264 8265 time = checkDate.getTime(); 8266 checkDate.setMonth(0); // Compare with Jan 1 8267 checkDate.setDate(1); 8268 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; 8269 }, 8270 8271 /* Parse a string value into a date object. 8272 * See formatDate below for the possible formats. 8273 * 8274 * @param format string - the expected format of the date 8275 * @param value string - the date in the above format 8276 * @param settings Object - attributes include: 8277 * shortYearCutoff number - the cutoff year for determining the century (optional) 8278 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 8279 * dayNames string[7] - names of the days from Sunday (optional) 8280 * monthNamesShort string[12] - abbreviated names of the months (optional) 8281 * monthNames string[12] - names of the months (optional) 8282 * @return Date - the extracted date value or null if value is blank 8283 */ 8284 parseDate: function (format, value, settings) { 8285 if (format == null || value == null) { 8286 throw "Invalid arguments"; 8287 } 8288 8289 value = (typeof value === "object" ? value.toString() : value + ""); 8290 if (value === "") { 8291 return null; 8292 } 8293 8294 var iFormat, dim, extra, 8295 iValue = 0, 8296 shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff, 8297 shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : 8298 new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)), 8299 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, 8300 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, 8301 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, 8302 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, 8303 year = -1, 8304 month = -1, 8305 day = -1, 8306 doy = -1, 8307 literal = false, 8308 date, 8309 8310 // Check whether a format character is doubled 8311 lookAhead = function (match) { 8312 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 8313 if (matches) { 8314 iFormat++; 8315 } 8316 return matches; 8317 }, 8318 8319 // Extract a number from the string value 8320 getNumber = function (match) { 8321 var isDoubled = lookAhead(match), 8322 size = (match === "@" ? 14 : (match === "!" ? 20 : 8323 (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))), 8324 minSize = (match === "y" ? size : 1), 8325 digits = new RegExp("^\\d{" + minSize + "," + size + "}"), 8326 num = value.substring(iValue).match(digits); 8327 if (!num) { 8328 throw "Missing number at position " + iValue; 8329 } 8330 iValue += num[0].length; 8331 return parseInt(num[0], 10); 8332 }, 8333 8334 // Extract a name from the string value and convert to an index 8335 getName = function (match, shortNames, longNames) { 8336 var index = -1, 8337 names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { 8338 return [[k, v]]; 8339 }).sort(function (a, b) { 8340 return -(a[1].length - b[1].length); 8341 }); 8342 8343 $.each(names, function (i, pair) { 8344 var name = pair[1]; 8345 if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) { 8346 index = pair[0]; 8347 iValue += name.length; 8348 return false; 8349 } 8350 }); 8351 if (index !== -1) { 8352 return index + 1; 8353 } else { 8354 throw "Unknown name at position " + iValue; 8355 } 8356 }, 8357 8358 // Confirm that a literal character matches the string value 8359 checkLiteral = function () { 8360 if (value.charAt(iValue) !== format.charAt(iFormat)) { 8361 throw "Unexpected literal at position " + iValue; 8362 } 8363 iValue++; 8364 }; 8365 8366 for (iFormat = 0; iFormat < format.length; iFormat++) { 8367 if (literal) { 8368 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 8369 literal = false; 8370 } else { 8371 checkLiteral(); 8372 } 8373 } else { 8374 switch (format.charAt(iFormat)) { 8375 case "d": 8376 day = getNumber("d"); 8377 break; 8378 case "D": 8379 getName("D", dayNamesShort, dayNames); 8380 break; 8381 case "o": 8382 doy = getNumber("o"); 8383 break; 8384 case "m": 8385 month = getNumber("m"); 8386 break; 8387 case "M": 8388 month = getName("M", monthNamesShort, monthNames); 8389 break; 8390 case "y": 8391 year = getNumber("y"); 8392 break; 8393 case "@": 8394 date = new Date(getNumber("@")); 8395 year = date.getFullYear(); 8396 month = date.getMonth() + 1; 8397 day = date.getDate(); 8398 break; 8399 case "!": 8400 date = new Date((getNumber("!") - this._ticksTo1970) / 10000); 8401 year = date.getFullYear(); 8402 month = date.getMonth() + 1; 8403 day = date.getDate(); 8404 break; 8405 case "'": 8406 if (lookAhead("'")) { 8407 checkLiteral(); 8408 } else { 8409 literal = true; 8410 } 8411 break; 8412 default: 8413 checkLiteral(); 8414 } 8415 } 8416 } 8417 8418 if (iValue < value.length) { 8419 extra = value.substr(iValue); 8420 if (!/^\s+/.test(extra)) { 8421 throw "Extra/unparsed characters found in date: " + extra; 8422 } 8423 } 8424 8425 if (year === -1) { 8426 year = new Date().getFullYear(); 8427 } else if (year < 100) { 8428 year += new Date().getFullYear() - new Date().getFullYear() % 100 + 8429 (year <= shortYearCutoff ? 0 : -100); 8430 } 8431 8432 if (doy > -1) { 8433 month = 1; 8434 day = doy; 8435 do { 8436 dim = this._getDaysInMonth(year, month - 1); 8437 if (day <= dim) { 8438 break; 8439 } 8440 month++; 8441 day -= dim; 8442 } while (true); 8443 } 8444 8445 date = this._daylightSavingAdjust(new Date(year, month - 1, day)); 8446 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) { 8447 throw "Invalid date"; // E.g. 31/02/00 8448 } 8449 return date; 8450 }, 8451 8452 /* Standard date formats. */ 8453 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601) 8454 COOKIE: "D, dd M yy", 8455 ISO_8601: "yy-mm-dd", 8456 RFC_822: "D, d M y", 8457 RFC_850: "DD, dd-M-y", 8458 RFC_1036: "D, d M y", 8459 RFC_1123: "D, d M yy", 8460 RFC_2822: "D, d M yy", 8461 RSS: "D, d M y", // RFC 822 8462 TICKS: "!", 8463 TIMESTAMP: "@", 8464 W3C: "yy-mm-dd", // ISO 8601 8465 8466 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + 8467 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), 8468 8469 /* Format a date object into a string value. 8470 * The format can be combinations of the following: 8471 * d - day of month (no leading zero) 8472 * dd - day of month (two digit) 8473 * o - day of year (no leading zeros) 8474 * oo - day of year (three digit) 8475 * D - day name short 8476 * DD - day name long 8477 * m - month of year (no leading zero) 8478 * mm - month of year (two digit) 8479 * M - month name short 8480 * MM - month name long 8481 * y - year (two digit) 8482 * yy - year (four digit) 8483 * @ - Unix timestamp (ms since 01/01/1970) 8484 * ! - Windows ticks (100ns since 01/01/0001) 8485 * "..." - literal text 8486 * '' - single quote 8487 * 8488 * @param format string - the desired format of the date 8489 * @param date Date - the date value to format 8490 * @param settings Object - attributes include: 8491 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 8492 * dayNames string[7] - names of the days from Sunday (optional) 8493 * monthNamesShort string[12] - abbreviated names of the months (optional) 8494 * monthNames string[12] - names of the months (optional) 8495 * @return string - the date in the above format 8496 */ 8497 formatDate: function (format, date, settings) { 8498 if (!date) { 8499 return ""; 8500 } 8501 8502 var iFormat, 8503 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, 8504 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, 8505 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, 8506 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, 8507 8508 // Check whether a format character is doubled 8509 lookAhead = function (match) { 8510 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 8511 if (matches) { 8512 iFormat++; 8513 } 8514 return matches; 8515 }, 8516 8517 // Format a number, with leading zero if necessary 8518 formatNumber = function (match, value, len) { 8519 var num = "" + value; 8520 if (lookAhead(match)) { 8521 while (num.length < len) { 8522 num = "0" + num; 8523 } 8524 } 8525 return num; 8526 }, 8527 8528 // Format a name, short or long as requested 8529 formatName = function (match, value, shortNames, longNames) { 8530 return (lookAhead(match) ? longNames[value] : shortNames[value]); 8531 }, 8532 output = "", 8533 literal = false; 8534 8535 if (date) { 8536 for (iFormat = 0; iFormat < format.length; iFormat++) { 8537 if (literal) { 8538 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 8539 literal = false; 8540 } else { 8541 output += format.charAt(iFormat); 8542 } 8543 } else { 8544 switch (format.charAt(iFormat)) { 8545 case "d": 8546 output += formatNumber("d", date.getDate(), 2); 8547 break; 8548 case "D": 8549 output += formatName("D", date.getDay(), dayNamesShort, dayNames); 8550 break; 8551 case "o": 8552 output += formatNumber("o", 8553 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); 8554 break; 8555 case "m": 8556 output += formatNumber("m", date.getMonth() + 1, 2); 8557 break; 8558 case "M": 8559 output += formatName("M", date.getMonth(), monthNamesShort, monthNames); 8560 break; 8561 case "y": 8562 output += (lookAhead("y") ? date.getFullYear() : 8563 (date.getFullYear() % 100 < 10 ? "0" : "") + date.getFullYear() % 100); 8564 break; 8565 case "@": 8566 output += date.getTime(); 8567 break; 8568 case "!": 8569 output += date.getTime() * 10000 + this._ticksTo1970; 8570 break; 8571 case "'": 8572 if (lookAhead("'")) { 8573 output += "'"; 8574 } else { 8575 literal = true; 8576 } 8577 break; 8578 default: 8579 output += format.charAt(iFormat); 8580 } 8581 } 8582 } 8583 } 8584 return output; 8585 }, 8586 8587 /* Extract all possible characters from the date format. */ 8588 _possibleChars: function (format) { 8589 var iFormat, 8590 chars = "", 8591 literal = false, 8592 8593 // Check whether a format character is doubled 8594 lookAhead = function (match) { 8595 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 8596 if (matches) { 8597 iFormat++; 8598 } 8599 return matches; 8600 }; 8601 8602 for (iFormat = 0; iFormat < format.length; iFormat++) { 8603 if (literal) { 8604 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 8605 literal = false; 8606 } else { 8607 chars += format.charAt(iFormat); 8608 } 8609 } else { 8610 switch (format.charAt(iFormat)) { 8611 case "d": case "m": case "y": case "@": 8612 chars += "0123456789"; 8613 break; 8614 case "D": case "M": 8615 return null; // Accept anything 8616 case "'": 8617 if (lookAhead("'")) { 8618 chars += "'"; 8619 } else { 8620 literal = true; 8621 } 8622 break; 8623 default: 8624 chars += format.charAt(iFormat); 8625 } 8626 } 8627 } 8628 return chars; 8629 }, 8630 8631 /* Get a setting value, defaulting if necessary. */ 8632 _get: function (inst, name) { 8633 return inst.settings[name] !== undefined ? 8634 inst.settings[name] : this._defaults[name]; 8635 }, 8636 8637 /* Parse existing date and initialise date picker. */ 8638 _setDateFromField: function (inst, noDefault) { 8639 if (inst.input.val() === inst.lastVal) { 8640 return; 8641 } 8642 8643 var dateFormat = this._get(inst, "dateFormat"), 8644 dates = inst.lastVal = inst.input ? inst.input.val() : null, 8645 defaultDate = this._getDefaultDate(inst), 8646 date = defaultDate, 8647 settings = this._getFormatConfig(inst); 8648 8649 try { 8650 date = this.parseDate(dateFormat, dates, settings) || defaultDate; 8651 } catch (event) { 8652 dates = (noDefault ? "" : dates); 8653 } 8654 inst.selectedDay = date.getDate(); 8655 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8656 inst.drawYear = inst.selectedYear = date.getFullYear(); 8657 inst.currentDay = (dates ? date.getDate() : 0); 8658 inst.currentMonth = (dates ? date.getMonth() : 0); 8659 inst.currentYear = (dates ? date.getFullYear() : 0); 8660 this._adjustInstDate(inst); 8661 }, 8662 8663 /* Retrieve the default date shown on opening. */ 8664 _getDefaultDate: function (inst) { 8665 return this._restrictMinMax(inst, 8666 this._determineDate(inst, this._get(inst, "defaultDate"), new Date())); 8667 }, 8668 8669 /* A date may be specified as an exact value or a relative one. */ 8670 _determineDate: function (inst, date, defaultDate) { 8671 var offsetNumeric = function (offset) { 8672 var date = new Date(); 8673 date.setDate(date.getDate() + offset); 8674 return date; 8675 }, 8676 offsetString = function (offset) { 8677 try { 8678 return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), 8679 offset, $.datepicker._getFormatConfig(inst)); 8680 } catch (e) { 8681 8682 // Ignore 8683 } 8684 8685 var date = (offset.toLowerCase().match(/^c/) ? 8686 $.datepicker._getDate(inst) : null) || new Date(), 8687 year = date.getFullYear(), 8688 month = date.getMonth(), 8689 day = date.getDate(), 8690 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, 8691 matches = pattern.exec(offset); 8692 8693 while (matches) { 8694 switch (matches[2] || "d") { 8695 case "d": case "D": 8696 day += parseInt(matches[1], 10); break; 8697 case "w": case "W": 8698 day += parseInt(matches[1], 10) * 7; break; 8699 case "m": case "M": 8700 month += parseInt(matches[1], 10); 8701 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 8702 break; 8703 case "y": case "Y": 8704 year += parseInt(matches[1], 10); 8705 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 8706 break; 8707 } 8708 matches = pattern.exec(offset); 8709 } 8710 return new Date(year, month, day); 8711 }, 8712 newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) : 8713 (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); 8714 8715 newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate); 8716 if (newDate) { 8717 newDate.setHours(0); 8718 newDate.setMinutes(0); 8719 newDate.setSeconds(0); 8720 newDate.setMilliseconds(0); 8721 } 8722 return this._daylightSavingAdjust(newDate); 8723 }, 8724 8725 /* Handle switch to/from daylight saving. 8726 * Hours may be non-zero on daylight saving cut-over: 8727 * > 12 when midnight changeover, but then cannot generate 8728 * midnight datetime, so jump to 1AM, otherwise reset. 8729 * @param date (Date) the date to check 8730 * @return (Date) the corrected date 8731 */ 8732 _daylightSavingAdjust: function (date) { 8733 if (!date) { 8734 return null; 8735 } 8736 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); 8737 return date; 8738 }, 8739 8740 /* Set the date(s) directly. */ 8741 _setDate: function (inst, date, noChange) { 8742 var clear = !date, 8743 origMonth = inst.selectedMonth, 8744 origYear = inst.selectedYear, 8745 newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); 8746 8747 inst.selectedDay = inst.currentDay = newDate.getDate(); 8748 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); 8749 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); 8750 if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) { 8751 this._notifyChange(inst); 8752 } 8753 this._adjustInstDate(inst); 8754 if (inst.input) { 8755 inst.input.val(clear ? "" : this._formatDate(inst)); 8756 } 8757 }, 8758 8759 /* Retrieve the date(s) directly. */ 8760 _getDate: function (inst) { 8761 var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null : 8762 this._daylightSavingAdjust(new Date( 8763 inst.currentYear, inst.currentMonth, inst.currentDay))); 8764 return startDate; 8765 }, 8766 8767 /* Attach the onxxx handlers. These are declared statically so 8768 * they work with static code transformers like Caja. 8769 */ 8770 _attachHandlers: function (inst) { 8771 var stepMonths = this._get(inst, "stepMonths"), 8772 id = "#" + inst.id.replace(/\\\\/g, "\\"); 8773 inst.dpDiv.find("[data-handler]").map(function () { 8774 var handler = { 8775 prev: function () { 8776 $.datepicker._adjustDate(id, -stepMonths, "M"); 8777 }, 8778 next: function () { 8779 $.datepicker._adjustDate(id, +stepMonths, "M"); 8780 }, 8781 hide: function () { 8782 $.datepicker._hideDatepicker(); 8783 }, 8784 today: function () { 8785 $.datepicker._gotoToday(id); 8786 }, 8787 selectDay: function () { 8788 $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this); 8789 return false; 8790 }, 8791 selectMonth: function () { 8792 $.datepicker._selectMonthYear(id, this, "M"); 8793 return false; 8794 }, 8795 selectYear: function () { 8796 $.datepicker._selectMonthYear(id, this, "Y"); 8797 return false; 8798 } 8799 }; 8800 $(this).on(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]); 8801 }); 8802 }, 8803 8804 /* Generate the HTML for the current state of the date picker. */ 8805 _generateHTML: function (inst) { 8806 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, 8807 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, 8808 monthNames, monthNamesShort, beforeShowDay, showOtherMonths, 8809 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, 8810 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, 8811 printDate, dRow, tbody, daySettings, otherMonth, unselectable, 8812 tempDate = new Date(), 8813 today = this._daylightSavingAdjust( 8814 new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time 8815 isRTL = this._get(inst, "isRTL"), 8816 showButtonPanel = this._get(inst, "showButtonPanel"), 8817 hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"), 8818 navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"), 8819 numMonths = this._getNumberOfMonths(inst), 8820 showCurrentAtPos = this._get(inst, "showCurrentAtPos"), 8821 stepMonths = this._get(inst, "stepMonths"), 8822 isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1), 8823 currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : 8824 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))), 8825 minDate = this._getMinMaxDate(inst, "min"), 8826 maxDate = this._getMinMaxDate(inst, "max"), 8827 drawMonth = inst.drawMonth - showCurrentAtPos, 8828 drawYear = inst.drawYear; 8829 8830 if (drawMonth < 0) { 8831 drawMonth += 12; 8832 drawYear--; 8833 } 8834 if (maxDate) { 8835 maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), 8836 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); 8837 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); 8838 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { 8839 drawMonth--; 8840 if (drawMonth < 0) { 8841 drawMonth = 11; 8842 drawYear--; 8843 } 8844 } 8845 } 8846 inst.drawMonth = drawMonth; 8847 inst.drawYear = drawYear; 8848 8849 prevText = this._get(inst, "prevText"); 8850 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, 8851 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), 8852 this._getFormatConfig(inst))); 8853 8854 if (this._canAdjustMonth(inst, -1, drawYear, drawMonth)) { 8855 prev = $("<a>") 8856 .attr({ 8857 "class": "ui-datepicker-prev ui-corner-all", 8858 "data-handler": "prev", 8859 "data-event": "click", 8860 title: prevText 8861 }) 8862 .append( 8863 $("<span>") 8864 .addClass("ui-icon ui-icon-circle-triangle-" + 8865 (isRTL ? "e" : "w")) 8866 .text(prevText) 8867 )[0].outerHTML; 8868 } else if (hideIfNoPrevNext) { 8869 prev = ""; 8870 } else { 8871 prev = $("<a>") 8872 .attr({ 8873 "class": "ui-datepicker-prev ui-corner-all ui-state-disabled", 8874 title: prevText 8875 }) 8876 .append( 8877 $("<span>") 8878 .addClass("ui-icon ui-icon-circle-triangle-" + 8879 (isRTL ? "e" : "w")) 8880 .text(prevText) 8881 )[0].outerHTML; 8882 } 8883 8884 nextText = this._get(inst, "nextText"); 8885 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, 8886 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), 8887 this._getFormatConfig(inst))); 8888 8889 if (this._canAdjustMonth(inst, +1, drawYear, drawMonth)) { 8890 next = $("<a>") 8891 .attr({ 8892 "class": "ui-datepicker-next ui-corner-all", 8893 "data-handler": "next", 8894 "data-event": "click", 8895 title: nextText 8896 }) 8897 .append( 8898 $("<span>") 8899 .addClass("ui-icon ui-icon-circle-triangle-" + 8900 (isRTL ? "w" : "e")) 8901 .text(nextText) 8902 )[0].outerHTML; 8903 } else if (hideIfNoPrevNext) { 8904 next = ""; 8905 } else { 8906 next = $("<a>") 8907 .attr({ 8908 "class": "ui-datepicker-next ui-corner-all ui-state-disabled", 8909 title: nextText 8910 }) 8911 .append( 8912 $("<span>") 8913 .attr("class", "ui-icon ui-icon-circle-triangle-" + 8914 (isRTL ? "w" : "e")) 8915 .text(nextText) 8916 )[0].outerHTML; 8917 } 8918 8919 currentText = this._get(inst, "currentText"); 8920 gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today); 8921 currentText = (!navigationAsDateFormat ? currentText : 8922 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); 8923 8924 controls = ""; 8925 if (!inst.inline) { 8926 controls = $("<button>") 8927 .attr({ 8928 type: "button", 8929 "class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all", 8930 "data-handler": "hide", 8931 "data-event": "click" 8932 }) 8933 .text(this._get(inst, "closeText"))[0].outerHTML; 8934 } 8935 8936 buttonPanel = ""; 8937 if (showButtonPanel) { 8938 buttonPanel = $("<div class='ui-datepicker-buttonpane ui-widget-content'>") 8939 .append(isRTL ? controls : "") 8940 .append(this._isInRange(inst, gotoDate) ? 8941 $("<button>") 8942 .attr({ 8943 type: "button", 8944 "class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all", 8945 "data-handler": "today", 8946 "data-event": "click" 8947 }) 8948 .text(currentText) : 8949 "") 8950 .append(isRTL ? "" : controls)[0].outerHTML; 8951 } 8952 8953 firstDay = parseInt(this._get(inst, "firstDay"), 10); 8954 firstDay = (isNaN(firstDay) ? 0 : firstDay); 8955 8956 showWeek = this._get(inst, "showWeek"); 8957 dayNames = this._get(inst, "dayNames"); 8958 dayNamesMin = this._get(inst, "dayNamesMin"); 8959 monthNames = this._get(inst, "monthNames"); 8960 monthNamesShort = this._get(inst, "monthNamesShort"); 8961 beforeShowDay = this._get(inst, "beforeShowDay"); 8962 showOtherMonths = this._get(inst, "showOtherMonths"); 8963 selectOtherMonths = this._get(inst, "selectOtherMonths"); 8964 defaultDate = this._getDefaultDate(inst); 8965 html = ""; 8966 8967 for (row = 0; row < numMonths[0]; row++) { 8968 group = ""; 8969 this.maxRows = 4; 8970 for (col = 0; col < numMonths[1]; col++) { 8971 selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); 8972 cornerClass = " ui-corner-all"; 8973 calender = ""; 8974 if (isMultiMonth) { 8975 calender += "<div class='ui-datepicker-group"; 8976 if (numMonths[1] > 1) { 8977 switch (col) { 8978 case 0: calender += " ui-datepicker-group-first"; 8979 cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break; 8980 case numMonths[1] - 1: calender += " ui-datepicker-group-last"; 8981 cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break; 8982 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break; 8983 } 8984 } 8985 calender += "'>"; 8986 } 8987 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + 8988 (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") + 8989 (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") + 8990 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, 8991 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers 8992 "</div><table class='ui-datepicker-calendar'><thead>" + 8993 "<tr>"; 8994 thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : ""); 8995 for (dow = 0; dow < 7; dow++) { // days of the week 8996 day = (dow + firstDay) % 7; 8997 thead += "<th scope='col'" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" + 8998 "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>"; 8999 } 9000 calender += thead + "</tr></thead><tbody>"; 9001 daysInMonth = this._getDaysInMonth(drawYear, drawMonth); 9002 if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) { 9003 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); 9004 } 9005 leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; 9006 curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate 9007 numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) 9008 this.maxRows = numRows; 9009 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); 9010 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows 9011 calender += "<tr>"; 9012 tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" + 9013 this._get(inst, "calculateWeek")(printDate) + "</td>"); 9014 for (dow = 0; dow < 7; dow++) { // create date picker days 9015 daySettings = (beforeShowDay ? 9016 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]); 9017 otherMonth = (printDate.getMonth() !== drawMonth); 9018 unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || 9019 (minDate && printDate < minDate) || (maxDate && printDate > maxDate); 9020 tbody += "<td class='" + 9021 ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends 9022 (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months 9023 ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key 9024 (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ? 9025 9026 // or defaultDate is current printedDate and defaultDate is selectedDate 9027 " " + this._dayOverClass : "") + // highlight selected day 9028 (unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "") + // highlight unselectable days 9029 (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates 9030 (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day 9031 (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different) 9032 ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "'") + "'" : "") + // cell title 9033 (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions 9034 (otherMonth && !showOtherMonths ? " " : // display for other months 9035 (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + 9036 (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") + 9037 (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day 9038 (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months 9039 "' href='#' aria-current='" + (printDate.getTime() === currentDate.getTime() ? "true" : "false") + // mark date as selected for screen reader 9040 "' data-date='" + printDate.getDate() + // store date as data 9041 "'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date 9042 printDate.setDate(printDate.getDate() + 1); 9043 printDate = this._daylightSavingAdjust(printDate); 9044 } 9045 calender += tbody + "</tr>"; 9046 } 9047 drawMonth++; 9048 if (drawMonth > 11) { 9049 drawMonth = 0; 9050 drawYear++; 9051 } 9052 calender += "</tbody></table>" + (isMultiMonth ? "</div>" + 9053 ((numMonths[0] > 0 && col === numMonths[1] - 1) ? "<div class='ui-datepicker-row-break'></div>" : "") : ""); 9054 group += calender; 9055 } 9056 html += group; 9057 } 9058 html += buttonPanel; 9059 inst._keyEvent = false; 9060 return html; 9061 }, 9062 9063 /* Generate the month and year header. */ 9064 _generateMonthYearHeader: function (inst, drawMonth, drawYear, minDate, maxDate, 9065 secondary, monthNames, monthNamesShort) { 9066 9067 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, 9068 changeMonth = this._get(inst, "changeMonth"), 9069 changeYear = this._get(inst, "changeYear"), 9070 showMonthAfterYear = this._get(inst, "showMonthAfterYear"), 9071 selectMonthLabel = this._get(inst, "selectMonthLabel"), 9072 selectYearLabel = this._get(inst, "selectYearLabel"), 9073 html = "<div class='ui-datepicker-title'>", 9074 monthHtml = ""; 9075 9076 // Month selection 9077 if (secondary || !changeMonth) { 9078 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>"; 9079 } else { 9080 inMinYear = (minDate && minDate.getFullYear() === drawYear); 9081 inMaxYear = (maxDate && maxDate.getFullYear() === drawYear); 9082 monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>"; 9083 for (month = 0; month < 12; month++) { 9084 if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) { 9085 monthHtml += "<option value='" + month + "'" + 9086 (month === drawMonth ? " selected='selected'" : "") + 9087 ">" + monthNamesShort[month] + "</option>"; 9088 } 9089 } 9090 monthHtml += "</select>"; 9091 } 9092 9093 if (!showMonthAfterYear) { 9094 html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : ""); 9095 } 9096 9097 // Year selection 9098 if (!inst.yearshtml) { 9099 inst.yearshtml = ""; 9100 if (secondary || !changeYear) { 9101 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>"; 9102 } else { 9103 9104 // determine range of years to display 9105 years = this._get(inst, "yearRange").split(":"); 9106 thisYear = new Date().getFullYear(); 9107 determineYear = function (value) { 9108 var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) : 9109 (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) : 9110 parseInt(value, 10))); 9111 return (isNaN(year) ? thisYear : year); 9112 }; 9113 year = determineYear(years[0]); 9114 endYear = Math.max(year, determineYear(years[1] || "")); 9115 year = (minDate ? Math.max(year, minDate.getFullYear()) : year); 9116 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); 9117 inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>"; 9118 for (; year <= endYear; year++) { 9119 inst.yearshtml += "<option value='" + year + "'" + 9120 (year === drawYear ? " selected='selected'" : "") + 9121 ">" + year + "</option>"; 9122 } 9123 inst.yearshtml += "</select>"; 9124 9125 html += inst.yearshtml; 9126 inst.yearshtml = null; 9127 } 9128 } 9129 9130 html += this._get(inst, "yearSuffix"); 9131 if (showMonthAfterYear) { 9132 html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml; 9133 } 9134 html += "</div>"; // Close datepicker_header 9135 return html; 9136 }, 9137 9138 /* Adjust one of the date sub-fields. */ 9139 _adjustInstDate: function (inst, offset, period) { 9140 var year = inst.selectedYear + (period === "Y" ? offset : 0), 9141 month = inst.selectedMonth + (period === "M" ? offset : 0), 9142 day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0), 9143 date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day))); 9144 9145 inst.selectedDay = date.getDate(); 9146 inst.drawMonth = inst.selectedMonth = date.getMonth(); 9147 inst.drawYear = inst.selectedYear = date.getFullYear(); 9148 if (period === "M" || period === "Y") { 9149 this._notifyChange(inst); 9150 } 9151 }, 9152 9153 /* Ensure a date is within any min/max bounds. */ 9154 _restrictMinMax: function (inst, date) { 9155 var minDate = this._getMinMaxDate(inst, "min"), 9156 maxDate = this._getMinMaxDate(inst, "max"), 9157 newDate = (minDate && date < minDate ? minDate : date); 9158 return (maxDate && newDate > maxDate ? maxDate : newDate); 9159 }, 9160 9161 /* Notify change of month/year. */ 9162 _notifyChange: function (inst) { 9163 var onChange = this._get(inst, "onChangeMonthYear"); 9164 if (onChange) { 9165 onChange.apply((inst.input ? inst.input[0] : null), 9166 [inst.selectedYear, inst.selectedMonth + 1, inst]); 9167 } 9168 }, 9169 9170 /* Determine the number of months to show. */ 9171 _getNumberOfMonths: function (inst) { 9172 var numMonths = this._get(inst, "numberOfMonths"); 9173 return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths)); 9174 }, 9175 9176 /* Determine the current maximum date - ensure no time components are set. */ 9177 _getMinMaxDate: function (inst, minMax) { 9178 return this._determineDate(inst, this._get(inst, minMax + "Date"), null); 9179 }, 9180 9181 /* Find the number of days in a given month. */ 9182 _getDaysInMonth: function (year, month) { 9183 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); 9184 }, 9185 9186 /* Find the day of the week of the first of a month. */ 9187 _getFirstDayOfMonth: function (year, month) { 9188 return new Date(year, month, 1).getDay(); 9189 }, 9190 9191 /* Determines if we should allow a "next/prev" month display change. */ 9192 _canAdjustMonth: function (inst, offset, curYear, curMonth) { 9193 var numMonths = this._getNumberOfMonths(inst), 9194 date = this._daylightSavingAdjust(new Date(curYear, 9195 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); 9196 9197 if (offset < 0) { 9198 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); 9199 } 9200 return this._isInRange(inst, date); 9201 }, 9202 9203 /* Is the given date in the accepted range? */ 9204 _isInRange: function (inst, date) { 9205 var yearSplit, currentYear, 9206 minDate = this._getMinMaxDate(inst, "min"), 9207 maxDate = this._getMinMaxDate(inst, "max"), 9208 minYear = null, 9209 maxYear = null, 9210 years = this._get(inst, "yearRange"); 9211 if (years) { 9212 yearSplit = years.split(":"); 9213 currentYear = new Date().getFullYear(); 9214 minYear = parseInt(yearSplit[0], 10); 9215 maxYear = parseInt(yearSplit[1], 10); 9216 if (yearSplit[0].match(/[+\-].*/)) { 9217 minYear += currentYear; 9218 } 9219 if (yearSplit[1].match(/[+\-].*/)) { 9220 maxYear += currentYear; 9221 } 9222 } 9223 9224 return ((!minDate || date.getTime() >= minDate.getTime()) && 9225 (!maxDate || date.getTime() <= maxDate.getTime()) && 9226 (!minYear || date.getFullYear() >= minYear) && 9227 (!maxYear || date.getFullYear() <= maxYear)); 9228 }, 9229 9230 /* Provide the configuration settings for formatting/parsing. */ 9231 _getFormatConfig: function (inst) { 9232 var shortYearCutoff = this._get(inst, "shortYearCutoff"); 9233 shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff : 9234 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); 9235 return { 9236 shortYearCutoff: shortYearCutoff, 9237 dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"), 9238 monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames") 9239 }; 9240 }, 9241 9242 /* Format the given date for display. */ 9243 _formatDate: function (inst, day, month, year) { 9244 if (!day) { 9245 inst.currentDay = inst.selectedDay; 9246 inst.currentMonth = inst.selectedMonth; 9247 inst.currentYear = inst.selectedYear; 9248 } 9249 var date = (day ? (typeof day === "object" ? day : 9250 this._daylightSavingAdjust(new Date(year, month, day))) : 9251 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); 9252 return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst)); 9253 } 9254 }); 9255 9256 /* 9257 * Bind hover events for datepicker elements. 9258 * Done via delegate so the binding only occurs once in the lifetime of the parent div. 9259 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. 9260 */ 9261 function datepicker_bindHover(dpDiv) { 9262 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a"; 9263 return dpDiv.on("mouseout", selector, function () { 9264 $(this).removeClass("ui-state-hover"); 9265 if (this.className.indexOf("ui-datepicker-prev") !== -1) { 9266 $(this).removeClass("ui-datepicker-prev-hover"); 9267 } 9268 if (this.className.indexOf("ui-datepicker-next") !== -1) { 9269 $(this).removeClass("ui-datepicker-next-hover"); 9270 } 9271 }) 9272 .on("mouseover", selector, datepicker_handleMouseover); 9273 } 9274 9275 function datepicker_handleMouseover() { 9276 if (!$.datepicker._isDisabledDatepicker(datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[0] : datepicker_instActive.input[0])) { 9277 $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); 9278 $(this).addClass("ui-state-hover"); 9279 if (this.className.indexOf("ui-datepicker-prev") !== -1) { 9280 $(this).addClass("ui-datepicker-prev-hover"); 9281 } 9282 if (this.className.indexOf("ui-datepicker-next") !== -1) { 9283 $(this).addClass("ui-datepicker-next-hover"); 9284 } 9285 } 9286 } 9287 9288 /* jQuery extend now ignores nulls! */ 9289 function datepicker_extendRemove(target, props) { 9290 $.extend(target, props); 9291 for (var name in props) { 9292 if (props[name] == null) { 9293 target[name] = props[name]; 9294 } 9295 } 9296 return target; 9297 } 9298 9299 /* Invoke the datepicker functionality. 9300 @param options string - a command, optionally followed by additional parameters or 9301 Object - settings for attaching new datepicker functionality 9302 @return jQuery object */ 9303 $.fn.datepicker = function (options) { 9304 9305 /* Verify an empty collection wasn't passed - Fixes #6976 */ 9306 if (!this.length) { 9307 return this; 9308 } 9309 9310 /* Initialise the date picker. */ 9311 if (!$.datepicker.initialized) { 9312 $(document).on("mousedown", $.datepicker._checkExternalClick); 9313 $.datepicker.initialized = true; 9314 } 9315 9316 /* Append datepicker main container to body if not exist. */ 9317 if ($("#" + $.datepicker._mainDivId).length === 0) { 9318 $("body").append($.datepicker.dpDiv); 9319 } 9320 9321 var otherArgs = Array.prototype.slice.call(arguments, 1); 9322 if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) { 9323 return $.datepicker["_" + options + "Datepicker"]. 9324 apply($.datepicker, [this[0]].concat(otherArgs)); 9325 } 9326 if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") { 9327 return $.datepicker["_" + options + "Datepicker"]. 9328 apply($.datepicker, [this[0]].concat(otherArgs)); 9329 } 9330 return this.each(function () { 9331 if (typeof options === "string") { 9332 $.datepicker["_" + options + "Datepicker"] 9333 .apply($.datepicker, [this].concat(otherArgs)); 9334 } else { 9335 $.datepicker._attachDatepicker(this, options); 9336 } 9337 }); 9338 }; 9339 9340 $.datepicker = new Datepicker(); // singleton instance 9341 $.datepicker.initialized = false; 9342 $.datepicker.uuid = new Date().getTime(); 9343 $.datepicker.version = "1.14.1"; 9344 9345 var widgetsDatepicker = $.datepicker; 9346 9347 9348 /*! 9349 * jQuery UI Mouse 1.14.1 9350 * https://jqueryui.com 9351 * 9352 * Copyright OpenJS Foundation and other contributors 9353 * Released under the MIT license. 9354 * https://jquery.org/license 9355 */ 9356 9357 //>>label: Mouse 9358 //>>group: Widgets 9359 //>>description: Abstracts mouse-based interactions to assist in creating certain widgets. 9360 //>>docs: https://api.jqueryui.com/mouse/ 9361 9362 9363 var mouseHandled = false; 9364 $(document).on("mouseup", function () { 9365 mouseHandled = false; 9366 }); 9367 9368 var widgetsMouse = $.widget("ui.mouse", { 9369 version: "1.14.1", 9370 options: { 9371 cancel: "input, textarea, button, select, option", 9372 distance: 1, 9373 delay: 0 9374 }, 9375 _mouseInit: function () { 9376 var that = this; 9377 9378 this.element 9379 .on("mousedown." + this.widgetName, function (event) { 9380 return that._mouseDown(event); 9381 }) 9382 .on("click." + this.widgetName, function (event) { 9383 if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) { 9384 $.removeData(event.target, that.widgetName + ".preventClickEvent"); 9385 event.stopImmediatePropagation(); 9386 return false; 9387 } 9388 }); 9389 9390 this.started = false; 9391 }, 9392 9393 // TODO: make sure destroying one instance of mouse doesn't mess with 9394 // other instances of mouse 9395 _mouseDestroy: function () { 9396 this.element.off("." + this.widgetName); 9397 if (this._mouseMoveDelegate) { 9398 this.document 9399 .off("mousemove." + this.widgetName, this._mouseMoveDelegate) 9400 .off("mouseup." + this.widgetName, this._mouseUpDelegate); 9401 } 9402 }, 9403 9404 _mouseDown: function (event) { 9405 9406 // don't let more than one widget handle mouseStart 9407 if (mouseHandled) { 9408 return; 9409 } 9410 9411 this._mouseMoved = false; 9412 9413 // We may have missed mouseup (out of window) 9414 if (this._mouseStarted) { 9415 this._mouseUp(event); 9416 } 9417 9418 this._mouseDownEvent = event; 9419 9420 var that = this, 9421 btnIsLeft = event.which === 1, 9422 elIsCancel = typeof this.options.cancel === "string" ? 9423 $(event.target).closest(this.options.cancel).length : 9424 false; 9425 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { 9426 return true; 9427 } 9428 9429 this.mouseDelayMet = !this.options.delay; 9430 if (!this.mouseDelayMet) { 9431 this._mouseDelayTimer = setTimeout(function () { 9432 that.mouseDelayMet = true; 9433 }, this.options.delay); 9434 } 9435 9436 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 9437 this._mouseStarted = (this._mouseStart(event) !== false); 9438 if (!this._mouseStarted) { 9439 event.preventDefault(); 9440 return true; 9441 } 9442 } 9443 9444 // Click event may never have fired (Gecko & Opera) 9445 if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) { 9446 $.removeData(event.target, this.widgetName + ".preventClickEvent"); 9447 } 9448 9449 // These delegates are required to keep context 9450 this._mouseMoveDelegate = function (event) { 9451 return that._mouseMove(event); 9452 }; 9453 this._mouseUpDelegate = function (event) { 9454 return that._mouseUp(event); 9455 }; 9456 9457 this.document 9458 .on("mousemove." + this.widgetName, this._mouseMoveDelegate) 9459 .on("mouseup." + this.widgetName, this._mouseUpDelegate); 9460 9461 event.preventDefault(); 9462 9463 mouseHandled = true; 9464 return true; 9465 }, 9466 9467 _mouseMove: function (event) { 9468 9469 // Only check for mouseups outside the document if you've moved inside the document 9470 // at least once. 9471 if (this._mouseMoved && !event.which) { 9472 9473 // Support: Safari <=8 - 9 9474 // Safari sets which to 0 if you press any of the following keys 9475 // during a drag (#14461) 9476 if (event.originalEvent.altKey || event.originalEvent.ctrlKey || 9477 event.originalEvent.metaKey || event.originalEvent.shiftKey) { 9478 this.ignoreMissingWhich = true; 9479 } else if (!this.ignoreMissingWhich) { 9480 return this._mouseUp(event); 9481 } 9482 } 9483 9484 if (event.which || event.button) { 9485 this._mouseMoved = true; 9486 } 9487 9488 if (this._mouseStarted) { 9489 this._mouseDrag(event); 9490 return event.preventDefault(); 9491 } 9492 9493 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 9494 this._mouseStarted = 9495 (this._mouseStart(this._mouseDownEvent, event) !== false); 9496 if (this._mouseStarted) { 9497 this._mouseDrag(event); 9498 } else { 9499 this._mouseUp(event); 9500 } 9501 } 9502 9503 return !this._mouseStarted; 9504 }, 9505 9506 _mouseUp: function (event) { 9507 this.document 9508 .off("mousemove." + this.widgetName, this._mouseMoveDelegate) 9509 .off("mouseup." + this.widgetName, this._mouseUpDelegate); 9510 9511 if (this._mouseStarted) { 9512 this._mouseStarted = false; 9513 9514 if (event.target === this._mouseDownEvent.target) { 9515 $.data(event.target, this.widgetName + ".preventClickEvent", true); 9516 } 9517 9518 this._mouseStop(event); 9519 } 9520 9521 if (this._mouseDelayTimer) { 9522 clearTimeout(this._mouseDelayTimer); 9523 delete this._mouseDelayTimer; 9524 } 9525 9526 this.ignoreMissingWhich = false; 9527 mouseHandled = false; 9528 event.preventDefault(); 9529 }, 9530 9531 _mouseDistanceMet: function (event) { 9532 return (Math.max( 9533 Math.abs(this._mouseDownEvent.pageX - event.pageX), 9534 Math.abs(this._mouseDownEvent.pageY - event.pageY) 9535 ) >= this.options.distance 9536 ); 9537 }, 9538 9539 _mouseDelayMet: function ( /* event */) { 9540 return this.mouseDelayMet; 9541 }, 9542 9543 // These are placeholder methods, to be overriden by extending plugin 9544 _mouseStart: function ( /* event */) { }, 9545 _mouseDrag: function ( /* event */) { }, 9546 _mouseStop: function ( /* event */) { }, 9547 _mouseCapture: function ( /* event */) { 9548 return true; 9549 } 9550 }); 9551 9552 9553 9554 // $.ui.plugin is deprecated. Use $.widget() extensions instead. 9555 var plugin = $.ui.plugin = { 9556 add: function (module, option, set) { 9557 var i, 9558 proto = $.ui[module].prototype; 9559 for (i in set) { 9560 proto.plugins[i] = proto.plugins[i] || []; 9561 proto.plugins[i].push([option, set[i]]); 9562 } 9563 }, 9564 call: function (instance, name, args, allowDisconnected) { 9565 var i, 9566 set = instance.plugins[name]; 9567 9568 if (!set) { 9569 return; 9570 } 9571 9572 if (!allowDisconnected && (!instance.element[0].parentNode || 9573 instance.element[0].parentNode.nodeType === 11)) { 9574 return; 9575 } 9576 9577 for (i = 0; i < set.length; i++) { 9578 if (instance.options[set[i][0]]) { 9579 set[i][1].apply(instance.element, args); 9580 } 9581 } 9582 } 9583 }; 9584 9585 9586 /*! 9587 * jQuery UI Draggable 1.14.1 9588 * https://jqueryui.com 9589 * 9590 * Copyright OpenJS Foundation and other contributors 9591 * Released under the MIT license. 9592 * https://jquery.org/license 9593 */ 9594 9595 //>>label: Draggable 9596 //>>group: Interactions 9597 //>>description: Enables dragging functionality for any element. 9598 //>>docs: https://api.jqueryui.com/draggable/ 9599 //>>demos: https://jqueryui.com/draggable/ 9600 //>>css.structure: ../../themes/base/draggable.css 9601 9602 9603 $.widget("ui.draggable", $.ui.mouse, { 9604 version: "1.14.1", 9605 widgetEventPrefix: "drag", 9606 options: { 9607 addClasses: true, 9608 appendTo: "parent", 9609 axis: false, 9610 connectToSortable: false, 9611 containment: false, 9612 cursor: "auto", 9613 cursorAt: false, 9614 grid: false, 9615 handle: false, 9616 helper: "original", 9617 iframeFix: false, 9618 opacity: false, 9619 refreshPositions: false, 9620 revert: false, 9621 revertDuration: 500, 9622 scope: "default", 9623 scroll: true, 9624 scrollSensitivity: 20, 9625 scrollSpeed: 20, 9626 snap: false, 9627 snapMode: "both", 9628 snapTolerance: 20, 9629 stack: false, 9630 zIndex: false, 9631 9632 // Callbacks 9633 drag: null, 9634 start: null, 9635 stop: null 9636 }, 9637 _create: function () { 9638 9639 if (this.options.helper === "original") { 9640 this._setPositionRelative(); 9641 } 9642 if (this.options.addClasses) { 9643 this._addClass("ui-draggable"); 9644 } 9645 this._setHandleClassName(); 9646 9647 this._mouseInit(); 9648 }, 9649 9650 _setOption: function (key, value) { 9651 this._super(key, value); 9652 if (key === "handle") { 9653 this._removeHandleClassName(); 9654 this._setHandleClassName(); 9655 } 9656 }, 9657 9658 _destroy: function () { 9659 if ((this.helper || this.element).is(".ui-draggable-dragging")) { 9660 this.destroyOnClear = true; 9661 return; 9662 } 9663 this._removeHandleClassName(); 9664 this._mouseDestroy(); 9665 }, 9666 9667 _mouseCapture: function (event) { 9668 var o = this.options; 9669 9670 // Among others, prevent a drag on a resizable-handle 9671 if (this.helper || o.disabled || 9672 $(event.target).closest(".ui-resizable-handle").length > 0) { 9673 return false; 9674 } 9675 9676 //Quit if we're not on a valid handle 9677 this.handle = this._getHandle(event); 9678 if (!this.handle) { 9679 return false; 9680 } 9681 9682 this._blurActiveElement(event); 9683 9684 this._blockFrames(o.iframeFix === true ? "iframe" : o.iframeFix); 9685 9686 return true; 9687 9688 }, 9689 9690 _blockFrames: function (selector) { 9691 this.iframeBlocks = this.document.find(selector).map(function () { 9692 var iframe = $(this); 9693 9694 return $("<div>") 9695 .css("position", "absolute") 9696 .appendTo(iframe.parent()) 9697 .outerWidth(iframe.outerWidth()) 9698 .outerHeight(iframe.outerHeight()) 9699 .offset(iframe.offset())[0]; 9700 }); 9701 }, 9702 9703 _unblockFrames: function () { 9704 if (this.iframeBlocks) { 9705 this.iframeBlocks.remove(); 9706 delete this.iframeBlocks; 9707 } 9708 }, 9709 9710 _blurActiveElement: function (event) { 9711 var activeElement = this.document[0].activeElement, 9712 target = $(event.target); 9713 9714 // Don't blur if the event occurred on an element that is within 9715 // the currently focused element 9716 // See #10527, #12472 9717 if (target.closest(activeElement).length) { 9718 return; 9719 } 9720 9721 // Blur any element that currently has focus, see #4261 9722 $(activeElement).trigger("blur"); 9723 }, 9724 9725 _mouseStart: function (event) { 9726 9727 var o = this.options; 9728 9729 //Create and append the visible helper 9730 this.helper = this._createHelper(event); 9731 9732 this._addClass(this.helper, "ui-draggable-dragging"); 9733 9734 //Cache the helper size 9735 this._cacheHelperProportions(); 9736 9737 //If ddmanager is used for droppables, set the global draggable 9738 if ($.ui.ddmanager) { 9739 $.ui.ddmanager.current = this; 9740 } 9741 9742 /* 9743 * - Position generation - 9744 * This block generates everything position related - it's the core of draggables. 9745 */ 9746 9747 //Cache the margins of the original element 9748 this._cacheMargins(); 9749 9750 //Store the helper's css position 9751 this.cssPosition = this.helper.css("position"); 9752 this.scrollParent = this.helper.scrollParent(true); 9753 this.offsetParent = this.helper.offsetParent(); 9754 this.hasFixedAncestor = this.helper.parents().filter(function () { 9755 return $(this).css("position") === "fixed"; 9756 }).length > 0; 9757 9758 //The element's absolute position on the page minus margins 9759 this.positionAbs = this.element.offset(); 9760 this._refreshOffsets(event); 9761 9762 //Generate the original position 9763 this.originalPosition = this.position = this._generatePosition(event, false); 9764 this.originalPageX = event.pageX; 9765 this.originalPageY = event.pageY; 9766 9767 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 9768 if (o.cursorAt) { 9769 this._adjustOffsetFromHelper(o.cursorAt); 9770 } 9771 9772 //Set a containment if given in the options 9773 this._setContainment(); 9774 9775 //Trigger event + callbacks 9776 if (this._trigger("start", event) === false) { 9777 this._clear(); 9778 return false; 9779 } 9780 9781 //Recache the helper size 9782 this._cacheHelperProportions(); 9783 9784 //Prepare the droppable offsets 9785 if ($.ui.ddmanager && !o.dropBehaviour) { 9786 $.ui.ddmanager.prepareOffsets(this, event); 9787 } 9788 9789 // Execute the drag once - this causes the helper not to be visible before getting its 9790 // correct position 9791 this._mouseDrag(event, true); 9792 9793 // If the ddmanager is used for droppables, inform the manager that dragging has started 9794 // (see #5003) 9795 if ($.ui.ddmanager) { 9796 $.ui.ddmanager.dragStart(this, event); 9797 } 9798 9799 return true; 9800 }, 9801 9802 _refreshOffsets: function (event) { 9803 this.offset = { 9804 top: this.positionAbs.top - this.margins.top, 9805 left: this.positionAbs.left - this.margins.left, 9806 scroll: false, 9807 parent: this._getParentOffset(), 9808 relative: this._getRelativeOffset() 9809 }; 9810 9811 this.offset.click = { 9812 left: event.pageX - this.offset.left, 9813 top: event.pageY - this.offset.top 9814 }; 9815 }, 9816 9817 _mouseDrag: function (event, noPropagation) { 9818 9819 // reset any necessary cached properties (see #5009) 9820 if (this.hasFixedAncestor) { 9821 this.offset.parent = this._getParentOffset(); 9822 } 9823 9824 //Compute the helpers position 9825 this.position = this._generatePosition(event, true); 9826 this.positionAbs = this._convertPositionTo("absolute"); 9827 9828 //Call plugins and callbacks and use the resulting position if something is returned 9829 if (!noPropagation) { 9830 var ui = this._uiHash(); 9831 if (this._trigger("drag", event, ui) === false) { 9832 this._mouseUp(new $.Event("mouseup", event)); 9833 return false; 9834 } 9835 this.position = ui.position; 9836 } 9837 9838 this.helper[0].style.left = this.position.left + "px"; 9839 this.helper[0].style.top = this.position.top + "px"; 9840 9841 if ($.ui.ddmanager) { 9842 $.ui.ddmanager.drag(this, event); 9843 } 9844 9845 return false; 9846 }, 9847 9848 _mouseStop: function (event) { 9849 9850 //If we are using droppables, inform the manager about the drop 9851 var that = this, 9852 dropped = false; 9853 if ($.ui.ddmanager && !this.options.dropBehaviour) { 9854 dropped = $.ui.ddmanager.drop(this, event); 9855 } 9856 9857 //if a drop comes from outside (a sortable) 9858 if (this.dropped) { 9859 dropped = this.dropped; 9860 this.dropped = false; 9861 } 9862 9863 if ((this.options.revert === "invalid" && !dropped) || 9864 (this.options.revert === "valid" && dropped) || 9865 this.options.revert === true || (typeof this.options.revert === "function" && 9866 this.options.revert.call(this.element, dropped)) 9867 ) { 9868 $(this.helper).animate( 9869 this.originalPosition, 9870 parseInt(this.options.revertDuration, 10), 9871 function () { 9872 if (that._trigger("stop", event) !== false) { 9873 that._clear(); 9874 } 9875 } 9876 ); 9877 } else { 9878 if (this._trigger("stop", event) !== false) { 9879 this._clear(); 9880 } 9881 } 9882 9883 return false; 9884 }, 9885 9886 _mouseUp: function (event) { 9887 this._unblockFrames(); 9888 9889 // If the ddmanager is used for droppables, inform the manager that dragging has stopped 9890 // (see #5003) 9891 if ($.ui.ddmanager) { 9892 $.ui.ddmanager.dragStop(this, event); 9893 } 9894 9895 // Only need to focus if the event occurred on the draggable itself, see #10527 9896 if (this.handleElement.is(event.target)) { 9897 9898 // The interaction is over; whether or not the click resulted in a drag, 9899 // focus the element 9900 this.element.trigger("focus"); 9901 } 9902 9903 return $.ui.mouse.prototype._mouseUp.call(this, event); 9904 }, 9905 9906 cancel: function () { 9907 9908 if (this.helper.is(".ui-draggable-dragging")) { 9909 this._mouseUp(new $.Event("mouseup", { target: this.element[0] })); 9910 } else { 9911 this._clear(); 9912 } 9913 9914 return this; 9915 9916 }, 9917 9918 _getHandle: function (event) { 9919 return this.options.handle ? 9920 !!$(event.target).closest(this.element.find(this.options.handle)).length : 9921 true; 9922 }, 9923 9924 _setHandleClassName: function () { 9925 this.handleElement = this.options.handle ? 9926 this.element.find(this.options.handle) : this.element; 9927 this._addClass(this.handleElement, "ui-draggable-handle"); 9928 }, 9929 9930 _removeHandleClassName: function () { 9931 this._removeClass(this.handleElement, "ui-draggable-handle"); 9932 }, 9933 9934 _createHelper: function (event) { 9935 9936 var o = this.options, 9937 helperIsFunction = typeof o.helper === "function", 9938 helper = helperIsFunction ? 9939 $(o.helper.apply(this.element[0], [event])) : 9940 (o.helper === "clone" ? 9941 this.element.clone().removeAttr("id") : 9942 this.element); 9943 9944 if (!helper.parents("body").length) { 9945 helper.appendTo((o.appendTo === "parent" ? 9946 this.element[0].parentNode : 9947 o.appendTo)); 9948 } 9949 9950 // https://bugs.jqueryui.com/ticket/9446 9951 // a helper function can return the original element 9952 // which wouldn't have been set to relative in _create 9953 if (helperIsFunction && helper[0] === this.element[0]) { 9954 this._setPositionRelative(); 9955 } 9956 9957 if (helper[0] !== this.element[0] && 9958 !(/(fixed|absolute)/).test(helper.css("position"))) { 9959 helper.css("position", "absolute"); 9960 } 9961 9962 return helper; 9963 9964 }, 9965 9966 _setPositionRelative: function () { 9967 if (!(/^(?:r|a|f)/).test(this.element.css("position"))) { 9968 this.element[0].style.position = "relative"; 9969 } 9970 }, 9971 9972 _adjustOffsetFromHelper: function (obj) { 9973 if (typeof obj === "string") { 9974 obj = obj.split(" "); 9975 } 9976 if (Array.isArray(obj)) { 9977 obj = { left: +obj[0], top: +obj[1] || 0 }; 9978 } 9979 if ("left" in obj) { 9980 this.offset.click.left = obj.left + this.margins.left; 9981 } 9982 if ("right" in obj) { 9983 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 9984 } 9985 if ("top" in obj) { 9986 this.offset.click.top = obj.top + this.margins.top; 9987 } 9988 if ("bottom" in obj) { 9989 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 9990 } 9991 }, 9992 9993 _isRootNode: function (element) { 9994 return (/(html|body)/i).test(element.tagName) || element === this.document[0]; 9995 }, 9996 9997 _getParentOffset: function () { 9998 9999 //Get the offsetParent and cache its position 10000 var po = this.offsetParent.offset(), 10001 document = this.document[0]; 10002 10003 // This is a special case where we need to modify a offset calculated on start, since the 10004 // following happened: 10005 // 1. The position of the helper is absolute, so it's position is calculated based on the 10006 // next positioned parent 10007 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't 10008 // the document, which means that the scroll is included in the initial calculation of the 10009 // offset of the parent, and never recalculated upon drag 10010 if (this.cssPosition === "absolute" && this.scrollParent[0] !== document && 10011 $.contains(this.scrollParent[0], this.offsetParent[0])) { 10012 po.left += this.scrollParent.scrollLeft(); 10013 po.top += this.scrollParent.scrollTop(); 10014 } 10015 10016 if (this._isRootNode(this.offsetParent[0])) { 10017 po = { top: 0, left: 0 }; 10018 } 10019 10020 return { 10021 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0), 10022 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0) 10023 }; 10024 10025 }, 10026 10027 _getRelativeOffset: function () { 10028 if (this.cssPosition !== "relative") { 10029 return { top: 0, left: 0 }; 10030 } 10031 10032 var p = this.element.position(), 10033 scrollIsRootNode = this._isRootNode(this.scrollParent[0]); 10034 10035 return { 10036 top: p.top - (parseInt(this.helper.css("top"), 10) || 0) + 10037 (!scrollIsRootNode ? this.scrollParent.scrollTop() : 0), 10038 left: p.left - (parseInt(this.helper.css("left"), 10) || 0) + 10039 (!scrollIsRootNode ? this.scrollParent.scrollLeft() : 0) 10040 }; 10041 10042 }, 10043 10044 _cacheMargins: function () { 10045 this.margins = { 10046 left: (parseInt(this.element.css("marginLeft"), 10) || 0), 10047 top: (parseInt(this.element.css("marginTop"), 10) || 0), 10048 right: (parseInt(this.element.css("marginRight"), 10) || 0), 10049 bottom: (parseInt(this.element.css("marginBottom"), 10) || 0) 10050 }; 10051 }, 10052 10053 _cacheHelperProportions: function () { 10054 this.helperProportions = { 10055 width: this.helper.outerWidth(), 10056 height: this.helper.outerHeight() 10057 }; 10058 }, 10059 10060 _setContainment: function () { 10061 10062 var isUserScrollable, c, ce, 10063 o = this.options, 10064 document = this.document[0]; 10065 10066 this.relativeContainer = null; 10067 10068 if (!o.containment) { 10069 this.containment = null; 10070 return; 10071 } 10072 10073 if (o.containment === "window") { 10074 this.containment = [ 10075 $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, 10076 $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top, 10077 $(window).scrollLeft() + $(window).width() - 10078 this.helperProportions.width - this.margins.left, 10079 $(window).scrollTop() + 10080 ($(window).height() || document.body.parentNode.scrollHeight) - 10081 this.helperProportions.height - this.margins.top 10082 ]; 10083 return; 10084 } 10085 10086 if (o.containment === "document") { 10087 this.containment = [ 10088 0, 10089 0, 10090 $(document).width() - this.helperProportions.width - this.margins.left, 10091 ($(document).height() || document.body.parentNode.scrollHeight) - 10092 this.helperProportions.height - this.margins.top 10093 ]; 10094 return; 10095 } 10096 10097 if (o.containment.constructor === Array) { 10098 this.containment = o.containment; 10099 return; 10100 } 10101 10102 if (o.containment === "parent") { 10103 o.containment = this.helper[0].parentNode; 10104 } 10105 10106 c = $(o.containment); 10107 ce = c[0]; 10108 10109 if (!ce) { 10110 return; 10111 } 10112 10113 isUserScrollable = /(scroll|auto)/.test(c.css("overflow")); 10114 10115 this.containment = [ 10116 (parseInt(c.css("borderLeftWidth"), 10) || 0) + 10117 (parseInt(c.css("paddingLeft"), 10) || 0), 10118 (parseInt(c.css("borderTopWidth"), 10) || 0) + 10119 (parseInt(c.css("paddingTop"), 10) || 0), 10120 (isUserScrollable ? Math.max(ce.scrollWidth, ce.offsetWidth) : ce.offsetWidth) - 10121 (parseInt(c.css("borderRightWidth"), 10) || 0) - 10122 (parseInt(c.css("paddingRight"), 10) || 0) - 10123 this.helperProportions.width - 10124 this.margins.left - 10125 this.margins.right, 10126 (isUserScrollable ? Math.max(ce.scrollHeight, ce.offsetHeight) : ce.offsetHeight) - 10127 (parseInt(c.css("borderBottomWidth"), 10) || 0) - 10128 (parseInt(c.css("paddingBottom"), 10) || 0) - 10129 this.helperProportions.height - 10130 this.margins.top - 10131 this.margins.bottom 10132 ]; 10133 this.relativeContainer = c; 10134 }, 10135 10136 _convertPositionTo: function (d, pos) { 10137 10138 if (!pos) { 10139 pos = this.position; 10140 } 10141 10142 var mod = d === "absolute" ? 1 : -1, 10143 scrollIsRootNode = this._isRootNode(this.scrollParent[0]); 10144 10145 return { 10146 top: ( 10147 10148 // The absolute mouse position 10149 pos.top + 10150 10151 // Only for relative positioned nodes: Relative offset from element to offset parent 10152 this.offset.relative.top * mod + 10153 10154 // The offsetParent's offset without borders (offset + border) 10155 this.offset.parent.top * mod - 10156 ((this.cssPosition === "fixed" ? 10157 -this.offset.scroll.top : 10158 (scrollIsRootNode ? 0 : this.offset.scroll.top)) * mod) 10159 ), 10160 left: ( 10161 10162 // The absolute mouse position 10163 pos.left + 10164 10165 // Only for relative positioned nodes: Relative offset from element to offset parent 10166 this.offset.relative.left * mod + 10167 10168 // The offsetParent's offset without borders (offset + border) 10169 this.offset.parent.left * mod - 10170 ((this.cssPosition === "fixed" ? 10171 -this.offset.scroll.left : 10172 (scrollIsRootNode ? 0 : this.offset.scroll.left)) * mod) 10173 ) 10174 }; 10175 10176 }, 10177 10178 _generatePosition: function (event, constrainPosition) { 10179 10180 var containment, co, top, left, 10181 o = this.options, 10182 scrollIsRootNode = this._isRootNode(this.scrollParent[0]), 10183 pageX = event.pageX, 10184 pageY = event.pageY; 10185 10186 // Cache the scroll 10187 if (!scrollIsRootNode || !this.offset.scroll) { 10188 this.offset.scroll = { 10189 top: this.scrollParent.scrollTop(), 10190 left: this.scrollParent.scrollLeft() 10191 }; 10192 } 10193 10194 /* 10195 * - Position constraining - 10196 * Constrain the position to a mix of grid, containment. 10197 */ 10198 10199 // If we are not dragging yet, we won't check for options 10200 if (constrainPosition) { 10201 if (this.containment) { 10202 if (this.relativeContainer) { 10203 co = this.relativeContainer.offset(); 10204 containment = [ 10205 this.containment[0] + co.left, 10206 this.containment[1] + co.top, 10207 this.containment[2] + co.left, 10208 this.containment[3] + co.top 10209 ]; 10210 } else { 10211 containment = this.containment; 10212 } 10213 10214 if (event.pageX - this.offset.click.left < containment[0]) { 10215 pageX = containment[0] + this.offset.click.left; 10216 } 10217 if (event.pageY - this.offset.click.top < containment[1]) { 10218 pageY = containment[1] + this.offset.click.top; 10219 } 10220 if (event.pageX - this.offset.click.left > containment[2]) { 10221 pageX = containment[2] + this.offset.click.left; 10222 } 10223 if (event.pageY - this.offset.click.top > containment[3]) { 10224 pageY = containment[3] + this.offset.click.top; 10225 } 10226 } 10227 10228 if (o.grid) { 10229 10230 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid 10231 // argument errors in IE (see ticket #6950) 10232 top = o.grid[1] ? this.originalPageY + Math.round((pageY - 10233 this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; 10234 pageY = containment ? ((top - this.offset.click.top >= containment[1] || 10235 top - this.offset.click.top > containment[3]) ? 10236 top : 10237 ((top - this.offset.click.top >= containment[1]) ? 10238 top - o.grid[1] : top + o.grid[1])) : top; 10239 10240 left = o.grid[0] ? this.originalPageX + 10241 Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : 10242 this.originalPageX; 10243 pageX = containment ? ((left - this.offset.click.left >= containment[0] || 10244 left - this.offset.click.left > containment[2]) ? 10245 left : 10246 ((left - this.offset.click.left >= containment[0]) ? 10247 left - o.grid[0] : left + o.grid[0])) : left; 10248 } 10249 10250 if (o.axis === "y") { 10251 pageX = this.originalPageX; 10252 } 10253 10254 if (o.axis === "x") { 10255 pageY = this.originalPageY; 10256 } 10257 } 10258 10259 return { 10260 top: ( 10261 10262 // The absolute mouse position 10263 pageY - 10264 10265 // Click offset (relative to the element) 10266 this.offset.click.top - 10267 10268 // Only for relative positioned nodes: Relative offset from element to offset parent 10269 this.offset.relative.top - 10270 10271 // The offsetParent's offset without borders (offset + border) 10272 this.offset.parent.top + 10273 (this.cssPosition === "fixed" ? 10274 -this.offset.scroll.top : 10275 (scrollIsRootNode ? 0 : this.offset.scroll.top)) 10276 ), 10277 left: ( 10278 10279 // The absolute mouse position 10280 pageX - 10281 10282 // Click offset (relative to the element) 10283 this.offset.click.left - 10284 10285 // Only for relative positioned nodes: Relative offset from element to offset parent 10286 this.offset.relative.left - 10287 10288 // The offsetParent's offset without borders (offset + border) 10289 this.offset.parent.left + 10290 (this.cssPosition === "fixed" ? 10291 -this.offset.scroll.left : 10292 (scrollIsRootNode ? 0 : this.offset.scroll.left)) 10293 ) 10294 }; 10295 10296 }, 10297 10298 _clear: function () { 10299 this._removeClass(this.helper, "ui-draggable-dragging"); 10300 if (this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) { 10301 this.helper.remove(); 10302 } 10303 this.helper = null; 10304 this.cancelHelperRemoval = false; 10305 if (this.destroyOnClear) { 10306 this.destroy(); 10307 } 10308 }, 10309 10310 // From now on bulk stuff - mainly helpers 10311 10312 _trigger: function (type, event, ui) { 10313 ui = ui || this._uiHash(); 10314 $.ui.plugin.call(this, type, [event, ui, this], true); 10315 10316 // Absolute position and offset (see #6884 ) have to be recalculated after plugins 10317 if (/^(drag|start|stop)/.test(type)) { 10318 this.positionAbs = this._convertPositionTo("absolute"); 10319 ui.offset = this.positionAbs; 10320 } 10321 return $.Widget.prototype._trigger.call(this, type, event, ui); 10322 }, 10323 10324 plugins: {}, 10325 10326 _uiHash: function () { 10327 return { 10328 helper: this.helper, 10329 position: this.position, 10330 originalPosition: this.originalPosition, 10331 offset: this.positionAbs 10332 }; 10333 } 10334 10335 }); 10336 10337 $.ui.plugin.add("draggable", "connectToSortable", { 10338 start: function (event, ui, draggable) { 10339 var uiSortable = $.extend({}, ui, { 10340 item: draggable.element 10341 }); 10342 10343 draggable.sortables = []; 10344 $(draggable.options.connectToSortable).each(function () { 10345 var sortable = $(this).sortable("instance"); 10346 10347 if (sortable && !sortable.options.disabled) { 10348 draggable.sortables.push(sortable); 10349 10350 // RefreshPositions is called at drag start to refresh the containerCache 10351 // which is used in drag. This ensures it's initialized and synchronized 10352 // with any changes that might have happened on the page since initialization. 10353 sortable.refreshPositions(); 10354 sortable._trigger("activate", event, uiSortable); 10355 } 10356 }); 10357 }, 10358 stop: function (event, ui, draggable) { 10359 var uiSortable = $.extend({}, ui, { 10360 item: draggable.element 10361 }); 10362 10363 draggable.cancelHelperRemoval = false; 10364 10365 $.each(draggable.sortables, function () { 10366 var sortable = this; 10367 10368 if (sortable.isOver) { 10369 sortable.isOver = 0; 10370 10371 // Allow this sortable to handle removing the helper 10372 draggable.cancelHelperRemoval = true; 10373 sortable.cancelHelperRemoval = false; 10374 10375 // Use _storedCSS To restore properties in the sortable, 10376 // as this also handles revert (#9675) since the draggable 10377 // may have modified them in unexpected ways (#8809) 10378 sortable._storedCSS = { 10379 position: sortable.placeholder.css("position"), 10380 top: sortable.placeholder.css("top"), 10381 left: sortable.placeholder.css("left") 10382 }; 10383 10384 sortable._mouseStop(event); 10385 10386 // Once drag has ended, the sortable should return to using 10387 // its original helper, not the shared helper from draggable 10388 sortable.options.helper = sortable.options._helper; 10389 } else { 10390 10391 // Prevent this Sortable from removing the helper. 10392 // However, don't set the draggable to remove the helper 10393 // either as another connected Sortable may yet handle the removal. 10394 sortable.cancelHelperRemoval = true; 10395 10396 sortable._trigger("deactivate", event, uiSortable); 10397 } 10398 }); 10399 }, 10400 drag: function (event, ui, draggable) { 10401 $.each(draggable.sortables, function () { 10402 var innermostIntersecting = false, 10403 sortable = this; 10404 10405 // Copy over variables that sortable's _intersectsWith uses 10406 sortable.positionAbs = draggable.positionAbs; 10407 sortable.helperProportions = draggable.helperProportions; 10408 sortable.offset.click = draggable.offset.click; 10409 10410 if (sortable._intersectsWith(sortable.containerCache)) { 10411 innermostIntersecting = true; 10412 10413 $.each(draggable.sortables, function () { 10414 10415 // Copy over variables that sortable's _intersectsWith uses 10416 this.positionAbs = draggable.positionAbs; 10417 this.helperProportions = draggable.helperProportions; 10418 this.offset.click = draggable.offset.click; 10419 10420 if (this !== sortable && 10421 this._intersectsWith(this.containerCache) && 10422 $.contains(sortable.element[0], this.element[0])) { 10423 innermostIntersecting = false; 10424 } 10425 10426 return innermostIntersecting; 10427 }); 10428 } 10429 10430 if (innermostIntersecting) { 10431 10432 // If it intersects, we use a little isOver variable and set it once, 10433 // so that the move-in stuff gets fired only once. 10434 if (!sortable.isOver) { 10435 sortable.isOver = 1; 10436 10437 // Store draggable's parent in case we need to reappend to it later. 10438 draggable._parent = ui.helper.parent(); 10439 10440 sortable.currentItem = ui.helper 10441 .appendTo(sortable.element) 10442 .data("ui-sortable-item", true); 10443 10444 // Store helper option to later restore it 10445 sortable.options._helper = sortable.options.helper; 10446 10447 sortable.options.helper = function () { 10448 return ui.helper[0]; 10449 }; 10450 10451 // Fire the start events of the sortable with our passed browser event, 10452 // and our own helper (so it doesn't create a new one) 10453 event.target = sortable.currentItem[0]; 10454 sortable._mouseCapture(event, true); 10455 sortable._mouseStart(event, true, true); 10456 10457 // Because the browser event is way off the new appended portlet, 10458 // modify necessary variables to reflect the changes 10459 sortable.offset.click.top = draggable.offset.click.top; 10460 sortable.offset.click.left = draggable.offset.click.left; 10461 sortable.offset.parent.left -= draggable.offset.parent.left - 10462 sortable.offset.parent.left; 10463 sortable.offset.parent.top -= draggable.offset.parent.top - 10464 sortable.offset.parent.top; 10465 10466 draggable._trigger("toSortable", event); 10467 10468 // Inform draggable that the helper is in a valid drop zone, 10469 // used solely in the revert option to handle "valid/invalid". 10470 draggable.dropped = sortable.element; 10471 10472 // Need to refreshPositions of all sortables in the case that 10473 // adding to one sortable changes the location of the other sortables (#9675) 10474 $.each(draggable.sortables, function () { 10475 this.refreshPositions(); 10476 }); 10477 10478 // Hack so receive/update callbacks work (mostly) 10479 draggable.currentItem = draggable.element; 10480 sortable.fromOutside = draggable; 10481 } 10482 10483 if (sortable.currentItem) { 10484 sortable._mouseDrag(event); 10485 10486 // Copy the sortable's position because the draggable's can potentially reflect 10487 // a relative position, while sortable is always absolute, which the dragged 10488 // element has now become. (#8809) 10489 ui.position = sortable.position; 10490 } 10491 } else { 10492 10493 // If it doesn't intersect with the sortable, and it intersected before, 10494 // we fake the drag stop of the sortable, but make sure it doesn't remove 10495 // the helper by using cancelHelperRemoval. 10496 if (sortable.isOver) { 10497 10498 sortable.isOver = 0; 10499 sortable.cancelHelperRemoval = true; 10500 10501 // Calling sortable's mouseStop would trigger a revert, 10502 // so revert must be temporarily false until after mouseStop is called. 10503 sortable.options._revert = sortable.options.revert; 10504 sortable.options.revert = false; 10505 10506 sortable._trigger("out", event, sortable._uiHash(sortable)); 10507 sortable._mouseStop(event, true); 10508 10509 // Restore sortable behaviors that were modfied 10510 // when the draggable entered the sortable area (#9481) 10511 sortable.options.revert = sortable.options._revert; 10512 sortable.options.helper = sortable.options._helper; 10513 10514 if (sortable.placeholder) { 10515 sortable.placeholder.remove(); 10516 } 10517 10518 // Restore and recalculate the draggable's offset considering the sortable 10519 // may have modified them in unexpected ways. (#8809, #10669) 10520 ui.helper.appendTo(draggable._parent); 10521 draggable._refreshOffsets(event); 10522 ui.position = draggable._generatePosition(event, true); 10523 10524 draggable._trigger("fromSortable", event); 10525 10526 // Inform draggable that the helper is no longer in a valid drop zone 10527 draggable.dropped = false; 10528 10529 // Need to refreshPositions of all sortables just in case removing 10530 // from one sortable changes the location of other sortables (#9675) 10531 $.each(draggable.sortables, function () { 10532 this.refreshPositions(); 10533 }); 10534 } 10535 } 10536 }); 10537 } 10538 }); 10539 10540 $.ui.plugin.add("draggable", "cursor", { 10541 start: function (event, ui, instance) { 10542 var t = $("body"), 10543 o = instance.options; 10544 10545 if (t.css("cursor")) { 10546 o._cursor = t.css("cursor"); 10547 } 10548 t.css("cursor", o.cursor); 10549 }, 10550 stop: function (event, ui, instance) { 10551 var o = instance.options; 10552 if (o._cursor) { 10553 $("body").css("cursor", o._cursor); 10554 } 10555 } 10556 }); 10557 10558 $.ui.plugin.add("draggable", "opacity", { 10559 start: function (event, ui, instance) { 10560 var t = $(ui.helper), 10561 o = instance.options; 10562 if (t.css("opacity")) { 10563 o._opacity = t.css("opacity"); 10564 } 10565 t.css("opacity", o.opacity); 10566 }, 10567 stop: function (event, ui, instance) { 10568 var o = instance.options; 10569 if (o._opacity) { 10570 $(ui.helper).css("opacity", o._opacity); 10571 } 10572 } 10573 }); 10574 10575 $.ui.plugin.add("draggable", "scroll", { 10576 start: function (event, ui, i) { 10577 if (!i.scrollParentNotHidden) { 10578 i.scrollParentNotHidden = i.helper.scrollParent(false); 10579 } 10580 10581 if (i.scrollParentNotHidden[0] !== i.document[0] && 10582 i.scrollParentNotHidden[0].tagName !== "HTML") { 10583 i.overflowOffset = i.scrollParentNotHidden.offset(); 10584 } 10585 }, 10586 drag: function (event, ui, i) { 10587 10588 var o = i.options, 10589 scrolled = false, 10590 scrollParent = i.scrollParentNotHidden[0], 10591 document = i.document[0]; 10592 10593 if (scrollParent !== document && scrollParent.tagName !== "HTML") { 10594 if (!o.axis || o.axis !== "x") { 10595 if ((i.overflowOffset.top + scrollParent.offsetHeight) - event.pageY < 10596 o.scrollSensitivity) { 10597 scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed; 10598 } else if (event.pageY - i.overflowOffset.top < o.scrollSensitivity) { 10599 scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed; 10600 } 10601 } 10602 10603 if (!o.axis || o.axis !== "y") { 10604 if ((i.overflowOffset.left + scrollParent.offsetWidth) - event.pageX < 10605 o.scrollSensitivity) { 10606 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed; 10607 } else if (event.pageX - i.overflowOffset.left < o.scrollSensitivity) { 10608 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed; 10609 } 10610 } 10611 10612 } else { 10613 10614 if (!o.axis || o.axis !== "x") { 10615 if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) { 10616 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); 10617 } else if ($(window).height() - (event.pageY - $(document).scrollTop()) < 10618 o.scrollSensitivity) { 10619 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); 10620 } 10621 } 10622 10623 if (!o.axis || o.axis !== "y") { 10624 if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { 10625 scrolled = $(document).scrollLeft( 10626 $(document).scrollLeft() - o.scrollSpeed 10627 ); 10628 } else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < 10629 o.scrollSensitivity) { 10630 scrolled = $(document).scrollLeft( 10631 $(document).scrollLeft() + o.scrollSpeed 10632 ); 10633 } 10634 } 10635 10636 } 10637 10638 if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { 10639 $.ui.ddmanager.prepareOffsets(i, event); 10640 } 10641 10642 } 10643 }); 10644 10645 $.ui.plugin.add("draggable", "snap", { 10646 start: function (event, ui, i) { 10647 10648 var o = i.options; 10649 10650 i.snapElements = []; 10651 10652 $(o.snap.constructor !== String ? (o.snap.items || ":data(ui-draggable)") : o.snap) 10653 .each(function () { 10654 var $t = $(this), 10655 $o = $t.offset(); 10656 if (this !== i.element[0]) { 10657 i.snapElements.push({ 10658 item: this, 10659 width: $t.outerWidth(), height: $t.outerHeight(), 10660 top: $o.top, left: $o.left 10661 }); 10662 } 10663 }); 10664 10665 }, 10666 drag: function (event, ui, inst) { 10667 10668 var ts, bs, ls, rs, l, r, t, b, i, first, 10669 o = inst.options, 10670 d = o.snapTolerance, 10671 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, 10672 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; 10673 10674 for (i = inst.snapElements.length - 1; i >= 0; i--) { 10675 10676 l = inst.snapElements[i].left - inst.margins.left; 10677 r = l + inst.snapElements[i].width; 10678 t = inst.snapElements[i].top - inst.margins.top; 10679 b = t + inst.snapElements[i].height; 10680 10681 if (x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || 10682 !$.contains(inst.snapElements[i].item.ownerDocument, 10683 inst.snapElements[i].item)) { 10684 if (inst.snapElements[i].snapping) { 10685 if (inst.options.snap.release) { 10686 inst.options.snap.release.call( 10687 inst.element, 10688 event, 10689 $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }) 10690 ); 10691 } 10692 } 10693 inst.snapElements[i].snapping = false; 10694 continue; 10695 } 10696 10697 if (o.snapMode !== "inner") { 10698 ts = Math.abs(t - y2) <= d; 10699 bs = Math.abs(b - y1) <= d; 10700 ls = Math.abs(l - x2) <= d; 10701 rs = Math.abs(r - x1) <= d; 10702 if (ts) { 10703 ui.position.top = inst._convertPositionTo("relative", { 10704 top: t - inst.helperProportions.height, 10705 left: 0 10706 }).top; 10707 } 10708 if (bs) { 10709 ui.position.top = inst._convertPositionTo("relative", { 10710 top: b, 10711 left: 0 10712 }).top; 10713 } 10714 if (ls) { 10715 ui.position.left = inst._convertPositionTo("relative", { 10716 top: 0, 10717 left: l - inst.helperProportions.width 10718 }).left; 10719 } 10720 if (rs) { 10721 ui.position.left = inst._convertPositionTo("relative", { 10722 top: 0, 10723 left: r 10724 }).left; 10725 } 10726 } 10727 10728 first = (ts || bs || ls || rs); 10729 10730 if (o.snapMode !== "outer") { 10731 ts = Math.abs(t - y1) <= d; 10732 bs = Math.abs(b - y2) <= d; 10733 ls = Math.abs(l - x1) <= d; 10734 rs = Math.abs(r - x2) <= d; 10735 if (ts) { 10736 ui.position.top = inst._convertPositionTo("relative", { 10737 top: t, 10738 left: 0 10739 }).top; 10740 } 10741 if (bs) { 10742 ui.position.top = inst._convertPositionTo("relative", { 10743 top: b - inst.helperProportions.height, 10744 left: 0 10745 }).top; 10746 } 10747 if (ls) { 10748 ui.position.left = inst._convertPositionTo("relative", { 10749 top: 0, 10750 left: l 10751 }).left; 10752 } 10753 if (rs) { 10754 ui.position.left = inst._convertPositionTo("relative", { 10755 top: 0, 10756 left: r - inst.helperProportions.width 10757 }).left; 10758 } 10759 } 10760 10761 if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) { 10762 if (inst.options.snap.snap) { 10763 inst.options.snap.snap.call( 10764 inst.element, 10765 event, 10766 $.extend(inst._uiHash(), { 10767 snapItem: inst.snapElements[i].item 10768 })); 10769 } 10770 } 10771 inst.snapElements[i].snapping = (ts || bs || ls || rs || first); 10772 10773 } 10774 10775 } 10776 }); 10777 10778 $.ui.plugin.add("draggable", "stack", { 10779 start: function (event, ui, instance) { 10780 var min, 10781 o = instance.options, 10782 group = $.makeArray($(o.stack)).sort(function (a, b) { 10783 return (parseInt($(a).css("zIndex"), 10) || 0) - 10784 (parseInt($(b).css("zIndex"), 10) || 0); 10785 }); 10786 10787 if (!group.length) { 10788 return; 10789 } 10790 10791 min = parseInt($(group[0]).css("zIndex"), 10) || 0; 10792 $(group).each(function (i) { 10793 $(this).css("zIndex", min + i); 10794 }); 10795 this.css("zIndex", (min + group.length)); 10796 } 10797 }); 10798 10799 $.ui.plugin.add("draggable", "zIndex", { 10800 start: function (event, ui, instance) { 10801 var t = $(ui.helper), 10802 o = instance.options; 10803 10804 if (t.css("zIndex")) { 10805 o._zIndex = t.css("zIndex"); 10806 } 10807 t.css("zIndex", o.zIndex); 10808 }, 10809 stop: function (event, ui, instance) { 10810 var o = instance.options; 10811 10812 if (o._zIndex) { 10813 $(ui.helper).css("zIndex", o._zIndex); 10814 } 10815 } 10816 }); 10817 10818 var widgetsDraggable = $.ui.draggable; 10819 10820 10821 /*! 10822 * jQuery UI Resizable 1.14.1 10823 * https://jqueryui.com 10824 * 10825 * Copyright OpenJS Foundation and other contributors 10826 * Released under the MIT license. 10827 * https://jquery.org/license 10828 */ 10829 10830 //>>label: Resizable 10831 //>>group: Interactions 10832 //>>description: Enables resize functionality for any element. 10833 //>>docs: https://api.jqueryui.com/resizable/ 10834 //>>demos: https://jqueryui.com/resizable/ 10835 //>>css.structure: ../../themes/base/core.css 10836 //>>css.structure: ../../themes/base/resizable.css 10837 //>>css.theme: ../../themes/base/theme.css 10838 10839 10840 $.widget("ui.resizable", $.ui.mouse, { 10841 version: "1.14.1", 10842 widgetEventPrefix: "resize", 10843 options: { 10844 alsoResize: false, 10845 animate: false, 10846 animateDuration: "slow", 10847 animateEasing: "swing", 10848 aspectRatio: false, 10849 autoHide: false, 10850 classes: { 10851 "ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se" 10852 }, 10853 containment: false, 10854 ghost: false, 10855 grid: false, 10856 handles: "e,s,se", 10857 helper: false, 10858 maxHeight: null, 10859 maxWidth: null, 10860 minHeight: 10, 10861 minWidth: 10, 10862 10863 // See #7960 10864 zIndex: 90, 10865 10866 // Callbacks 10867 resize: null, 10868 start: null, 10869 stop: null 10870 }, 10871 10872 _num: function (value) { 10873 return parseFloat(value) || 0; 10874 }, 10875 10876 _isNumber: function (value) { 10877 return !isNaN(parseFloat(value)); 10878 }, 10879 10880 _hasScroll: function (el, a) { 10881 10882 var scroll, 10883 has = false, 10884 overflow = $(el).css("overflow"); 10885 10886 if (overflow === "hidden") { 10887 return false; 10888 } 10889 if (overflow === "scroll") { 10890 return true; 10891 } 10892 10893 scroll = (a && a === "left") ? "scrollLeft" : "scrollTop"; 10894 10895 if (el[scroll] > 0) { 10896 return true; 10897 } 10898 10899 // TODO: determine which cases actually cause this to happen 10900 // if the element doesn't have the scroll set, see if it's possible to 10901 // set the scroll 10902 try { 10903 el[scroll] = 1; 10904 has = (el[scroll] > 0); 10905 el[scroll] = 0; 10906 } catch (e) { 10907 10908 // `el` might be a string, then setting `scroll` will throw 10909 // an error in strict mode; ignore it. 10910 } 10911 return has; 10912 }, 10913 10914 _create: function () { 10915 10916 var margins, 10917 o = this.options, 10918 that = this; 10919 this._addClass("ui-resizable"); 10920 10921 $.extend(this, { 10922 _aspectRatio: !!(o.aspectRatio), 10923 aspectRatio: o.aspectRatio, 10924 originalElement: this.element, 10925 _proportionallyResizeElements: [], 10926 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null 10927 }); 10928 10929 // Wrap the element if it cannot hold child nodes 10930 if (this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)) { 10931 10932 this.element.wrap( 10933 $("<div class='ui-wrapper'></div>").css({ 10934 overflow: "hidden", 10935 position: this.element.css("position"), 10936 width: this.element.outerWidth(), 10937 height: this.element.outerHeight(), 10938 top: this.element.css("top"), 10939 left: this.element.css("left") 10940 }) 10941 ); 10942 10943 this.element = this.element.parent().data( 10944 "ui-resizable", this.element.resizable("instance") 10945 ); 10946 10947 this.elementIsWrapper = true; 10948 10949 margins = { 10950 marginTop: this.originalElement.css("marginTop"), 10951 marginRight: this.originalElement.css("marginRight"), 10952 marginBottom: this.originalElement.css("marginBottom"), 10953 marginLeft: this.originalElement.css("marginLeft") 10954 }; 10955 10956 this.element.css(margins); 10957 10958 // Support: Safari 10959 // Prevent Safari textarea resize 10960 this.originalResizeStyle = this.originalElement.css("resize"); 10961 this.originalElement.css("resize", "none"); 10962 10963 this._proportionallyResizeElements.push(this.originalElement.css({ 10964 position: "static", 10965 zoom: 1, 10966 display: "block" 10967 })); 10968 10969 this._proportionallyResize(); 10970 } 10971 10972 this._setupHandles(); 10973 10974 if (o.autoHide) { 10975 $(this.element) 10976 .on("mouseenter", function () { 10977 if (o.disabled) { 10978 return; 10979 } 10980 that._removeClass("ui-resizable-autohide"); 10981 that._handles.show(); 10982 }) 10983 .on("mouseleave", function () { 10984 if (o.disabled) { 10985 return; 10986 } 10987 if (!that.resizing) { 10988 that._addClass("ui-resizable-autohide"); 10989 that._handles.hide(); 10990 } 10991 }); 10992 } 10993 10994 this._mouseInit(); 10995 }, 10996 10997 _destroy: function () { 10998 10999 this._mouseDestroy(); 11000 this._addedHandles.remove(); 11001 11002 var wrapper, 11003 _destroy = function (exp) { 11004 $(exp) 11005 .removeData("resizable") 11006 .removeData("ui-resizable") 11007 .off(".resizable"); 11008 }; 11009 11010 // TODO: Unwrap at same DOM position 11011 if (this.elementIsWrapper) { 11012 _destroy(this.element); 11013 wrapper = this.element; 11014 this.originalElement.css({ 11015 position: wrapper.css("position"), 11016 width: wrapper.outerWidth(), 11017 height: wrapper.outerHeight(), 11018 top: wrapper.css("top"), 11019 left: wrapper.css("left") 11020 }).insertAfter(wrapper); 11021 wrapper.remove(); 11022 } 11023 11024 this.originalElement.css("resize", this.originalResizeStyle); 11025 _destroy(this.originalElement); 11026 11027 return this; 11028 }, 11029 11030 _setOption: function (key, value) { 11031 this._super(key, value); 11032 11033 switch (key) { 11034 case "handles": 11035 this._removeHandles(); 11036 this._setupHandles(); 11037 break; 11038 case "aspectRatio": 11039 this._aspectRatio = !!value; 11040 break; 11041 default: 11042 break; 11043 } 11044 }, 11045 11046 _setupHandles: function () { 11047 var o = this.options, handle, i, n, hname, axis, that = this; 11048 this.handles = o.handles || 11049 (!$(".ui-resizable-handle", this.element).length ? 11050 "e,s,se" : { 11051 n: ".ui-resizable-n", 11052 e: ".ui-resizable-e", 11053 s: ".ui-resizable-s", 11054 w: ".ui-resizable-w", 11055 se: ".ui-resizable-se", 11056 sw: ".ui-resizable-sw", 11057 ne: ".ui-resizable-ne", 11058 nw: ".ui-resizable-nw" 11059 }); 11060 11061 this._handles = $(); 11062 this._addedHandles = $(); 11063 if (this.handles.constructor === String) { 11064 11065 if (this.handles === "all") { 11066 this.handles = "n,e,s,w,se,sw,ne,nw"; 11067 } 11068 11069 n = this.handles.split(","); 11070 this.handles = {}; 11071 11072 for (i = 0; i < n.length; i++) { 11073 11074 handle = String.prototype.trim.call(n[i]); 11075 hname = "ui-resizable-" + handle; 11076 axis = $("<div>"); 11077 this._addClass(axis, "ui-resizable-handle " + hname); 11078 11079 axis.css({ zIndex: o.zIndex }); 11080 11081 this.handles[handle] = ".ui-resizable-" + handle; 11082 if (!this.element.children(this.handles[handle]).length) { 11083 this.element.append(axis); 11084 this._addedHandles = this._addedHandles.add(axis); 11085 } 11086 } 11087 11088 } 11089 11090 this._renderAxis = function (target) { 11091 11092 var i, axis, padPos, padWrapper; 11093 11094 target = target || this.element; 11095 11096 for (i in this.handles) { 11097 11098 if (this.handles[i].constructor === String) { 11099 this.handles[i] = this.element.children(this.handles[i]).first().show(); 11100 } else if (this.handles[i].jquery || this.handles[i].nodeType) { 11101 this.handles[i] = $(this.handles[i]); 11102 this._on(this.handles[i], { "mousedown": that._mouseDown }); 11103 } 11104 11105 if (this.elementIsWrapper && 11106 this.originalElement[0] 11107 .nodeName 11108 .match(/^(textarea|input|select|button)$/i)) { 11109 axis = $(this.handles[i], this.element); 11110 11111 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? 11112 axis.outerHeight() : 11113 axis.outerWidth(); 11114 11115 padPos = ["padding", 11116 /ne|nw|n/.test(i) ? "Top" : 11117 /se|sw|s/.test(i) ? "Bottom" : 11118 /^e$/.test(i) ? "Right" : "Left"].join(""); 11119 11120 target.css(padPos, padWrapper); 11121 11122 this._proportionallyResize(); 11123 } 11124 11125 this._handles = this._handles.add(this.handles[i]); 11126 } 11127 }; 11128 11129 // TODO: make renderAxis a prototype function 11130 this._renderAxis(this.element); 11131 11132 this._handles = this._handles.add(this.element.find(".ui-resizable-handle")); 11133 this._handles.disableSelection(); 11134 11135 this._handles.on("mouseover", function () { 11136 if (!that.resizing) { 11137 if (this.className) { 11138 axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); 11139 } 11140 that.axis = axis && axis[1] ? axis[1] : "se"; 11141 } 11142 }); 11143 11144 if (o.autoHide) { 11145 this._handles.hide(); 11146 this._addClass("ui-resizable-autohide"); 11147 } 11148 }, 11149 11150 _removeHandles: function () { 11151 this._addedHandles.remove(); 11152 }, 11153 11154 _mouseCapture: function (event) { 11155 var i, handle, 11156 capture = false; 11157 11158 for (i in this.handles) { 11159 handle = $(this.handles[i])[0]; 11160 if (handle === event.target || $.contains(handle, event.target)) { 11161 capture = true; 11162 } 11163 } 11164 11165 return !this.options.disabled && capture; 11166 }, 11167 11168 _mouseStart: function (event) { 11169 11170 var curleft, curtop, cursor, calculatedSize, 11171 o = this.options, 11172 el = this.element; 11173 11174 this.resizing = true; 11175 11176 this._renderProxy(); 11177 11178 curleft = this._num(this.helper.css("left")); 11179 curtop = this._num(this.helper.css("top")); 11180 11181 if (o.containment) { 11182 curleft += $(o.containment).scrollLeft() || 0; 11183 curtop += $(o.containment).scrollTop() || 0; 11184 } 11185 11186 this.offset = this.helper.offset(); 11187 this.position = { left: curleft, top: curtop }; 11188 11189 if (!this._helper) { 11190 calculatedSize = this._calculateAdjustedElementDimensions(el); 11191 } 11192 11193 this.size = this._helper ? { 11194 width: this.helper.width(), 11195 height: this.helper.height() 11196 } : { 11197 width: calculatedSize.width, 11198 height: calculatedSize.height 11199 }; 11200 11201 this.originalSize = this._helper ? { 11202 width: el.outerWidth(), 11203 height: el.outerHeight() 11204 } : { 11205 width: calculatedSize.width, 11206 height: calculatedSize.height 11207 }; 11208 11209 this.sizeDiff = { 11210 width: el.outerWidth() - el.width(), 11211 height: el.outerHeight() - el.height() 11212 }; 11213 11214 this.originalPosition = { left: curleft, top: curtop }; 11215 this.originalMousePosition = { left: event.pageX, top: event.pageY }; 11216 11217 this.aspectRatio = (typeof o.aspectRatio === "number") ? 11218 o.aspectRatio : 11219 ((this.originalSize.width / this.originalSize.height) || 1); 11220 11221 cursor = $(".ui-resizable-" + this.axis).css("cursor"); 11222 $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor); 11223 11224 this._addClass("ui-resizable-resizing"); 11225 this._propagate("start", event); 11226 return true; 11227 }, 11228 11229 _mouseDrag: function (event) { 11230 11231 var data, props, 11232 smp = this.originalMousePosition, 11233 a = this.axis, 11234 dx = (event.pageX - smp.left) || 0, 11235 dy = (event.pageY - smp.top) || 0, 11236 trigger = this._change[a]; 11237 11238 this._updatePrevProperties(); 11239 11240 if (!trigger) { 11241 return false; 11242 } 11243 11244 data = trigger.apply(this, [event, dx, dy]); 11245 11246 this._updateVirtualBoundaries(event.shiftKey); 11247 if (this._aspectRatio || event.shiftKey) { 11248 data = this._updateRatio(data, event); 11249 } 11250 11251 data = this._respectSize(data, event); 11252 11253 this._updateCache(data); 11254 11255 this._propagate("resize", event); 11256 11257 props = this._applyChanges(); 11258 11259 if (!this._helper && this._proportionallyResizeElements.length) { 11260 this._proportionallyResize(); 11261 } 11262 11263 if (!$.isEmptyObject(props)) { 11264 this._updatePrevProperties(); 11265 this._trigger("resize", event, this.ui()); 11266 this._applyChanges(); 11267 } 11268 11269 return false; 11270 }, 11271 11272 _mouseStop: function (event) { 11273 11274 this.resizing = false; 11275 var pr, ista, soffseth, soffsetw, s, left, top, 11276 o = this.options, that = this; 11277 11278 if (this._helper) { 11279 11280 pr = this._proportionallyResizeElements; 11281 ista = pr.length && (/textarea/i).test(pr[0].nodeName); 11282 soffseth = ista && this._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height; 11283 soffsetw = ista ? 0 : that.sizeDiff.width; 11284 11285 s = { 11286 width: (that.helper.width() - soffsetw), 11287 height: (that.helper.height() - soffseth) 11288 }; 11289 left = (parseFloat(that.element.css("left")) + 11290 (that.position.left - that.originalPosition.left)) || null; 11291 top = (parseFloat(that.element.css("top")) + 11292 (that.position.top - that.originalPosition.top)) || null; 11293 11294 if (!o.animate) { 11295 this.element.css($.extend(s, { top: top, left: left })); 11296 } 11297 11298 that.helper.height(that.size.height); 11299 that.helper.width(that.size.width); 11300 11301 if (this._helper && !o.animate) { 11302 this._proportionallyResize(); 11303 } 11304 } 11305 11306 $("body").css("cursor", "auto"); 11307 11308 this._removeClass("ui-resizable-resizing"); 11309 11310 this._propagate("stop", event); 11311 11312 if (this._helper) { 11313 this.helper.remove(); 11314 } 11315 11316 return false; 11317 11318 }, 11319 11320 _updatePrevProperties: function () { 11321 this.prevPosition = { 11322 top: this.position.top, 11323 left: this.position.left 11324 }; 11325 this.prevSize = { 11326 width: this.size.width, 11327 height: this.size.height 11328 }; 11329 }, 11330 11331 _applyChanges: function () { 11332 var props = {}; 11333 11334 if (this.position.top !== this.prevPosition.top) { 11335 props.top = this.position.top + "px"; 11336 } 11337 if (this.position.left !== this.prevPosition.left) { 11338 props.left = this.position.left + "px"; 11339 } 11340 11341 this.helper.css(props); 11342 11343 if (this.size.width !== this.prevSize.width) { 11344 props.width = this.size.width + "px"; 11345 this.helper.width(props.width); 11346 } 11347 if (this.size.height !== this.prevSize.height) { 11348 props.height = this.size.height + "px"; 11349 this.helper.height(props.height); 11350 } 11351 11352 return props; 11353 }, 11354 11355 _updateVirtualBoundaries: function (forceAspectRatio) { 11356 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, 11357 o = this.options; 11358 11359 b = { 11360 minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0, 11361 maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity, 11362 minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0, 11363 maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity 11364 }; 11365 11366 if (this._aspectRatio || forceAspectRatio) { 11367 pMinWidth = b.minHeight * this.aspectRatio; 11368 pMinHeight = b.minWidth / this.aspectRatio; 11369 pMaxWidth = b.maxHeight * this.aspectRatio; 11370 pMaxHeight = b.maxWidth / this.aspectRatio; 11371 11372 if (pMinWidth > b.minWidth) { 11373 b.minWidth = pMinWidth; 11374 } 11375 if (pMinHeight > b.minHeight) { 11376 b.minHeight = pMinHeight; 11377 } 11378 if (pMaxWidth < b.maxWidth) { 11379 b.maxWidth = pMaxWidth; 11380 } 11381 if (pMaxHeight < b.maxHeight) { 11382 b.maxHeight = pMaxHeight; 11383 } 11384 } 11385 this._vBoundaries = b; 11386 }, 11387 11388 _updateCache: function (data) { 11389 this.offset = this.helper.offset(); 11390 if (this._isNumber(data.left)) { 11391 this.position.left = data.left; 11392 } 11393 if (this._isNumber(data.top)) { 11394 this.position.top = data.top; 11395 } 11396 if (this._isNumber(data.height)) { 11397 this.size.height = data.height; 11398 } 11399 if (this._isNumber(data.width)) { 11400 this.size.width = data.width; 11401 } 11402 }, 11403 11404 _updateRatio: function (data) { 11405 11406 var cpos = this.position, 11407 csize = this.size, 11408 a = this.axis; 11409 11410 if (this._isNumber(data.height)) { 11411 data.width = (data.height * this.aspectRatio); 11412 } else if (this._isNumber(data.width)) { 11413 data.height = (data.width / this.aspectRatio); 11414 } 11415 11416 if (a === "sw") { 11417 data.left = cpos.left + (csize.width - data.width); 11418 data.top = null; 11419 } 11420 if (a === "nw") { 11421 data.top = cpos.top + (csize.height - data.height); 11422 data.left = cpos.left + (csize.width - data.width); 11423 } 11424 11425 return data; 11426 }, 11427 11428 _respectSize: function (data) { 11429 11430 var o = this._vBoundaries, 11431 a = this.axis, 11432 ismaxw = this._isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), 11433 ismaxh = this._isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), 11434 isminw = this._isNumber(data.width) && o.minWidth && (o.minWidth > data.width), 11435 isminh = this._isNumber(data.height) && o.minHeight && (o.minHeight > data.height), 11436 dw = this.originalPosition.left + this.originalSize.width, 11437 dh = this.originalPosition.top + this.originalSize.height, 11438 cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); 11439 if (isminw) { 11440 data.width = o.minWidth; 11441 } 11442 if (isminh) { 11443 data.height = o.minHeight; 11444 } 11445 if (ismaxw) { 11446 data.width = o.maxWidth; 11447 } 11448 if (ismaxh) { 11449 data.height = o.maxHeight; 11450 } 11451 11452 if (isminw && cw) { 11453 data.left = dw - o.minWidth; 11454 } 11455 if (ismaxw && cw) { 11456 data.left = dw - o.maxWidth; 11457 } 11458 if (isminh && ch) { 11459 data.top = dh - o.minHeight; 11460 } 11461 if (ismaxh && ch) { 11462 data.top = dh - o.maxHeight; 11463 } 11464 11465 // Fixing jump error on top/left - bug #2330 11466 if (!data.width && !data.height && !data.left && data.top) { 11467 data.top = null; 11468 } else if (!data.width && !data.height && !data.top && data.left) { 11469 data.left = null; 11470 } 11471 11472 return data; 11473 }, 11474 11475 _getPaddingPlusBorderDimensions: function (element) { 11476 var i = 0, 11477 widths = [], 11478 borders = [ 11479 element.css("borderTopWidth"), 11480 element.css("borderRightWidth"), 11481 element.css("borderBottomWidth"), 11482 element.css("borderLeftWidth") 11483 ], 11484 paddings = [ 11485 element.css("paddingTop"), 11486 element.css("paddingRight"), 11487 element.css("paddingBottom"), 11488 element.css("paddingLeft") 11489 ]; 11490 11491 for (; i < 4; i++) { 11492 widths[i] = (parseFloat(borders[i]) || 0); 11493 widths[i] += (parseFloat(paddings[i]) || 0); 11494 } 11495 11496 return { 11497 height: widths[0] + widths[2], 11498 width: widths[1] + widths[3] 11499 }; 11500 }, 11501 11502 _calculateAdjustedElementDimensions: function (element) { 11503 var elWidth, elHeight, paddingBorder, 11504 ce = element.get(0); 11505 11506 if (element.css("box-sizing") !== "content-box" || 11507 (!this._hasScroll(ce) && !this._hasScroll(ce, "left"))) { 11508 return { 11509 height: parseFloat(element.css("height")), 11510 width: parseFloat(element.css("width")) 11511 }; 11512 } 11513 11514 // Check if CSS inline styles are set and use those (usually from previous resizes) 11515 elWidth = parseFloat(ce.style.width); 11516 elHeight = parseFloat(ce.style.height); 11517 11518 paddingBorder = this._getPaddingPlusBorderDimensions(element); 11519 elWidth = isNaN(elWidth) ? 11520 this._getElementTheoreticalSize(element, paddingBorder, "width") : 11521 elWidth; 11522 elHeight = isNaN(elHeight) ? 11523 this._getElementTheoreticalSize(element, paddingBorder, "height") : 11524 elHeight; 11525 11526 return { 11527 height: elHeight, 11528 width: elWidth 11529 }; 11530 }, 11531 11532 _getElementTheoreticalSize: function (element, extraSize, dimension) { 11533 11534 // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border 11535 var size = Math.max(0, Math.ceil( 11536 element.get(0)["offset" + dimension[0].toUpperCase() + dimension.slice(1)] - 11537 extraSize[dimension] - 11538 0.5 11539 11540 // If offsetWidth/offsetHeight is unknown, then we can't determine theoretical size. 11541 // Use an explicit zero to avoid NaN. 11542 // See https://github.com/jquery/jquery/issues/3964 11543 )) || 0; 11544 11545 return size; 11546 }, 11547 11548 _proportionallyResize: function () { 11549 11550 if (!this._proportionallyResizeElements.length) { 11551 return; 11552 } 11553 11554 var prel, 11555 i = 0, 11556 element = this.helper || this.element; 11557 11558 for (; i < this._proportionallyResizeElements.length; i++) { 11559 11560 prel = this._proportionallyResizeElements[i]; 11561 11562 // TODO: Seems like a bug to cache this.outerDimensions 11563 // considering that we are in a loop. 11564 if (!this.outerDimensions) { 11565 this.outerDimensions = this._getPaddingPlusBorderDimensions(prel); 11566 } 11567 11568 prel.css({ 11569 height: (element.height() - this.outerDimensions.height) || 0, 11570 width: (element.width() - this.outerDimensions.width) || 0 11571 }); 11572 11573 } 11574 11575 }, 11576 11577 _renderProxy: function () { 11578 11579 var el = this.element, o = this.options; 11580 this.elementOffset = el.offset(); 11581 11582 if (this._helper) { 11583 11584 this.helper = this.helper || $("<div></div>").css({ overflow: "hidden" }); 11585 11586 this._addClass(this.helper, this._helper); 11587 this.helper.css({ 11588 width: this.element.outerWidth(), 11589 height: this.element.outerHeight(), 11590 position: "absolute", 11591 left: this.elementOffset.left + "px", 11592 top: this.elementOffset.top + "px", 11593 zIndex: ++o.zIndex //TODO: Don't modify option 11594 }); 11595 11596 this.helper 11597 .appendTo("body") 11598 .disableSelection(); 11599 11600 } else { 11601 this.helper = this.element; 11602 } 11603 11604 }, 11605 11606 _change: { 11607 e: function (event, dx) { 11608 return { width: this.originalSize.width + dx }; 11609 }, 11610 w: function (event, dx) { 11611 var cs = this.originalSize, sp = this.originalPosition; 11612 return { left: sp.left + dx, width: cs.width - dx }; 11613 }, 11614 n: function (event, dx, dy) { 11615 var cs = this.originalSize, sp = this.originalPosition; 11616 return { top: sp.top + dy, height: cs.height - dy }; 11617 }, 11618 s: function (event, dx, dy) { 11619 return { height: this.originalSize.height + dy }; 11620 }, 11621 se: function (event, dx, dy) { 11622 return $.extend(this._change.s.apply(this, arguments), 11623 this._change.e.apply(this, [event, dx, dy])); 11624 }, 11625 sw: function (event, dx, dy) { 11626 return $.extend(this._change.s.apply(this, arguments), 11627 this._change.w.apply(this, [event, dx, dy])); 11628 }, 11629 ne: function (event, dx, dy) { 11630 return $.extend(this._change.n.apply(this, arguments), 11631 this._change.e.apply(this, [event, dx, dy])); 11632 }, 11633 nw: function (event, dx, dy) { 11634 return $.extend(this._change.n.apply(this, arguments), 11635 this._change.w.apply(this, [event, dx, dy])); 11636 } 11637 }, 11638 11639 _propagate: function (n, event) { 11640 $.ui.plugin.call(this, n, [event, this.ui()]); 11641 if (n !== "resize") { 11642 this._trigger(n, event, this.ui()); 11643 } 11644 }, 11645 11646 plugins: {}, 11647 11648 ui: function () { 11649 return { 11650 originalElement: this.originalElement, 11651 element: this.element, 11652 helper: this.helper, 11653 position: this.position, 11654 size: this.size, 11655 originalSize: this.originalSize, 11656 originalPosition: this.originalPosition 11657 }; 11658 } 11659 11660 }); 11661 11662 /* 11663 * Resizable Extensions 11664 */ 11665 11666 $.ui.plugin.add("resizable", "animate", { 11667 11668 stop: function (event) { 11669 var that = $(this).resizable("instance"), 11670 o = that.options, 11671 pr = that._proportionallyResizeElements, 11672 ista = pr.length && (/textarea/i).test(pr[0].nodeName), 11673 soffseth = ista && that._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height, 11674 soffsetw = ista ? 0 : that.sizeDiff.width, 11675 style = { 11676 width: (that.size.width - soffsetw), 11677 height: (that.size.height - soffseth) 11678 }, 11679 left = (parseFloat(that.element.css("left")) + 11680 (that.position.left - that.originalPosition.left)) || null, 11681 top = (parseFloat(that.element.css("top")) + 11682 (that.position.top - that.originalPosition.top)) || null; 11683 11684 that.element.animate( 11685 $.extend(style, top && left ? { top: top, left: left } : {}), { 11686 duration: o.animateDuration, 11687 easing: o.animateEasing, 11688 step: function () { 11689 11690 var data = { 11691 width: parseFloat(that.element.css("width")), 11692 height: parseFloat(that.element.css("height")), 11693 top: parseFloat(that.element.css("top")), 11694 left: parseFloat(that.element.css("left")) 11695 }; 11696 11697 if (pr && pr.length) { 11698 $(pr[0]).css({ width: data.width, height: data.height }); 11699 } 11700 11701 // Propagating resize, and updating values for each animation step 11702 that._updateCache(data); 11703 that._propagate("resize", event); 11704 11705 } 11706 } 11707 ); 11708 } 11709 11710 }); 11711 11712 $.ui.plugin.add("resizable", "containment", { 11713 11714 start: function () { 11715 var element, p, co, ch, cw, width, height, 11716 that = $(this).resizable("instance"), 11717 o = that.options, 11718 el = that.element, 11719 oc = o.containment, 11720 ce = (oc instanceof $) ? 11721 oc.get(0) : 11722 (/parent/.test(oc)) ? el.parent().get(0) : oc; 11723 11724 if (!ce) { 11725 return; 11726 } 11727 11728 that.containerElement = $(ce); 11729 11730 if (/document/.test(oc) || oc === document) { 11731 that.containerOffset = { 11732 left: 0, 11733 top: 0 11734 }; 11735 that.containerPosition = { 11736 left: 0, 11737 top: 0 11738 }; 11739 11740 that.parentData = { 11741 element: $(document), 11742 left: 0, 11743 top: 0, 11744 width: $(document).width(), 11745 height: $(document).height() || document.body.parentNode.scrollHeight 11746 }; 11747 } else { 11748 element = $(ce); 11749 p = []; 11750 $(["Top", "Right", "Left", "Bottom"]).each(function (i, name) { 11751 p[i] = that._num(element.css("padding" + name)); 11752 }); 11753 11754 that.containerOffset = element.offset(); 11755 that.containerPosition = element.position(); 11756 that.containerSize = { 11757 height: (element.innerHeight() - p[3]), 11758 width: (element.innerWidth() - p[1]) 11759 }; 11760 11761 co = that.containerOffset; 11762 ch = that.containerSize.height; 11763 cw = that.containerSize.width; 11764 width = (that._hasScroll(ce, "left") ? ce.scrollWidth : cw); 11765 height = (that._hasScroll(ce) ? ce.scrollHeight : ch); 11766 11767 that.parentData = { 11768 element: ce, 11769 left: co.left, 11770 top: co.top, 11771 width: width, 11772 height: height 11773 }; 11774 } 11775 }, 11776 11777 resize: function (event) { 11778 var woset, hoset, isParent, isOffsetRelative, 11779 that = $(this).resizable("instance"), 11780 o = that.options, 11781 co = that.containerOffset, 11782 cp = that.position, 11783 pRatio = that._aspectRatio || event.shiftKey, 11784 cop = { 11785 top: 0, 11786 left: 0 11787 }, 11788 ce = that.containerElement, 11789 continueResize = true; 11790 11791 if (ce[0] !== document && (/static/).test(ce.css("position"))) { 11792 cop = co; 11793 } 11794 11795 if (cp.left < (that._helper ? co.left : 0)) { 11796 that.size.width = that.size.width + 11797 (that._helper ? 11798 (that.position.left - co.left) : 11799 (that.position.left - cop.left)); 11800 11801 if (pRatio) { 11802 that.size.height = that.size.width / that.aspectRatio; 11803 continueResize = false; 11804 } 11805 that.position.left = o.helper ? co.left : 0; 11806 } 11807 11808 if (cp.top < (that._helper ? co.top : 0)) { 11809 that.size.height = that.size.height + 11810 (that._helper ? 11811 (that.position.top - co.top) : 11812 that.position.top); 11813 11814 if (pRatio) { 11815 that.size.width = that.size.height * that.aspectRatio; 11816 continueResize = false; 11817 } 11818 that.position.top = that._helper ? co.top : 0; 11819 } 11820 11821 isParent = that.containerElement.get(0) === that.element.parent().get(0); 11822 isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position")); 11823 11824 if (isParent && isOffsetRelative) { 11825 that.offset.left = that.parentData.left + that.position.left; 11826 that.offset.top = that.parentData.top + that.position.top; 11827 } else { 11828 that.offset.left = that.element.offset().left; 11829 that.offset.top = that.element.offset().top; 11830 } 11831 11832 woset = Math.abs(that.sizeDiff.width + 11833 (that._helper ? 11834 that.offset.left - cop.left : 11835 (that.offset.left - co.left))); 11836 11837 hoset = Math.abs(that.sizeDiff.height + 11838 (that._helper ? 11839 that.offset.top - cop.top : 11840 (that.offset.top - co.top))); 11841 11842 if (woset + that.size.width >= that.parentData.width) { 11843 that.size.width = that.parentData.width - woset; 11844 if (pRatio) { 11845 that.size.height = that.size.width / that.aspectRatio; 11846 continueResize = false; 11847 } 11848 } 11849 11850 if (hoset + that.size.height >= that.parentData.height) { 11851 that.size.height = that.parentData.height - hoset; 11852 if (pRatio) { 11853 that.size.width = that.size.height * that.aspectRatio; 11854 continueResize = false; 11855 } 11856 } 11857 11858 if (!continueResize) { 11859 that.position.left = that.prevPosition.left; 11860 that.position.top = that.prevPosition.top; 11861 that.size.width = that.prevSize.width; 11862 that.size.height = that.prevSize.height; 11863 } 11864 }, 11865 11866 stop: function () { 11867 var that = $(this).resizable("instance"), 11868 o = that.options, 11869 co = that.containerOffset, 11870 cop = that.containerPosition, 11871 ce = that.containerElement, 11872 helper = $(that.helper), 11873 ho = helper.offset(), 11874 w = helper.outerWidth() - that.sizeDiff.width, 11875 h = helper.outerHeight() - that.sizeDiff.height; 11876 11877 if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) { 11878 $(this).css({ 11879 left: ho.left - cop.left - co.left, 11880 width: w, 11881 height: h 11882 }); 11883 } 11884 11885 if (that._helper && !o.animate && (/static/).test(ce.css("position"))) { 11886 $(this).css({ 11887 left: ho.left - cop.left - co.left, 11888 width: w, 11889 height: h 11890 }); 11891 } 11892 } 11893 }); 11894 11895 $.ui.plugin.add("resizable", "alsoResize", { 11896 11897 start: function () { 11898 var that = $(this).resizable("instance"), 11899 o = that.options; 11900 11901 $(o.alsoResize).each(function () { 11902 var el = $(this), 11903 elSize = that._calculateAdjustedElementDimensions(el); 11904 11905 el.data("ui-resizable-alsoresize", { 11906 width: elSize.width, height: elSize.height, 11907 left: parseFloat(el.css("left")), top: parseFloat(el.css("top")) 11908 }); 11909 }); 11910 }, 11911 11912 resize: function (event, ui) { 11913 var that = $(this).resizable("instance"), 11914 o = that.options, 11915 os = that.originalSize, 11916 op = that.originalPosition, 11917 delta = { 11918 height: (that.size.height - os.height) || 0, 11919 width: (that.size.width - os.width) || 0, 11920 top: (that.position.top - op.top) || 0, 11921 left: (that.position.left - op.left) || 0 11922 }; 11923 11924 $(o.alsoResize).each(function () { 11925 var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {}, 11926 css = el.parents(ui.originalElement[0]).length ? 11927 ["width", "height"] : 11928 ["width", "height", "top", "left"]; 11929 11930 $.each(css, function (i, prop) { 11931 var sum = (start[prop] || 0) + (delta[prop] || 0); 11932 if (sum && sum >= 0) { 11933 style[prop] = sum || null; 11934 } 11935 }); 11936 11937 el.css(style); 11938 }); 11939 }, 11940 11941 stop: function () { 11942 $(this).removeData("ui-resizable-alsoresize"); 11943 } 11944 }); 11945 11946 $.ui.plugin.add("resizable", "ghost", { 11947 11948 start: function () { 11949 11950 var that = $(this).resizable("instance"), cs = that.size; 11951 11952 that.ghost = that.originalElement.clone(); 11953 that.ghost.css({ 11954 opacity: 0.25, 11955 display: "block", 11956 position: "relative", 11957 height: cs.height, 11958 width: cs.width, 11959 margin: 0, 11960 left: 0, 11961 top: 0 11962 }); 11963 11964 that._addClass(that.ghost, "ui-resizable-ghost"); 11965 11966 // DEPRECATED 11967 // TODO: remove after 1.12 11968 if ($.uiBackCompat === true && typeof that.options.ghost === "string") { 11969 11970 // Ghost option 11971 that.ghost.addClass(this.options.ghost); 11972 } 11973 11974 that.ghost.appendTo(that.helper); 11975 11976 }, 11977 11978 resize: function () { 11979 var that = $(this).resizable("instance"); 11980 if (that.ghost) { 11981 that.ghost.css({ 11982 position: "relative", 11983 height: that.size.height, 11984 width: that.size.width 11985 }); 11986 } 11987 }, 11988 11989 stop: function () { 11990 var that = $(this).resizable("instance"); 11991 if (that.ghost && that.helper) { 11992 that.helper.get(0).removeChild(that.ghost.get(0)); 11993 } 11994 } 11995 11996 }); 11997 11998 $.ui.plugin.add("resizable", "grid", { 11999 12000 resize: function () { 12001 var outerDimensions, 12002 that = $(this).resizable("instance"), 12003 o = that.options, 12004 cs = that.size, 12005 os = that.originalSize, 12006 op = that.originalPosition, 12007 a = that.axis, 12008 grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid, 12009 gridX = (grid[0] || 1), 12010 gridY = (grid[1] || 1), 12011 ox = Math.round((cs.width - os.width) / gridX) * gridX, 12012 oy = Math.round((cs.height - os.height) / gridY) * gridY, 12013 newWidth = os.width + ox, 12014 newHeight = os.height + oy, 12015 isMaxWidth = o.maxWidth && (o.maxWidth < newWidth), 12016 isMaxHeight = o.maxHeight && (o.maxHeight < newHeight), 12017 isMinWidth = o.minWidth && (o.minWidth > newWidth), 12018 isMinHeight = o.minHeight && (o.minHeight > newHeight); 12019 12020 o.grid = grid; 12021 12022 if (isMinWidth) { 12023 newWidth += gridX; 12024 } 12025 if (isMinHeight) { 12026 newHeight += gridY; 12027 } 12028 if (isMaxWidth) { 12029 newWidth -= gridX; 12030 } 12031 if (isMaxHeight) { 12032 newHeight -= gridY; 12033 } 12034 12035 if (/^(se|s|e)$/.test(a)) { 12036 that.size.width = newWidth; 12037 that.size.height = newHeight; 12038 } else if (/^(ne)$/.test(a)) { 12039 that.size.width = newWidth; 12040 that.size.height = newHeight; 12041 that.position.top = op.top - oy; 12042 } else if (/^(sw)$/.test(a)) { 12043 that.size.width = newWidth; 12044 that.size.height = newHeight; 12045 that.position.left = op.left - ox; 12046 } else { 12047 if (newHeight - gridY <= 0 || newWidth - gridX <= 0) { 12048 outerDimensions = that._getPaddingPlusBorderDimensions(this); 12049 } 12050 12051 if (newHeight - gridY > 0) { 12052 that.size.height = newHeight; 12053 that.position.top = op.top - oy; 12054 } else { 12055 newHeight = gridY - outerDimensions.height; 12056 that.size.height = newHeight; 12057 that.position.top = op.top + os.height - newHeight; 12058 } 12059 if (newWidth - gridX > 0) { 12060 that.size.width = newWidth; 12061 that.position.left = op.left - ox; 12062 } else { 12063 newWidth = gridX - outerDimensions.width; 12064 that.size.width = newWidth; 12065 that.position.left = op.left + os.width - newWidth; 12066 } 12067 } 12068 } 12069 12070 }); 12071 12072 var widgetsResizable = $.ui.resizable; 12073 12074 12075 /*! 12076 * jQuery UI Dialog 1.14.1 12077 * https://jqueryui.com 12078 * 12079 * Copyright OpenJS Foundation and other contributors 12080 * Released under the MIT license. 12081 * https://jquery.org/license 12082 */ 12083 12084 //>>label: Dialog 12085 //>>group: Widgets 12086 //>>description: Displays customizable dialog windows. 12087 //>>docs: https://api.jqueryui.com/dialog/ 12088 //>>demos: https://jqueryui.com/dialog/ 12089 //>>css.structure: ../../themes/base/core.css 12090 //>>css.structure: ../../themes/base/dialog.css 12091 //>>css.theme: ../../themes/base/theme.css 12092 12093 12094 $.widget("ui.dialog", { 12095 version: "1.14.1", 12096 options: { 12097 appendTo: "body", 12098 autoOpen: true, 12099 buttons: [], 12100 classes: { 12101 "ui-dialog": "ui-corner-all", 12102 "ui-dialog-titlebar": "ui-corner-all" 12103 }, 12104 closeOnEscape: true, 12105 closeText: "Close", 12106 draggable: true, 12107 hide: null, 12108 height: "auto", 12109 maxHeight: null, 12110 maxWidth: null, 12111 minHeight: 150, 12112 minWidth: 150, 12113 modal: false, 12114 position: { 12115 my: "center", 12116 at: "center", 12117 of: window, 12118 collision: "fit", 12119 12120 // Ensure the titlebar is always visible 12121 using: function (pos) { 12122 var topOffset = $(this).css(pos).offset().top; 12123 if (topOffset < 0) { 12124 $(this).css("top", pos.top - topOffset); 12125 } 12126 } 12127 }, 12128 resizable: true, 12129 show: null, 12130 title: null, 12131 uiDialogTitleHeadingLevel: 0, 12132 width: 300, 12133 12134 // Callbacks 12135 beforeClose: null, 12136 close: null, 12137 drag: null, 12138 dragStart: null, 12139 dragStop: null, 12140 focus: null, 12141 open: null, 12142 resize: null, 12143 resizeStart: null, 12144 resizeStop: null 12145 }, 12146 12147 sizeRelatedOptions: { 12148 buttons: true, 12149 height: true, 12150 maxHeight: true, 12151 maxWidth: true, 12152 minHeight: true, 12153 minWidth: true, 12154 width: true 12155 }, 12156 12157 resizableRelatedOptions: { 12158 maxHeight: true, 12159 maxWidth: true, 12160 minHeight: true, 12161 minWidth: true 12162 }, 12163 12164 _create: function () { 12165 this.originalCss = { 12166 display: this.element[0].style.display, 12167 width: this.element[0].style.width, 12168 minHeight: this.element[0].style.minHeight, 12169 maxHeight: this.element[0].style.maxHeight, 12170 height: this.element[0].style.height 12171 }; 12172 this.originalPosition = { 12173 parent: this.element.parent(), 12174 index: this.element.parent().children().index(this.element) 12175 }; 12176 this.originalTitle = this.element.attr("title"); 12177 if (this.options.title == null && this.originalTitle != null) { 12178 this.options.title = this.originalTitle; 12179 } 12180 12181 // Dialogs can't be disabled 12182 if (this.options.disabled) { 12183 this.options.disabled = false; 12184 } 12185 12186 this._createWrapper(); 12187 12188 this.element 12189 .show() 12190 .removeAttr("title") 12191 .appendTo(this.uiDialog); 12192 12193 this._addClass("ui-dialog-content", "ui-widget-content"); 12194 12195 this._createTitlebar(); 12196 this._createButtonPane(); 12197 12198 if (this.options.draggable && $.fn.draggable) { 12199 this._makeDraggable(); 12200 } 12201 if (this.options.resizable && $.fn.resizable) { 12202 this._makeResizable(); 12203 } 12204 12205 this._isOpen = false; 12206 12207 this._trackFocus(); 12208 }, 12209 12210 _init: function () { 12211 if (this.options.autoOpen) { 12212 this.open(); 12213 } 12214 }, 12215 12216 _appendTo: function () { 12217 var element = this.options.appendTo; 12218 if (element && (element.jquery || element.nodeType)) { 12219 return $(element); 12220 } 12221 return this.document.find(element || "body").eq(0); 12222 }, 12223 12224 _destroy: function () { 12225 var next, 12226 originalPosition = this.originalPosition; 12227 12228 this._untrackInstance(); 12229 this._destroyOverlay(); 12230 12231 this.element 12232 .removeUniqueId() 12233 .css(this.originalCss) 12234 12235 // Without detaching first, the following becomes really slow 12236 .detach(); 12237 12238 this.uiDialog.remove(); 12239 12240 if (this.originalTitle) { 12241 this.element.attr("title", this.originalTitle); 12242 } 12243 12244 next = originalPosition.parent.children().eq(originalPosition.index); 12245 12246 // Don't try to place the dialog next to itself (#8613) 12247 if (next.length && next[0] !== this.element[0]) { 12248 next.before(this.element); 12249 } else { 12250 originalPosition.parent.append(this.element); 12251 } 12252 }, 12253 12254 widget: function () { 12255 return this.uiDialog; 12256 }, 12257 12258 disable: $.noop, 12259 enable: $.noop, 12260 12261 close: function (event) { 12262 var that = this; 12263 12264 if (!this._isOpen || this._trigger("beforeClose", event) === false) { 12265 return; 12266 } 12267 12268 this._isOpen = false; 12269 this._focusedElement = null; 12270 this._destroyOverlay(); 12271 this._untrackInstance(); 12272 12273 if (!this.opener.filter(":focusable").trigger("focus").length) { 12274 12275 // Hiding a focused element doesn't trigger blur in WebKit 12276 // so in case we have nothing to focus on, explicitly blur the active element 12277 // https://bugs.webkit.org/show_bug.cgi?id=47182 12278 $(this.document[0].activeElement).trigger("blur"); 12279 } 12280 12281 this._hide(this.uiDialog, this.options.hide, function () { 12282 that._trigger("close", event); 12283 }); 12284 }, 12285 12286 isOpen: function () { 12287 return this._isOpen; 12288 }, 12289 12290 moveToTop: function () { 12291 this._moveToTop(); 12292 }, 12293 12294 _moveToTop: function (event, silent) { 12295 var moved = false, 12296 zIndices = this.uiDialog.siblings(".ui-front:visible").map(function () { 12297 return +$(this).css("z-index"); 12298 }).get(), 12299 zIndexMax = Math.max.apply(null, zIndices); 12300 12301 if (zIndexMax >= +this.uiDialog.css("z-index")) { 12302 this.uiDialog.css("z-index", zIndexMax + 1); 12303 moved = true; 12304 } 12305 12306 if (moved && !silent) { 12307 this._trigger("focus", event); 12308 } 12309 return moved; 12310 }, 12311 12312 open: function () { 12313 var that = this; 12314 if (this._isOpen) { 12315 if (this._moveToTop()) { 12316 this._focusTabbable(); 12317 } 12318 return; 12319 } 12320 12321 this._isOpen = true; 12322 this.opener = $(this.document[0].activeElement); 12323 12324 this._size(); 12325 this._position(); 12326 this._createOverlay(); 12327 this._moveToTop(null, true); 12328 12329 // Ensure the overlay is moved to the top with the dialog, but only when 12330 // opening. The overlay shouldn't move after the dialog is open so that 12331 // modeless dialogs opened after the modal dialog stack properly. 12332 if (this.overlay) { 12333 this.overlay.css("z-index", this.uiDialog.css("z-index") - 1); 12334 } 12335 12336 this._show(this.uiDialog, this.options.show, function () { 12337 that._focusTabbable(); 12338 that._trigger("focus"); 12339 }); 12340 12341 // Track the dialog immediately upon opening in case a focus event 12342 // somehow occurs outside of the dialog before an element inside the 12343 // dialog is focused (#10152) 12344 this._makeFocusTarget(); 12345 12346 this._trigger("open"); 12347 }, 12348 12349 _focusTabbable: function () { 12350 12351 // Set focus to the first match: 12352 // 1. An element that was focused previously 12353 // 2. First element inside the dialog matching [autofocus] 12354 // 3. Tabbable element inside the content element 12355 // 4. Tabbable element inside the buttonpane 12356 // 5. The close button 12357 // 6. The dialog itself 12358 var hasFocus = this._focusedElement; 12359 if (!hasFocus) { 12360 hasFocus = this.element.find("[autofocus]"); 12361 } 12362 if (!hasFocus.length) { 12363 hasFocus = this.element.find(":tabbable"); 12364 } 12365 if (!hasFocus.length) { 12366 hasFocus = this.uiDialogButtonPane.find(":tabbable"); 12367 } 12368 if (!hasFocus.length) { 12369 hasFocus = this.uiDialogTitlebarClose.filter(":tabbable"); 12370 } 12371 if (!hasFocus.length) { 12372 hasFocus = this.uiDialog; 12373 } 12374 hasFocus.eq(0).trigger("focus"); 12375 }, 12376 12377 _restoreTabbableFocus: function () { 12378 var activeElement = this.document[0].activeElement, 12379 isActive = this.uiDialog[0] === activeElement || 12380 $.contains(this.uiDialog[0], activeElement); 12381 if (!isActive) { 12382 this._focusTabbable(); 12383 } 12384 }, 12385 12386 _keepFocus: function (event) { 12387 event.preventDefault(); 12388 this._restoreTabbableFocus(); 12389 }, 12390 12391 _createWrapper: function () { 12392 this.uiDialog = $("<div>") 12393 .hide() 12394 .attr({ 12395 12396 // Setting tabIndex makes the div focusable 12397 tabIndex: -1, 12398 role: "dialog", 12399 "aria-modal": this.options.modal ? "true" : null 12400 }) 12401 .appendTo(this._appendTo()); 12402 12403 this._addClass(this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front"); 12404 this._on(this.uiDialog, { 12405 keydown: function (event) { 12406 if (this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && 12407 event.keyCode === $.ui.keyCode.ESCAPE) { 12408 event.preventDefault(); 12409 this.close(event); 12410 return; 12411 } 12412 12413 // Prevent tabbing out of dialogs 12414 if (event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented()) { 12415 return; 12416 } 12417 var tabbables = this.uiDialog.find(":tabbable"), 12418 first = tabbables.first(), 12419 last = tabbables.last(); 12420 12421 if ((event.target === last[0] || event.target === this.uiDialog[0]) && 12422 !event.shiftKey) { 12423 this._delay(function () { 12424 first.trigger("focus"); 12425 }); 12426 event.preventDefault(); 12427 } else if ((event.target === first[0] || 12428 event.target === this.uiDialog[0]) && event.shiftKey) { 12429 this._delay(function () { 12430 last.trigger("focus"); 12431 }); 12432 event.preventDefault(); 12433 } 12434 }, 12435 mousedown: function (event) { 12436 if (this._moveToTop(event)) { 12437 this._focusTabbable(); 12438 } 12439 } 12440 }); 12441 12442 // We assume that any existing aria-describedby attribute means 12443 // that the dialog content is marked up properly 12444 // otherwise we brute force the content as the description 12445 if (!this.element.find("[aria-describedby]").length) { 12446 this.uiDialog.attr({ 12447 "aria-describedby": this.element.uniqueId().attr("id") 12448 }); 12449 } 12450 }, 12451 12452 _createTitlebar: function () { 12453 var uiDialogTitle; 12454 12455 this.uiDialogTitlebar = $("<div>"); 12456 this._addClass(this.uiDialogTitlebar, 12457 "ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix"); 12458 this._on(this.uiDialogTitlebar, { 12459 mousedown: function (event) { 12460 12461 // Don't prevent click on close button (#8838) 12462 // Focusing a dialog that is partially scrolled out of view 12463 // causes the browser to scroll it into view, preventing the click event 12464 if (!$(event.target).closest(".ui-dialog-titlebar-close")) { 12465 12466 // Dialog isn't getting focus when dragging (#8063) 12467 this.uiDialog.trigger("focus"); 12468 } 12469 } 12470 }); 12471 12472 this.uiDialogTitlebarClose = $("<button type='button'></button>") 12473 .button({ 12474 label: $("<a>").text(this.options.closeText).html(), 12475 icon: "ui-icon-closethick", 12476 showLabel: false 12477 }) 12478 .appendTo(this.uiDialogTitlebar); 12479 12480 this._addClass(this.uiDialogTitlebarClose, "ui-dialog-titlebar-close"); 12481 this._on(this.uiDialogTitlebarClose, { 12482 click: function (event) { 12483 event.preventDefault(); 12484 this.close(event); 12485 } 12486 }); 12487 12488 var uiDialogHeadingLevel = Number.isInteger(this.options.uiDialogTitleHeadingLevel) && 12489 this.options.uiDialogTitleHeadingLevel > 0 && 12490 this.options.uiDialogTitleHeadingLevel <= 6 ? 12491 "h" + this.options.uiDialogTitleHeadingLevel : "span"; 12492 12493 uiDialogTitle = $("<" + uiDialogHeadingLevel + ">") 12494 .uniqueId().prependTo(this.uiDialogTitlebar); 12495 this._addClass(uiDialogTitle, "ui-dialog-title"); 12496 this._title(uiDialogTitle); 12497 12498 this.uiDialogTitlebar.prependTo(this.uiDialog); 12499 12500 this.uiDialog.attr({ 12501 "aria-labelledby": uiDialogTitle.attr("id") 12502 }); 12503 }, 12504 12505 _title: function (title) { 12506 if (this.options.title) { 12507 title.text(this.options.title); 12508 } else { 12509 title.html(" "); 12510 } 12511 }, 12512 12513 _createButtonPane: function () { 12514 this.uiDialogButtonPane = $("<div>"); 12515 this._addClass(this.uiDialogButtonPane, "ui-dialog-buttonpane", 12516 "ui-widget-content ui-helper-clearfix"); 12517 12518 this.uiButtonSet = $("<div>") 12519 .appendTo(this.uiDialogButtonPane); 12520 this._addClass(this.uiButtonSet, "ui-dialog-buttonset"); 12521 12522 this._createButtons(); 12523 }, 12524 12525 _createButtons: function () { 12526 var that = this, 12527 buttons = this.options.buttons; 12528 12529 // If we already have a button pane, remove it 12530 this.uiDialogButtonPane.remove(); 12531 this.uiButtonSet.empty(); 12532 12533 if ($.isEmptyObject(buttons) || (Array.isArray(buttons) && !buttons.length)) { 12534 this._removeClass(this.uiDialog, "ui-dialog-buttons"); 12535 return; 12536 } 12537 12538 $.each(buttons, function (name, props) { 12539 var click, buttonOptions; 12540 props = typeof props === "function" ? 12541 { click: props, text: name } : 12542 props; 12543 12544 // Default to a non-submitting button 12545 props = $.extend({ type: "button" }, props); 12546 12547 // Change the context for the click callback to be the main element 12548 click = props.click; 12549 buttonOptions = { 12550 icon: props.icon, 12551 iconPosition: props.iconPosition, 12552 showLabel: props.showLabel, 12553 12554 // Deprecated options 12555 icons: props.icons, 12556 text: props.text 12557 }; 12558 12559 delete props.click; 12560 delete props.icon; 12561 delete props.iconPosition; 12562 delete props.showLabel; 12563 12564 // Deprecated options 12565 delete props.icons; 12566 if (typeof props.text === "boolean") { 12567 delete props.text; 12568 } 12569 12570 $("<button></button>", props) 12571 .button(buttonOptions) 12572 .appendTo(that.uiButtonSet) 12573 .on("click", function () { 12574 click.apply(that.element[0], arguments); 12575 }); 12576 }); 12577 this._addClass(this.uiDialog, "ui-dialog-buttons"); 12578 this.uiDialogButtonPane.appendTo(this.uiDialog); 12579 }, 12580 12581 _makeDraggable: function () { 12582 var that = this, 12583 options = this.options; 12584 12585 function filteredUi(ui) { 12586 return { 12587 position: ui.position, 12588 offset: ui.offset 12589 }; 12590 } 12591 12592 this.uiDialog.draggable({ 12593 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", 12594 handle: ".ui-dialog-titlebar", 12595 containment: "document", 12596 start: function (event, ui) { 12597 that._addClass($(this), "ui-dialog-dragging"); 12598 that._blockFrames(); 12599 that._trigger("dragStart", event, filteredUi(ui)); 12600 }, 12601 drag: function (event, ui) { 12602 that._trigger("drag", event, filteredUi(ui)); 12603 }, 12604 stop: function (event, ui) { 12605 var left = ui.offset.left - that.document.scrollLeft(), 12606 top = ui.offset.top - that.document.scrollTop(); 12607 12608 options.position = { 12609 my: "left top", 12610 at: "left" + (left >= 0 ? "+" : "") + left + " " + 12611 "top" + (top >= 0 ? "+" : "") + top, 12612 of: that.window 12613 }; 12614 that._removeClass($(this), "ui-dialog-dragging"); 12615 that._unblockFrames(); 12616 that._trigger("dragStop", event, filteredUi(ui)); 12617 } 12618 }); 12619 }, 12620 12621 _makeResizable: function () { 12622 var that = this, 12623 options = this.options, 12624 handles = options.resizable, 12625 12626 // .ui-resizable has position: relative defined in the stylesheet 12627 // but dialogs have to use absolute or fixed positioning 12628 position = this.uiDialog.css("position"), 12629 resizeHandles = typeof handles === "string" ? 12630 handles : 12631 "n,e,s,w,se,sw,ne,nw"; 12632 12633 function filteredUi(ui) { 12634 return { 12635 originalPosition: ui.originalPosition, 12636 originalSize: ui.originalSize, 12637 position: ui.position, 12638 size: ui.size 12639 }; 12640 } 12641 12642 this.uiDialog.resizable({ 12643 cancel: ".ui-dialog-content", 12644 containment: "document", 12645 alsoResize: this.element, 12646 maxWidth: options.maxWidth, 12647 maxHeight: options.maxHeight, 12648 minWidth: options.minWidth, 12649 minHeight: this._minHeight(), 12650 handles: resizeHandles, 12651 start: function (event, ui) { 12652 that._addClass($(this), "ui-dialog-resizing"); 12653 that._blockFrames(); 12654 that._trigger("resizeStart", event, filteredUi(ui)); 12655 }, 12656 resize: function (event, ui) { 12657 that._trigger("resize", event, filteredUi(ui)); 12658 }, 12659 stop: function (event, ui) { 12660 var offset = that.uiDialog.offset(), 12661 left = offset.left - that.document.scrollLeft(), 12662 top = offset.top - that.document.scrollTop(); 12663 12664 options.height = that.uiDialog.height(); 12665 options.width = that.uiDialog.width(); 12666 options.position = { 12667 my: "left top", 12668 at: "left" + (left >= 0 ? "+" : "") + left + " " + 12669 "top" + (top >= 0 ? "+" : "") + top, 12670 of: that.window 12671 }; 12672 that._removeClass($(this), "ui-dialog-resizing"); 12673 that._unblockFrames(); 12674 that._trigger("resizeStop", event, filteredUi(ui)); 12675 } 12676 }) 12677 .css("position", position); 12678 }, 12679 12680 _trackFocus: function () { 12681 this._on(this.widget(), { 12682 focusin: function (event) { 12683 this._makeFocusTarget(); 12684 this._focusedElement = $(event.target); 12685 } 12686 }); 12687 }, 12688 12689 _makeFocusTarget: function () { 12690 this._untrackInstance(); 12691 this._trackingInstances().unshift(this); 12692 }, 12693 12694 _untrackInstance: function () { 12695 var instances = this._trackingInstances(), 12696 exists = $.inArray(this, instances); 12697 if (exists !== -1) { 12698 instances.splice(exists, 1); 12699 } 12700 }, 12701 12702 _trackingInstances: function () { 12703 var instances = this.document.data("ui-dialog-instances"); 12704 if (!instances) { 12705 instances = []; 12706 this.document.data("ui-dialog-instances", instances); 12707 } 12708 return instances; 12709 }, 12710 12711 _minHeight: function () { 12712 var options = this.options; 12713 12714 return options.height === "auto" ? 12715 options.minHeight : 12716 Math.min(options.minHeight, options.height); 12717 }, 12718 12719 _position: function () { 12720 12721 // Need to show the dialog to get the actual offset in the position plugin 12722 var isVisible = this.uiDialog.is(":visible"); 12723 if (!isVisible) { 12724 this.uiDialog.show(); 12725 } 12726 this.uiDialog.position(this.options.position); 12727 if (!isVisible) { 12728 this.uiDialog.hide(); 12729 } 12730 }, 12731 12732 _setOptions: function (options) { 12733 var that = this, 12734 resize = false, 12735 resizableOptions = {}; 12736 12737 $.each(options, function (key, value) { 12738 that._setOption(key, value); 12739 12740 if (key in that.sizeRelatedOptions) { 12741 resize = true; 12742 } 12743 if (key in that.resizableRelatedOptions) { 12744 resizableOptions[key] = value; 12745 } 12746 }); 12747 12748 if (resize) { 12749 this._size(); 12750 this._position(); 12751 } 12752 if (this.uiDialog.is(":data(ui-resizable)")) { 12753 this.uiDialog.resizable("option", resizableOptions); 12754 } 12755 }, 12756 12757 _setOption: function (key, value) { 12758 var isDraggable, isResizable, 12759 uiDialog = this.uiDialog; 12760 12761 if (key === "disabled") { 12762 return; 12763 } 12764 12765 this._super(key, value); 12766 12767 if (key === "appendTo") { 12768 this.uiDialog.appendTo(this._appendTo()); 12769 } 12770 12771 if (key === "buttons") { 12772 this._createButtons(); 12773 } 12774 12775 if (key === "closeText") { 12776 this.uiDialogTitlebarClose.button({ 12777 12778 // Ensure that we always pass a string 12779 label: $("<a>").text("" + this.options.closeText).html() 12780 }); 12781 } 12782 12783 if (key === "draggable") { 12784 isDraggable = uiDialog.is(":data(ui-draggable)"); 12785 if (isDraggable && !value) { 12786 uiDialog.draggable("destroy"); 12787 } 12788 12789 if (!isDraggable && value) { 12790 this._makeDraggable(); 12791 } 12792 } 12793 12794 if (key === "position") { 12795 this._position(); 12796 } 12797 12798 if (key === "resizable") { 12799 12800 // currently resizable, becoming non-resizable 12801 isResizable = uiDialog.is(":data(ui-resizable)"); 12802 if (isResizable && !value) { 12803 uiDialog.resizable("destroy"); 12804 } 12805 12806 // Currently resizable, changing handles 12807 if (isResizable && typeof value === "string") { 12808 uiDialog.resizable("option", "handles", value); 12809 } 12810 12811 // Currently non-resizable, becoming resizable 12812 if (!isResizable && value !== false) { 12813 this._makeResizable(); 12814 } 12815 } 12816 12817 if (key === "title") { 12818 this._title(this.uiDialogTitlebar.find(".ui-dialog-title")); 12819 } 12820 12821 if (key === "modal") { 12822 uiDialog.attr("aria-modal", value ? "true" : null); 12823 } 12824 }, 12825 12826 _size: function () { 12827 12828 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content 12829 // divs will both have width and height set, so we need to reset them 12830 var nonContentHeight, minContentHeight, maxContentHeight, 12831 options = this.options; 12832 12833 // Reset content sizing 12834 this.element.show().css({ 12835 width: "auto", 12836 minHeight: 0, 12837 maxHeight: "none", 12838 height: 0 12839 }); 12840 12841 if (options.minWidth > options.width) { 12842 options.width = options.minWidth; 12843 } 12844 12845 // Reset wrapper sizing 12846 // determine the height of all the non-content elements 12847 nonContentHeight = this.uiDialog.css({ 12848 height: "auto", 12849 width: options.width 12850 }) 12851 .outerHeight(); 12852 minContentHeight = Math.max(0, options.minHeight - nonContentHeight); 12853 maxContentHeight = typeof options.maxHeight === "number" ? 12854 Math.max(0, options.maxHeight - nonContentHeight) : 12855 "none"; 12856 12857 if (options.height === "auto") { 12858 this.element.css({ 12859 minHeight: minContentHeight, 12860 maxHeight: maxContentHeight, 12861 height: "auto" 12862 }); 12863 } else { 12864 this.element.height(Math.max(0, options.height - nonContentHeight)); 12865 } 12866 12867 if (this.uiDialog.is(":data(ui-resizable)")) { 12868 this.uiDialog.resizable("option", "minHeight", this._minHeight()); 12869 } 12870 }, 12871 12872 _blockFrames: function () { 12873 this.iframeBlocks = this.document.find("iframe").map(function () { 12874 var iframe = $(this); 12875 12876 return $("<div>") 12877 .css({ 12878 position: "absolute", 12879 width: iframe.outerWidth(), 12880 height: iframe.outerHeight() 12881 }) 12882 .appendTo(iframe.parent()) 12883 .offset(iframe.offset())[0]; 12884 }); 12885 }, 12886 12887 _unblockFrames: function () { 12888 if (this.iframeBlocks) { 12889 this.iframeBlocks.remove(); 12890 delete this.iframeBlocks; 12891 } 12892 }, 12893 12894 _allowInteraction: function (event) { 12895 if ($(event.target).closest(".ui-dialog").length) { 12896 return true; 12897 } 12898 12899 // TODO: Remove hack when datepicker implements 12900 // the .ui-front logic (#8989) 12901 return !!$(event.target).closest(".ui-datepicker").length; 12902 }, 12903 12904 _createOverlay: function () { 12905 if (!this.options.modal) { 12906 return; 12907 } 12908 12909 // We use a delay in case the overlay is created from an 12910 // event that we're going to be cancelling (#2804) 12911 var isOpening = true; 12912 this._delay(function () { 12913 isOpening = false; 12914 }); 12915 12916 if (!this.document.data("ui-dialog-overlays")) { 12917 12918 // Prevent use of anchors and inputs 12919 // This doesn't use `_on()` because it is a shared event handler 12920 // across all open modal dialogs. 12921 this.document.on("focusin.ui-dialog", function (event) { 12922 if (isOpening) { 12923 return; 12924 } 12925 12926 var instance = this._trackingInstances()[0]; 12927 if (!instance._allowInteraction(event)) { 12928 event.preventDefault(); 12929 instance._focusTabbable(); 12930 } 12931 }.bind(this)); 12932 } 12933 12934 this.overlay = $("<div>") 12935 .appendTo(this._appendTo()); 12936 12937 this._addClass(this.overlay, null, "ui-widget-overlay ui-front"); 12938 this._on(this.overlay, { 12939 mousedown: "_keepFocus" 12940 }); 12941 this.document.data("ui-dialog-overlays", 12942 (this.document.data("ui-dialog-overlays") || 0) + 1); 12943 }, 12944 12945 _destroyOverlay: function () { 12946 if (!this.options.modal) { 12947 return; 12948 } 12949 12950 if (this.overlay) { 12951 var overlays = this.document.data("ui-dialog-overlays") - 1; 12952 12953 if (!overlays) { 12954 this.document.off("focusin.ui-dialog"); 12955 this.document.removeData("ui-dialog-overlays"); 12956 } else { 12957 this.document.data("ui-dialog-overlays", overlays); 12958 } 12959 12960 this.overlay.remove(); 12961 this.overlay = null; 12962 } 12963 } 12964 }); 12965 12966 // DEPRECATED 12967 // TODO: switch return back to widget declaration at top of file when this is removed 12968 if ($.uiBackCompat === true) { 12969 12970 // Backcompat for dialogClass option 12971 $.widget("ui.dialog", $.ui.dialog, { 12972 options: { 12973 dialogClass: "" 12974 }, 12975 _createWrapper: function () { 12976 this._super(); 12977 this.uiDialog.addClass(this.options.dialogClass); 12978 }, 12979 _setOption: function (key, value) { 12980 if (key === "dialogClass") { 12981 this.uiDialog 12982 .removeClass(this.options.dialogClass) 12983 .addClass(value); 12984 } 12985 this._superApply(arguments); 12986 } 12987 }); 12988 } 12989 12990 var widgetsDialog = $.ui.dialog; 12991 12992 12993 /*! 12994 * jQuery UI Droppable 1.14.1 12995 * https://jqueryui.com 12996 * 12997 * Copyright OpenJS Foundation and other contributors 12998 * Released under the MIT license. 12999 * https://jquery.org/license 13000 */ 13001 13002 //>>label: Droppable 13003 //>>group: Interactions 13004 //>>description: Enables drop targets for draggable elements. 13005 //>>docs: https://api.jqueryui.com/droppable/ 13006 //>>demos: https://jqueryui.com/droppable/ 13007 13008 13009 $.widget("ui.droppable", { 13010 version: "1.14.1", 13011 widgetEventPrefix: "drop", 13012 options: { 13013 accept: "*", 13014 addClasses: true, 13015 greedy: false, 13016 scope: "default", 13017 tolerance: "intersect", 13018 13019 // Callbacks 13020 activate: null, 13021 deactivate: null, 13022 drop: null, 13023 out: null, 13024 over: null 13025 }, 13026 _create: function () { 13027 13028 var proportions, 13029 o = this.options, 13030 accept = o.accept; 13031 13032 this.isover = false; 13033 this.isout = true; 13034 13035 this.accept = typeof accept === "function" ? accept : function (d) { 13036 return d.is(accept); 13037 }; 13038 13039 this.proportions = function ( /* valueToWrite */) { 13040 if (arguments.length) { 13041 13042 // Store the droppable's proportions 13043 proportions = arguments[0]; 13044 } else { 13045 13046 // Retrieve or derive the droppable's proportions 13047 return proportions ? 13048 proportions : 13049 proportions = { 13050 width: this.element[0].offsetWidth, 13051 height: this.element[0].offsetHeight 13052 }; 13053 } 13054 }; 13055 13056 this._addToManager(o.scope); 13057 13058 if (o.addClasses) { 13059 this._addClass("ui-droppable"); 13060 } 13061 13062 }, 13063 13064 _addToManager: function (scope) { 13065 13066 // Add the reference and positions to the manager 13067 $.ui.ddmanager.droppables[scope] = $.ui.ddmanager.droppables[scope] || []; 13068 $.ui.ddmanager.droppables[scope].push(this); 13069 }, 13070 13071 _splice: function (drop) { 13072 var i = 0; 13073 for (; i < drop.length; i++) { 13074 if (drop[i] === this) { 13075 drop.splice(i, 1); 13076 } 13077 } 13078 }, 13079 13080 _destroy: function () { 13081 var drop = $.ui.ddmanager.droppables[this.options.scope]; 13082 13083 this._splice(drop); 13084 }, 13085 13086 _setOption: function (key, value) { 13087 13088 if (key === "accept") { 13089 this.accept = typeof value === "function" ? value : function (d) { 13090 return d.is(value); 13091 }; 13092 } else if (key === "scope") { 13093 var drop = $.ui.ddmanager.droppables[this.options.scope]; 13094 13095 this._splice(drop); 13096 this._addToManager(value); 13097 } 13098 13099 this._super(key, value); 13100 }, 13101 13102 _activate: function (event) { 13103 var draggable = $.ui.ddmanager.current; 13104 13105 this._addActiveClass(); 13106 if (draggable) { 13107 this._trigger("activate", event, this.ui(draggable)); 13108 } 13109 }, 13110 13111 _deactivate: function (event) { 13112 var draggable = $.ui.ddmanager.current; 13113 13114 this._removeActiveClass(); 13115 if (draggable) { 13116 this._trigger("deactivate", event, this.ui(draggable)); 13117 } 13118 }, 13119 13120 _over: function (event) { 13121 13122 var draggable = $.ui.ddmanager.current; 13123 13124 // Bail if draggable and droppable are same element 13125 if (!draggable || (draggable.currentItem || 13126 draggable.element)[0] === this.element[0]) { 13127 return; 13128 } 13129 13130 if (this.accept.call(this.element[0], (draggable.currentItem || 13131 draggable.element))) { 13132 this._addHoverClass(); 13133 this._trigger("over", event, this.ui(draggable)); 13134 } 13135 13136 }, 13137 13138 _out: function (event) { 13139 13140 var draggable = $.ui.ddmanager.current; 13141 13142 // Bail if draggable and droppable are same element 13143 if (!draggable || (draggable.currentItem || 13144 draggable.element)[0] === this.element[0]) { 13145 return; 13146 } 13147 13148 if (this.accept.call(this.element[0], (draggable.currentItem || 13149 draggable.element))) { 13150 this._removeHoverClass(); 13151 this._trigger("out", event, this.ui(draggable)); 13152 } 13153 13154 }, 13155 13156 _drop: function (event, custom) { 13157 13158 var draggable = custom || $.ui.ddmanager.current, 13159 childrenIntersection = false; 13160 13161 // Bail if draggable and droppable are same element 13162 if (!draggable || (draggable.currentItem || 13163 draggable.element)[0] === this.element[0]) { 13164 return false; 13165 } 13166 13167 this.element 13168 .find(":data(ui-droppable)") 13169 .not(".ui-draggable-dragging") 13170 .each(function () { 13171 var inst = $(this).droppable("instance"); 13172 if ( 13173 inst.options.greedy && 13174 !inst.options.disabled && 13175 inst.options.scope === draggable.options.scope && 13176 inst.accept.call( 13177 inst.element[0], (draggable.currentItem || draggable.element) 13178 ) && 13179 $.ui.intersect( 13180 draggable, 13181 $.extend(inst, { offset: inst.element.offset() }), 13182 inst.options.tolerance, event 13183 ) 13184 ) { 13185 childrenIntersection = true; 13186 return false; 13187 } 13188 }); 13189 if (childrenIntersection) { 13190 return false; 13191 } 13192 13193 if (this.accept.call(this.element[0], 13194 (draggable.currentItem || draggable.element))) { 13195 this._removeActiveClass(); 13196 this._removeHoverClass(); 13197 13198 this._trigger("drop", event, this.ui(draggable)); 13199 return this.element; 13200 } 13201 13202 return false; 13203 13204 }, 13205 13206 ui: function (c) { 13207 return { 13208 draggable: (c.currentItem || c.element), 13209 helper: c.helper, 13210 position: c.position, 13211 offset: c.positionAbs 13212 }; 13213 }, 13214 13215 // Extension points just to make backcompat sane and avoid duplicating logic 13216 // TODO: Remove in 1.14 along with call to it below 13217 _addHoverClass: function () { 13218 this._addClass("ui-droppable-hover"); 13219 }, 13220 13221 _removeHoverClass: function () { 13222 this._removeClass("ui-droppable-hover"); 13223 }, 13224 13225 _addActiveClass: function () { 13226 this._addClass("ui-droppable-active"); 13227 }, 13228 13229 _removeActiveClass: function () { 13230 this._removeClass("ui-droppable-active"); 13231 } 13232 }); 13233 13234 $.ui.intersect = (function () { 13235 function isOverAxis(x, reference, size) { 13236 return (x >= reference) && (x < (reference + size)); 13237 } 13238 13239 return function (draggable, droppable, toleranceMode, event) { 13240 13241 if (!droppable.offset) { 13242 return false; 13243 } 13244 13245 var x1 = (draggable.positionAbs || 13246 draggable.position.absolute).left + draggable.margins.left, 13247 y1 = (draggable.positionAbs || 13248 draggable.position.absolute).top + draggable.margins.top, 13249 x2 = x1 + draggable.helperProportions.width, 13250 y2 = y1 + draggable.helperProportions.height, 13251 l = droppable.offset.left, 13252 t = droppable.offset.top, 13253 r = l + droppable.proportions().width, 13254 b = t + droppable.proportions().height; 13255 13256 switch (toleranceMode) { 13257 case "fit": 13258 return (l <= x1 && x2 <= r && t <= y1 && y2 <= b); 13259 case "intersect": 13260 return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half 13261 x2 - (draggable.helperProportions.width / 2) < r && // Left Half 13262 t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half 13263 y2 - (draggable.helperProportions.height / 2) < b); // Top Half 13264 case "pointer": 13265 return isOverAxis(event.pageY, t, droppable.proportions().height) && 13266 isOverAxis(event.pageX, l, droppable.proportions().width); 13267 case "touch": 13268 return ( 13269 (y1 >= t && y1 <= b) || // Top edge touching 13270 (y2 >= t && y2 <= b) || // Bottom edge touching 13271 (y1 < t && y2 > b) // Surrounded vertically 13272 ) && ( 13273 (x1 >= l && x1 <= r) || // Left edge touching 13274 (x2 >= l && x2 <= r) || // Right edge touching 13275 (x1 < l && x2 > r) // Surrounded horizontally 13276 ); 13277 default: 13278 return false; 13279 } 13280 }; 13281 })(); 13282 13283 /* 13284 This manager tracks offsets of draggables and droppables 13285 */ 13286 $.ui.ddmanager = { 13287 current: null, 13288 droppables: { "default": [] }, 13289 prepareOffsets: function (t, event) { 13290 13291 var i, j, 13292 m = $.ui.ddmanager.droppables[t.options.scope] || [], 13293 type = event ? event.type : null, // workaround for #2317 13294 list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack(); 13295 13296 droppablesLoop: for (i = 0; i < m.length; i++) { 13297 13298 // No disabled and non-accepted 13299 if (m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0], 13300 (t.currentItem || t.element)))) { 13301 continue; 13302 } 13303 13304 // Filter out elements in the current dragged item 13305 for (j = 0; j < list.length; j++) { 13306 if (list[j] === m[i].element[0]) { 13307 m[i].proportions().height = 0; 13308 continue droppablesLoop; 13309 } 13310 } 13311 13312 m[i].visible = m[i].element.css("display") !== "none"; 13313 if (!m[i].visible) { 13314 continue; 13315 } 13316 13317 // Activate the droppable if used directly from draggables 13318 if (type === "mousedown") { 13319 m[i]._activate.call(m[i], event); 13320 } 13321 13322 m[i].offset = m[i].element.offset(); 13323 m[i].proportions({ 13324 width: m[i].element[0].offsetWidth, 13325 height: m[i].element[0].offsetHeight 13326 }); 13327 13328 } 13329 13330 }, 13331 drop: function (draggable, event) { 13332 13333 var dropped = false; 13334 13335 // Create a copy of the droppables in case the list changes during the drop (#9116) 13336 $.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function () { 13337 13338 if (!this.options) { 13339 return; 13340 } 13341 if (!this.options.disabled && this.visible && 13342 $.ui.intersect(draggable, this, this.options.tolerance, event)) { 13343 dropped = this._drop.call(this, event) || dropped; 13344 } 13345 13346 if (!this.options.disabled && this.visible && this.accept.call(this.element[0], 13347 (draggable.currentItem || draggable.element))) { 13348 this.isout = true; 13349 this.isover = false; 13350 this._deactivate.call(this, event); 13351 } 13352 13353 }); 13354 return dropped; 13355 13356 }, 13357 dragStart: function (draggable, event) { 13358 13359 // Listen for scrolling so that if the dragging causes scrolling the position of the 13360 // droppables can be recalculated (see #5003) 13361 draggable.element.parentsUntil("body").on("scroll.droppable", function () { 13362 if (!draggable.options.refreshPositions) { 13363 $.ui.ddmanager.prepareOffsets(draggable, event); 13364 } 13365 }); 13366 }, 13367 drag: function (draggable, event) { 13368 13369 // If you have a highly dynamic page, you might try this option. It renders positions 13370 // every time you move the mouse. 13371 if (draggable.options.refreshPositions) { 13372 $.ui.ddmanager.prepareOffsets(draggable, event); 13373 } 13374 13375 // Run through all droppables and check their positions based on specific tolerance options 13376 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function () { 13377 13378 if (this.options.disabled || this.greedyChild || !this.visible) { 13379 return; 13380 } 13381 13382 var parentInstance, scope, parent, 13383 intersects = $.ui.intersect(draggable, this, this.options.tolerance, event), 13384 c = !intersects && this.isover ? 13385 "isout" : 13386 (intersects && !this.isover ? "isover" : null); 13387 if (!c) { 13388 return; 13389 } 13390 13391 if (this.options.greedy) { 13392 13393 // find droppable parents with same scope 13394 scope = this.options.scope; 13395 parent = this.element.parents(":data(ui-droppable)").filter(function () { 13396 return $(this).droppable("instance").options.scope === scope; 13397 }); 13398 13399 if (parent.length) { 13400 parentInstance = $(parent[0]).droppable("instance"); 13401 parentInstance.greedyChild = (c === "isover"); 13402 } 13403 } 13404 13405 // We just moved into a greedy child 13406 if (parentInstance && c === "isover") { 13407 parentInstance.isover = false; 13408 parentInstance.isout = true; 13409 parentInstance._out.call(parentInstance, event); 13410 } 13411 13412 this[c] = true; 13413 this[c === "isout" ? "isover" : "isout"] = false; 13414 this[c === "isover" ? "_over" : "_out"].call(this, event); 13415 13416 // We just moved out of a greedy child 13417 if (parentInstance && c === "isout") { 13418 parentInstance.isout = false; 13419 parentInstance.isover = true; 13420 parentInstance._over.call(parentInstance, event); 13421 } 13422 }); 13423 13424 }, 13425 dragStop: function (draggable, event) { 13426 draggable.element.parentsUntil("body").off("scroll.droppable"); 13427 13428 // Call prepareOffsets one final time since IE does not fire return scroll events when 13429 // overflow was caused by drag (see #5003) 13430 if (!draggable.options.refreshPositions) { 13431 $.ui.ddmanager.prepareOffsets(draggable, event); 13432 } 13433 } 13434 }; 13435 13436 // DEPRECATED 13437 // TODO: switch return back to widget declaration at top of file when this is removed 13438 if ($.uiBackCompat === true) { 13439 13440 // Backcompat for activeClass and hoverClass options 13441 $.widget("ui.droppable", $.ui.droppable, { 13442 options: { 13443 hoverClass: false, 13444 activeClass: false 13445 }, 13446 _addActiveClass: function () { 13447 this._super(); 13448 if (this.options.activeClass) { 13449 this.element.addClass(this.options.activeClass); 13450 } 13451 }, 13452 _removeActiveClass: function () { 13453 this._super(); 13454 if (this.options.activeClass) { 13455 this.element.removeClass(this.options.activeClass); 13456 } 13457 }, 13458 _addHoverClass: function () { 13459 this._super(); 13460 if (this.options.hoverClass) { 13461 this.element.addClass(this.options.hoverClass); 13462 } 13463 }, 13464 _removeHoverClass: function () { 13465 this._super(); 13466 if (this.options.hoverClass) { 13467 this.element.removeClass(this.options.hoverClass); 13468 } 13469 } 13470 }); 13471 } 13472 13473 var widgetsDroppable = $.ui.droppable; 13474 13475 13476 /*! 13477 * jQuery UI Progressbar 1.14.1 13478 * https://jqueryui.com 13479 * 13480 * Copyright OpenJS Foundation and other contributors 13481 * Released under the MIT license. 13482 * https://jquery.org/license 13483 */ 13484 13485 //>>label: Progressbar 13486 //>>group: Widgets 13487 /* eslint-disable max-len */ 13488 //>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators. 13489 /* eslint-enable max-len */ 13490 //>>docs: https://api.jqueryui.com/progressbar/ 13491 //>>demos: https://jqueryui.com/progressbar/ 13492 //>>css.structure: ../../themes/base/core.css 13493 //>>css.structure: ../../themes/base/progressbar.css 13494 //>>css.theme: ../../themes/base/theme.css 13495 13496 13497 var widgetsProgressbar = $.widget("ui.progressbar", { 13498 version: "1.14.1", 13499 options: { 13500 classes: { 13501 "ui-progressbar": "ui-corner-all", 13502 "ui-progressbar-value": "ui-corner-left", 13503 "ui-progressbar-complete": "ui-corner-right" 13504 }, 13505 max: 100, 13506 value: 0, 13507 13508 change: null, 13509 complete: null 13510 }, 13511 13512 min: 0, 13513 13514 _create: function () { 13515 13516 // Constrain initial value 13517 this.oldValue = this.options.value = this._constrainedValue(); 13518 13519 this.element.attr({ 13520 13521 // Only set static values; aria-valuenow and aria-valuemax are 13522 // set inside _refreshValue() 13523 role: "progressbar", 13524 "aria-valuemin": this.min 13525 }); 13526 this._addClass("ui-progressbar", "ui-widget ui-widget-content"); 13527 13528 this.valueDiv = $("<div>").appendTo(this.element); 13529 this._addClass(this.valueDiv, "ui-progressbar-value", "ui-widget-header"); 13530 this._refreshValue(); 13531 }, 13532 13533 _destroy: function () { 13534 this.element.removeAttr("role aria-valuemin aria-valuemax aria-valuenow"); 13535 13536 this.valueDiv.remove(); 13537 }, 13538 13539 value: function (newValue) { 13540 if (newValue === undefined) { 13541 return this.options.value; 13542 } 13543 13544 this.options.value = this._constrainedValue(newValue); 13545 this._refreshValue(); 13546 }, 13547 13548 _constrainedValue: function (newValue) { 13549 if (newValue === undefined) { 13550 newValue = this.options.value; 13551 } 13552 13553 this.indeterminate = newValue === false; 13554 13555 // Sanitize value 13556 if (typeof newValue !== "number") { 13557 newValue = 0; 13558 } 13559 13560 return this.indeterminate ? false : 13561 Math.min(this.options.max, Math.max(this.min, newValue)); 13562 }, 13563 13564 _setOptions: function (options) { 13565 13566 // Ensure "value" option is set after other values (like max) 13567 var value = options.value; 13568 delete options.value; 13569 13570 this._super(options); 13571 13572 this.options.value = this._constrainedValue(value); 13573 this._refreshValue(); 13574 }, 13575 13576 _setOption: function (key, value) { 13577 if (key === "max") { 13578 13579 // Don't allow a max less than min 13580 value = Math.max(this.min, value); 13581 } 13582 this._super(key, value); 13583 }, 13584 13585 _setOptionDisabled: function (value) { 13586 this._super(value); 13587 13588 this.element.attr("aria-disabled", value); 13589 this._toggleClass(null, "ui-state-disabled", !!value); 13590 }, 13591 13592 _percentage: function () { 13593 return this.indeterminate ? 13594 100 : 13595 100 * (this.options.value - this.min) / (this.options.max - this.min); 13596 }, 13597 13598 _refreshValue: function () { 13599 var value = this.options.value, 13600 percentage = this._percentage(); 13601 13602 this.valueDiv 13603 .toggle(this.indeterminate || value > this.min) 13604 .width(percentage.toFixed(0) + "%"); 13605 13606 this 13607 ._toggleClass(this.valueDiv, "ui-progressbar-complete", null, 13608 value === this.options.max) 13609 ._toggleClass("ui-progressbar-indeterminate", null, this.indeterminate); 13610 13611 if (this.indeterminate) { 13612 this.element.removeAttr("aria-valuenow"); 13613 if (!this.overlayDiv) { 13614 this.overlayDiv = $("<div>").appendTo(this.valueDiv); 13615 this._addClass(this.overlayDiv, "ui-progressbar-overlay"); 13616 } 13617 } else { 13618 this.element.attr({ 13619 "aria-valuemax": this.options.max, 13620 "aria-valuenow": value 13621 }); 13622 if (this.overlayDiv) { 13623 this.overlayDiv.remove(); 13624 this.overlayDiv = null; 13625 } 13626 } 13627 13628 if (this.oldValue !== value) { 13629 this.oldValue = value; 13630 this._trigger("change"); 13631 } 13632 if (value === this.options.max) { 13633 this._trigger("complete"); 13634 } 13635 } 13636 }); 13637 13638 13639 /*! 13640 * jQuery UI Selectable 1.14.1 13641 * https://jqueryui.com 13642 * 13643 * Copyright OpenJS Foundation and other contributors 13644 * Released under the MIT license. 13645 * https://jquery.org/license 13646 */ 13647 13648 //>>label: Selectable 13649 //>>group: Interactions 13650 //>>description: Allows groups of elements to be selected with the mouse. 13651 //>>docs: https://api.jqueryui.com/selectable/ 13652 //>>demos: https://jqueryui.com/selectable/ 13653 //>>css.structure: ../../themes/base/selectable.css 13654 13655 13656 var widgetsSelectable = $.widget("ui.selectable", $.ui.mouse, { 13657 version: "1.14.1", 13658 options: { 13659 appendTo: "body", 13660 autoRefresh: true, 13661 distance: 0, 13662 filter: "*", 13663 tolerance: "touch", 13664 13665 // Callbacks 13666 selected: null, 13667 selecting: null, 13668 start: null, 13669 stop: null, 13670 unselected: null, 13671 unselecting: null 13672 }, 13673 _create: function () { 13674 var that = this; 13675 13676 this._addClass("ui-selectable"); 13677 13678 this.dragged = false; 13679 13680 // Cache selectee children based on filter 13681 this.refresh = function () { 13682 that.elementPos = $(that.element[0]).offset(); 13683 that.selectees = $(that.options.filter, that.element[0]); 13684 that._addClass(that.selectees, "ui-selectee"); 13685 that.selectees.each(function () { 13686 var $this = $(this), 13687 selecteeOffset = $this.offset(), 13688 pos = { 13689 left: selecteeOffset.left - that.elementPos.left, 13690 top: selecteeOffset.top - that.elementPos.top 13691 }; 13692 $.data(this, "selectable-item", { 13693 element: this, 13694 $element: $this, 13695 left: pos.left, 13696 top: pos.top, 13697 right: pos.left + $this.outerWidth(), 13698 bottom: pos.top + $this.outerHeight(), 13699 startselected: false, 13700 selected: $this.hasClass("ui-selected"), 13701 selecting: $this.hasClass("ui-selecting"), 13702 unselecting: $this.hasClass("ui-unselecting") 13703 }); 13704 }); 13705 }; 13706 this.refresh(); 13707 13708 this._mouseInit(); 13709 13710 this.helper = $("<div>"); 13711 this._addClass(this.helper, "ui-selectable-helper"); 13712 }, 13713 13714 _destroy: function () { 13715 this.selectees.removeData("selectable-item"); 13716 this._mouseDestroy(); 13717 }, 13718 13719 _mouseStart: function (event) { 13720 var that = this, 13721 options = this.options; 13722 13723 this.opos = [event.pageX, event.pageY]; 13724 this.elementPos = $(this.element[0]).offset(); 13725 13726 if (this.options.disabled) { 13727 return; 13728 } 13729 13730 this.selectees = $(options.filter, this.element[0]); 13731 13732 this._trigger("start", event); 13733 13734 $(options.appendTo).append(this.helper); 13735 13736 // position helper (lasso) 13737 this.helper.css({ 13738 "left": event.pageX, 13739 "top": event.pageY, 13740 "width": 0, 13741 "height": 0 13742 }); 13743 13744 if (options.autoRefresh) { 13745 this.refresh(); 13746 } 13747 13748 this.selectees.filter(".ui-selected").each(function () { 13749 var selectee = $.data(this, "selectable-item"); 13750 selectee.startselected = true; 13751 if (!event.metaKey && !event.ctrlKey) { 13752 that._removeClass(selectee.$element, "ui-selected"); 13753 selectee.selected = false; 13754 that._addClass(selectee.$element, "ui-unselecting"); 13755 selectee.unselecting = true; 13756 13757 // selectable UNSELECTING callback 13758 that._trigger("unselecting", event, { 13759 unselecting: selectee.element 13760 }); 13761 } 13762 }); 13763 13764 $(event.target).parents().addBack().each(function () { 13765 var doSelect, 13766 selectee = $.data(this, "selectable-item"); 13767 if (selectee) { 13768 doSelect = (!event.metaKey && !event.ctrlKey) || 13769 !selectee.$element.hasClass("ui-selected"); 13770 that._removeClass(selectee.$element, doSelect ? "ui-unselecting" : "ui-selected") 13771 ._addClass(selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting"); 13772 selectee.unselecting = !doSelect; 13773 selectee.selecting = doSelect; 13774 selectee.selected = doSelect; 13775 13776 // selectable (UN)SELECTING callback 13777 if (doSelect) { 13778 that._trigger("selecting", event, { 13779 selecting: selectee.element 13780 }); 13781 } else { 13782 that._trigger("unselecting", event, { 13783 unselecting: selectee.element 13784 }); 13785 } 13786 return false; 13787 } 13788 }); 13789 13790 }, 13791 13792 _mouseDrag: function (event) { 13793 13794 this.dragged = true; 13795 13796 if (this.options.disabled) { 13797 return; 13798 } 13799 13800 var tmp, 13801 that = this, 13802 options = this.options, 13803 x1 = this.opos[0], 13804 y1 = this.opos[1], 13805 x2 = event.pageX, 13806 y2 = event.pageY; 13807 13808 if (x1 > x2) { 13809 tmp = x2; x2 = x1; x1 = tmp; 13810 } 13811 if (y1 > y2) { 13812 tmp = y2; y2 = y1; y1 = tmp; 13813 } 13814 this.helper.css({ left: x1, top: y1, width: x2 - x1, height: y2 - y1 }); 13815 13816 this.selectees.each(function () { 13817 var selectee = $.data(this, "selectable-item"), 13818 hit = false, 13819 offset = {}; 13820 13821 //prevent helper from being selected if appendTo: selectable 13822 if (!selectee || selectee.element === that.element[0]) { 13823 return; 13824 } 13825 13826 offset.left = selectee.left + that.elementPos.left; 13827 offset.right = selectee.right + that.elementPos.left; 13828 offset.top = selectee.top + that.elementPos.top; 13829 offset.bottom = selectee.bottom + that.elementPos.top; 13830 13831 if (options.tolerance === "touch") { 13832 hit = (!(offset.left > x2 || offset.right < x1 || offset.top > y2 || 13833 offset.bottom < y1)); 13834 } else if (options.tolerance === "fit") { 13835 hit = (offset.left > x1 && offset.right < x2 && offset.top > y1 && 13836 offset.bottom < y2); 13837 } 13838 13839 if (hit) { 13840 13841 // SELECT 13842 if (selectee.selected) { 13843 that._removeClass(selectee.$element, "ui-selected"); 13844 selectee.selected = false; 13845 } 13846 if (selectee.unselecting) { 13847 that._removeClass(selectee.$element, "ui-unselecting"); 13848 selectee.unselecting = false; 13849 } 13850 if (!selectee.selecting) { 13851 that._addClass(selectee.$element, "ui-selecting"); 13852 selectee.selecting = true; 13853 13854 // selectable SELECTING callback 13855 that._trigger("selecting", event, { 13856 selecting: selectee.element 13857 }); 13858 } 13859 } else { 13860 13861 // UNSELECT 13862 if (selectee.selecting) { 13863 if ((event.metaKey || event.ctrlKey) && selectee.startselected) { 13864 that._removeClass(selectee.$element, "ui-selecting"); 13865 selectee.selecting = false; 13866 that._addClass(selectee.$element, "ui-selected"); 13867 selectee.selected = true; 13868 } else { 13869 that._removeClass(selectee.$element, "ui-selecting"); 13870 selectee.selecting = false; 13871 if (selectee.startselected) { 13872 that._addClass(selectee.$element, "ui-unselecting"); 13873 selectee.unselecting = true; 13874 } 13875 13876 // selectable UNSELECTING callback 13877 that._trigger("unselecting", event, { 13878 unselecting: selectee.element 13879 }); 13880 } 13881 } 13882 if (selectee.selected) { 13883 if (!event.metaKey && !event.ctrlKey && !selectee.startselected) { 13884 that._removeClass(selectee.$element, "ui-selected"); 13885 selectee.selected = false; 13886 13887 that._addClass(selectee.$element, "ui-unselecting"); 13888 selectee.unselecting = true; 13889 13890 // selectable UNSELECTING callback 13891 that._trigger("unselecting", event, { 13892 unselecting: selectee.element 13893 }); 13894 } 13895 } 13896 } 13897 }); 13898 13899 return false; 13900 }, 13901 13902 _mouseStop: function (event) { 13903 var that = this; 13904 13905 this.dragged = false; 13906 13907 $(".ui-unselecting", this.element[0]).each(function () { 13908 var selectee = $.data(this, "selectable-item"); 13909 that._removeClass(selectee.$element, "ui-unselecting"); 13910 selectee.unselecting = false; 13911 selectee.startselected = false; 13912 that._trigger("unselected", event, { 13913 unselected: selectee.element 13914 }); 13915 }); 13916 $(".ui-selecting", this.element[0]).each(function () { 13917 var selectee = $.data(this, "selectable-item"); 13918 that._removeClass(selectee.$element, "ui-selecting") 13919 ._addClass(selectee.$element, "ui-selected"); 13920 selectee.selecting = false; 13921 selectee.selected = true; 13922 selectee.startselected = true; 13923 that._trigger("selected", event, { 13924 selected: selectee.element 13925 }); 13926 }); 13927 this._trigger("stop", event); 13928 13929 this.helper.remove(); 13930 13931 return false; 13932 } 13933 13934 }); 13935 13936 13937 /*! 13938 * jQuery UI Selectmenu 1.14.1 13939 * https://jqueryui.com 13940 * 13941 * Copyright OpenJS Foundation and other contributors 13942 * Released under the MIT license. 13943 * https://jquery.org/license 13944 */ 13945 13946 //>>label: Selectmenu 13947 //>>group: Widgets 13948 /* eslint-disable max-len */ 13949 //>>description: Duplicates and extends the functionality of a native HTML select element, allowing it to be customizable in behavior and appearance far beyond the limitations of a native select. 13950 /* eslint-enable max-len */ 13951 //>>docs: https://api.jqueryui.com/selectmenu/ 13952 //>>demos: https://jqueryui.com/selectmenu/ 13953 //>>css.structure: ../../themes/base/core.css 13954 //>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css 13955 //>>css.theme: ../../themes/base/theme.css 13956 13957 13958 var widgetsSelectmenu = $.widget("ui.selectmenu", [$.ui.formResetMixin, { 13959 version: "1.14.1", 13960 defaultElement: "<select>", 13961 options: { 13962 appendTo: null, 13963 classes: { 13964 "ui-selectmenu-button-open": "ui-corner-top", 13965 "ui-selectmenu-button-closed": "ui-corner-all" 13966 }, 13967 disabled: null, 13968 icons: { 13969 button: "ui-icon-triangle-1-s" 13970 }, 13971 position: { 13972 my: "left top", 13973 at: "left bottom", 13974 collision: "none" 13975 }, 13976 width: false, 13977 13978 // Callbacks 13979 change: null, 13980 close: null, 13981 focus: null, 13982 open: null, 13983 select: null 13984 }, 13985 13986 _create: function () { 13987 var selectmenuId = this.element.uniqueId().attr("id"); 13988 this.ids = { 13989 element: selectmenuId, 13990 button: selectmenuId + "-button", 13991 menu: selectmenuId + "-menu" 13992 }; 13993 13994 this._drawButton(); 13995 this._drawMenu(); 13996 this._bindFormResetHandler(); 13997 13998 this._rendered = false; 13999 this.menuItems = $(); 14000 }, 14001 14002 _drawButton: function () { 14003 var icon, 14004 that = this, 14005 item = this._parseOption( 14006 this.element.find("option:selected"), 14007 this.element[0].selectedIndex 14008 ); 14009 14010 // Associate existing label with the new button 14011 this.labels = this.element.labels().attr("for", this.ids.button); 14012 this._on(this.labels, { 14013 click: function (event) { 14014 this.button.trigger("focus"); 14015 event.preventDefault(); 14016 } 14017 }); 14018 14019 // Hide original select element 14020 this.element.hide(); 14021 14022 // Create button 14023 this.button = $("<span>", { 14024 tabindex: this.options.disabled ? -1 : 0, 14025 id: this.ids.button, 14026 role: "combobox", 14027 "aria-expanded": "false", 14028 "aria-autocomplete": "list", 14029 "aria-owns": this.ids.menu, 14030 "aria-haspopup": "true", 14031 title: this.element.attr("title") 14032 }) 14033 .insertAfter(this.element); 14034 14035 this._addClass(this.button, "ui-selectmenu-button ui-selectmenu-button-closed", 14036 "ui-button ui-widget"); 14037 14038 icon = $("<span>").appendTo(this.button); 14039 this._addClass(icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button); 14040 this.buttonItem = this._renderButtonItem(item) 14041 .appendTo(this.button); 14042 14043 if (this.options.width !== false) { 14044 this._resizeButton(); 14045 } 14046 14047 this._on(this.button, this._buttonEvents); 14048 this.button.one("focusin", function () { 14049 14050 // Delay rendering the menu items until the button receives focus. 14051 // The menu may have already been rendered via a programmatic open. 14052 if (!that._rendered) { 14053 that._refreshMenu(); 14054 } 14055 }); 14056 }, 14057 14058 _drawMenu: function () { 14059 var that = this; 14060 14061 // Create menu 14062 this.menu = $("<ul>", { 14063 "aria-hidden": "true", 14064 "aria-labelledby": this.ids.button, 14065 id: this.ids.menu 14066 }); 14067 14068 // Wrap menu 14069 this.menuWrap = $("<div>").append(this.menu); 14070 this._addClass(this.menuWrap, "ui-selectmenu-menu", "ui-front"); 14071 this.menuWrap.appendTo(this._appendTo()); 14072 14073 // Initialize menu widget 14074 this.menuInstance = this.menu 14075 .menu({ 14076 classes: { 14077 "ui-menu": "ui-corner-bottom" 14078 }, 14079 role: "listbox", 14080 select: function (event, ui) { 14081 event.preventDefault(); 14082 that._select(ui.item.data("ui-selectmenu-item"), event); 14083 }, 14084 focus: function (event, ui) { 14085 var item = ui.item.data("ui-selectmenu-item"); 14086 14087 // Prevent inital focus from firing and check if its a newly focused item 14088 if (that.focusIndex != null && item.index !== that.focusIndex) { 14089 that._trigger("focus", event, { item: item }); 14090 if (!that.isOpen) { 14091 that._select(item, event); 14092 } 14093 } 14094 that.focusIndex = item.index; 14095 14096 that.button.attr("aria-activedescendant", 14097 that.menuItems.eq(item.index).attr("id")); 14098 } 14099 }) 14100 .menu("instance"); 14101 14102 // Don't close the menu on mouseleave 14103 this.menuInstance._off(this.menu, "mouseleave"); 14104 14105 // Cancel the menu's collapseAll on document click 14106 this.menuInstance._closeOnDocumentClick = function () { 14107 return false; 14108 }; 14109 14110 // Selects often contain empty items, but never contain dividers 14111 this.menuInstance._isDivider = function () { 14112 return false; 14113 }; 14114 }, 14115 14116 refresh: function () { 14117 this._refreshMenu(); 14118 this.buttonItem.replaceWith( 14119 this.buttonItem = this._renderButtonItem( 14120 14121 // Fall back to an empty object in case there are no options 14122 this._getSelectedItem().data("ui-selectmenu-item") || {} 14123 ) 14124 ); 14125 if (this.options.width === null) { 14126 this._resizeButton(); 14127 } 14128 }, 14129 14130 _refreshMenu: function () { 14131 var item, 14132 options = this.element.find("option"); 14133 14134 this.menu.empty(); 14135 14136 this._parseOptions(options); 14137 this._renderMenu(this.menu, this.items); 14138 14139 this.menuInstance.refresh(); 14140 this.menuItems = this.menu.find("li") 14141 .not(".ui-selectmenu-optgroup") 14142 .find(".ui-menu-item-wrapper"); 14143 14144 this._rendered = true; 14145 14146 if (!options.length) { 14147 return; 14148 } 14149 14150 item = this._getSelectedItem(); 14151 14152 // Update the menu to have the correct item focused 14153 this.menuInstance.focus(null, item); 14154 this._setAria(item.data("ui-selectmenu-item")); 14155 14156 // Set disabled state 14157 this._setOption("disabled", this.element.prop("disabled")); 14158 }, 14159 14160 open: function (event) { 14161 if (this.options.disabled) { 14162 return; 14163 } 14164 14165 // If this is the first time the menu is being opened, render the items 14166 if (!this._rendered) { 14167 this._refreshMenu(); 14168 } else { 14169 14170 // Menu clears focus on close, reset focus to selected item 14171 this._removeClass(this.menu.find(".ui-state-active"), null, "ui-state-active"); 14172 this.menuInstance.focus(null, this._getSelectedItem()); 14173 } 14174 14175 // If there are no options, don't open the menu 14176 if (!this.menuItems.length) { 14177 return; 14178 } 14179 14180 this.isOpen = true; 14181 this._toggleAttr(); 14182 this._resizeMenu(); 14183 this._position(); 14184 14185 this._on(this.document, this._documentClick); 14186 14187 this._trigger("open", event); 14188 }, 14189 14190 _position: function () { 14191 this.menuWrap.position($.extend({ of: this.button }, this.options.position)); 14192 }, 14193 14194 close: function (event) { 14195 if (!this.isOpen) { 14196 return; 14197 } 14198 14199 this.isOpen = false; 14200 this._toggleAttr(); 14201 14202 this.range = null; 14203 this._off(this.document); 14204 14205 this._trigger("close", event); 14206 }, 14207 14208 widget: function () { 14209 return this.button; 14210 }, 14211 14212 menuWidget: function () { 14213 return this.menu; 14214 }, 14215 14216 _renderButtonItem: function (item) { 14217 var buttonItem = $("<span>"); 14218 14219 this._setText(buttonItem, item.label); 14220 this._addClass(buttonItem, "ui-selectmenu-text"); 14221 14222 return buttonItem; 14223 }, 14224 14225 _renderMenu: function (ul, items) { 14226 var that = this, 14227 currentOptgroup = ""; 14228 14229 $.each(items, function (index, item) { 14230 var li; 14231 14232 if (item.optgroup !== currentOptgroup) { 14233 li = $("<li>", { 14234 text: item.optgroup 14235 }); 14236 that._addClass(li, "ui-selectmenu-optgroup", "ui-menu-divider" + 14237 (item.element.parent("optgroup").prop("disabled") ? 14238 " ui-state-disabled" : 14239 "")); 14240 14241 li.appendTo(ul); 14242 14243 currentOptgroup = item.optgroup; 14244 } 14245 14246 that._renderItemData(ul, item); 14247 }); 14248 }, 14249 14250 _renderItemData: function (ul, item) { 14251 return this._renderItem(ul, item).data("ui-selectmenu-item", item); 14252 }, 14253 14254 _renderItem: function (ul, item) { 14255 var li = $("<li>"), 14256 wrapper = $("<div>", { 14257 title: item.element.attr("title") 14258 }); 14259 14260 if (item.disabled) { 14261 this._addClass(li, null, "ui-state-disabled"); 14262 } 14263 14264 if (item.hidden) { 14265 li.prop("hidden", true); 14266 } else { 14267 this._setText(wrapper, item.label); 14268 } 14269 14270 return li.append(wrapper).appendTo(ul); 14271 }, 14272 14273 _setText: function (element, value) { 14274 if (value) { 14275 element.text(value); 14276 } else { 14277 element.html(" "); 14278 } 14279 }, 14280 14281 _move: function (direction, event) { 14282 var item, next, 14283 filter = ".ui-menu-item"; 14284 14285 if (this.isOpen) { 14286 item = this.menuItems.eq(this.focusIndex).parent("li"); 14287 } else { 14288 item = this.menuItems.eq(this.element[0].selectedIndex).parent("li"); 14289 filter += ":not(.ui-state-disabled)"; 14290 } 14291 14292 if (direction === "first" || direction === "last") { 14293 next = item[direction === "first" ? "prevAll" : "nextAll"](filter).eq(-1); 14294 } else { 14295 next = item[direction + "All"](filter).eq(0); 14296 } 14297 14298 if (next.length) { 14299 this.menuInstance.focus(event, next); 14300 } 14301 }, 14302 14303 _getSelectedItem: function () { 14304 return this.menuItems.eq(this.element[0].selectedIndex).parent("li"); 14305 }, 14306 14307 _toggle: function (event) { 14308 this[this.isOpen ? "close" : "open"](event); 14309 }, 14310 14311 _setSelection: function () { 14312 var selection; 14313 14314 if (!this.range) { 14315 return; 14316 } 14317 14318 selection = window.getSelection(); 14319 selection.removeAllRanges(); 14320 selection.addRange(this.range); 14321 }, 14322 14323 _documentClick: { 14324 mousedown: function (event) { 14325 if (!this.isOpen) { 14326 return; 14327 } 14328 14329 if (!$(event.target).closest(".ui-selectmenu-menu, #" + 14330 CSS.escape(this.ids.button)).length) { 14331 this.close(event); 14332 } 14333 } 14334 }, 14335 14336 _buttonEvents: { 14337 14338 // Prevent text selection from being reset when interacting with the selectmenu (#10144) 14339 mousedown: function () { 14340 var selection = window.getSelection(); 14341 if (selection.rangeCount) { 14342 this.range = selection.getRangeAt(0); 14343 } 14344 }, 14345 14346 click: function (event) { 14347 this._setSelection(); 14348 this._toggle(event); 14349 }, 14350 14351 keydown: function (event) { 14352 var preventDefault = true; 14353 switch (event.keyCode) { 14354 case $.ui.keyCode.TAB: 14355 case $.ui.keyCode.ESCAPE: 14356 this.close(event); 14357 preventDefault = false; 14358 break; 14359 case $.ui.keyCode.ENTER: 14360 if (this.isOpen) { 14361 this._selectFocusedItem(event); 14362 } 14363 break; 14364 case $.ui.keyCode.UP: 14365 if (event.altKey) { 14366 this._toggle(event); 14367 } else { 14368 this._move("prev", event); 14369 } 14370 break; 14371 case $.ui.keyCode.DOWN: 14372 if (event.altKey) { 14373 this._toggle(event); 14374 } else { 14375 this._move("next", event); 14376 } 14377 break; 14378 case $.ui.keyCode.SPACE: 14379 if (this.isOpen) { 14380 this._selectFocusedItem(event); 14381 } else { 14382 this._toggle(event); 14383 } 14384 break; 14385 case $.ui.keyCode.LEFT: 14386 this._move("prev", event); 14387 break; 14388 case $.ui.keyCode.RIGHT: 14389 this._move("next", event); 14390 break; 14391 case $.ui.keyCode.HOME: 14392 case $.ui.keyCode.PAGE_UP: 14393 this._move("first", event); 14394 break; 14395 case $.ui.keyCode.END: 14396 case $.ui.keyCode.PAGE_DOWN: 14397 this._move("last", event); 14398 break; 14399 default: 14400 this.menu.trigger(event); 14401 preventDefault = false; 14402 } 14403 14404 if (preventDefault) { 14405 event.preventDefault(); 14406 } 14407 } 14408 }, 14409 14410 _selectFocusedItem: function (event) { 14411 var item = this.menuItems.eq(this.focusIndex).parent("li"); 14412 if (!item.hasClass("ui-state-disabled")) { 14413 this._select(item.data("ui-selectmenu-item"), event); 14414 } 14415 }, 14416 14417 _select: function (item, event) { 14418 var oldIndex = this.element[0].selectedIndex; 14419 14420 // Change native select element 14421 this.element[0].selectedIndex = item.index; 14422 this.buttonItem.replaceWith(this.buttonItem = this._renderButtonItem(item)); 14423 this._setAria(item); 14424 this._trigger("select", event, { item: item }); 14425 14426 if (item.index !== oldIndex) { 14427 this._trigger("change", event, { item: item }); 14428 } 14429 14430 this.close(event); 14431 }, 14432 14433 _setAria: function (item) { 14434 var id = this.menuItems.eq(item.index).attr("id"); 14435 14436 this.button.attr({ 14437 "aria-labelledby": id, 14438 "aria-activedescendant": id 14439 }); 14440 this.menu.attr("aria-activedescendant", id); 14441 }, 14442 14443 _setOption: function (key, value) { 14444 if (key === "icons") { 14445 var icon = this.button.find("span.ui-icon"); 14446 this._removeClass(icon, null, this.options.icons.button) 14447 ._addClass(icon, null, value.button); 14448 } 14449 14450 this._super(key, value); 14451 14452 if (key === "appendTo") { 14453 this.menuWrap.appendTo(this._appendTo()); 14454 } 14455 14456 if (key === "width") { 14457 this._resizeButton(); 14458 } 14459 }, 14460 14461 _setOptionDisabled: function (value) { 14462 this._super(value); 14463 14464 this.menuInstance.option("disabled", value); 14465 this.button.attr("aria-disabled", value); 14466 this._toggleClass(this.button, null, "ui-state-disabled", value); 14467 14468 this.element.prop("disabled", value); 14469 if (value) { 14470 this.button.attr("tabindex", -1); 14471 this.close(); 14472 } else { 14473 this.button.attr("tabindex", 0); 14474 } 14475 }, 14476 14477 _appendTo: function () { 14478 var element = this.options.appendTo; 14479 14480 if (element) { 14481 element = element.jquery || element.nodeType ? 14482 $(element) : 14483 this.document.find(element).eq(0); 14484 } 14485 14486 if (!element || !element[0]) { 14487 element = this.element.closest(".ui-front, dialog"); 14488 } 14489 14490 if (!element.length) { 14491 element = this.document[0].body; 14492 } 14493 14494 return element; 14495 }, 14496 14497 _toggleAttr: function () { 14498 this.button.attr("aria-expanded", this.isOpen); 14499 14500 // We can't use two _toggleClass() calls here, because we need to make sure 14501 // we always remove classes first and add them second, otherwise if both classes have the 14502 // same theme class, it will be removed after we add it. 14503 this._removeClass(this.button, "ui-selectmenu-button-" + 14504 (this.isOpen ? "closed" : "open")) 14505 ._addClass(this.button, "ui-selectmenu-button-" + 14506 (this.isOpen ? "open" : "closed")) 14507 ._toggleClass(this.menuWrap, "ui-selectmenu-open", null, this.isOpen); 14508 14509 this.menu.attr("aria-hidden", !this.isOpen); 14510 }, 14511 14512 _resizeButton: function () { 14513 var width = this.options.width; 14514 14515 // For `width: false`, just remove inline style and stop 14516 if (width === false) { 14517 this.button.css("width", ""); 14518 return; 14519 } 14520 14521 // For `width: null`, match the width of the original element 14522 if (width === null) { 14523 width = this.element.show().outerWidth(); 14524 this.element.hide(); 14525 } 14526 14527 this.button.outerWidth(width); 14528 }, 14529 14530 _resizeMenu: function () { 14531 this.menu.outerWidth(Math.max( 14532 this.button.outerWidth(), 14533 this.menu.width("").outerWidth() 14534 )); 14535 }, 14536 14537 _getCreateOptions: function () { 14538 var options = this._super(); 14539 14540 options.disabled = this.element.prop("disabled"); 14541 14542 return options; 14543 }, 14544 14545 _parseOptions: function (options) { 14546 var that = this, 14547 data = []; 14548 options.each(function (index, item) { 14549 data.push(that._parseOption($(item), index)); 14550 }); 14551 this.items = data; 14552 }, 14553 14554 _parseOption: function (option, index) { 14555 var optgroup = option.parent("optgroup"); 14556 14557 return { 14558 element: option, 14559 index: index, 14560 value: option.val(), 14561 label: option.text(), 14562 hidden: optgroup.prop("hidden") || option.prop("hidden"), 14563 optgroup: optgroup.attr("label") || "", 14564 disabled: optgroup.prop("disabled") || option.prop("disabled") 14565 }; 14566 }, 14567 14568 _destroy: function () { 14569 this._unbindFormResetHandler(); 14570 this.menuWrap.remove(); 14571 this.button.remove(); 14572 this.element.show(); 14573 this.element.removeUniqueId(); 14574 this.labels.attr("for", this.ids.element); 14575 } 14576 }]); 14577 14578 14579 /*! 14580 * jQuery UI Slider 1.14.1 14581 * https://jqueryui.com 14582 * 14583 * Copyright OpenJS Foundation and other contributors 14584 * Released under the MIT license. 14585 * https://jquery.org/license 14586 */ 14587 14588 //>>label: Slider 14589 //>>group: Widgets 14590 //>>description: Displays a flexible slider with ranges and accessibility via keyboard. 14591 //>>docs: https://api.jqueryui.com/slider/ 14592 //>>demos: https://jqueryui.com/slider/ 14593 //>>css.structure: ../../themes/base/core.css 14594 //>>css.structure: ../../themes/base/slider.css 14595 //>>css.theme: ../../themes/base/theme.css 14596 14597 14598 var widgetsSlider = $.widget("ui.slider", $.ui.mouse, { 14599 version: "1.14.1", 14600 widgetEventPrefix: "slide", 14601 14602 options: { 14603 animate: false, 14604 classes: { 14605 "ui-slider": "ui-corner-all", 14606 "ui-slider-handle": "ui-corner-all", 14607 14608 // Note: ui-widget-header isn't the most fittingly semantic framework class for this 14609 // element, but worked best visually with a variety of themes 14610 "ui-slider-range": "ui-corner-all ui-widget-header" 14611 }, 14612 distance: 0, 14613 max: 100, 14614 min: 0, 14615 orientation: "horizontal", 14616 range: false, 14617 step: 1, 14618 value: 0, 14619 values: null, 14620 14621 // Callbacks 14622 change: null, 14623 slide: null, 14624 start: null, 14625 stop: null 14626 }, 14627 14628 // Number of pages in a slider 14629 // (how many times can you page up/down to go through the whole range) 14630 numPages: 5, 14631 14632 _create: function () { 14633 this._keySliding = false; 14634 this._mouseSliding = false; 14635 this._animateOff = true; 14636 this._handleIndex = null; 14637 this._detectOrientation(); 14638 this._mouseInit(); 14639 this._calculateNewMax(); 14640 14641 this._addClass("ui-slider ui-slider-" + this.orientation, 14642 "ui-widget ui-widget-content"); 14643 14644 this._refresh(); 14645 14646 this._animateOff = false; 14647 }, 14648 14649 _refresh: function () { 14650 this._createRange(); 14651 this._createHandles(); 14652 this._setupEvents(); 14653 this._refreshValue(); 14654 }, 14655 14656 _createHandles: function () { 14657 var i, handleCount, 14658 options = this.options, 14659 existingHandles = this.element.find(".ui-slider-handle"), 14660 handle = "<span tabindex='0'></span>", 14661 handles = []; 14662 14663 handleCount = (options.values && options.values.length) || 1; 14664 14665 if (existingHandles.length > handleCount) { 14666 existingHandles.slice(handleCount).remove(); 14667 existingHandles = existingHandles.slice(0, handleCount); 14668 } 14669 14670 for (i = existingHandles.length; i < handleCount; i++) { 14671 handles.push(handle); 14672 } 14673 14674 this.handles = existingHandles.add($(handles.join("")).appendTo(this.element)); 14675 14676 this._addClass(this.handles, "ui-slider-handle", "ui-state-default"); 14677 14678 this.handle = this.handles.eq(0); 14679 14680 this.handles.each(function (i) { 14681 $(this) 14682 .data("ui-slider-handle-index", i) 14683 .attr("tabIndex", 0); 14684 }); 14685 }, 14686 14687 _createRange: function () { 14688 var options = this.options; 14689 14690 if (options.range) { 14691 if (options.range === true) { 14692 if (!options.values) { 14693 options.values = [this._valueMin(), this._valueMin()]; 14694 } else if (options.values.length && options.values.length !== 2) { 14695 options.values = [options.values[0], options.values[0]]; 14696 } else if (Array.isArray(options.values)) { 14697 options.values = options.values.slice(0); 14698 } 14699 } 14700 14701 if (!this.range || !this.range.length) { 14702 this.range = $("<div>") 14703 .appendTo(this.element); 14704 14705 this._addClass(this.range, "ui-slider-range"); 14706 } else { 14707 this._removeClass(this.range, "ui-slider-range-min ui-slider-range-max"); 14708 14709 // Handle range switching from true to min/max 14710 this.range.css({ 14711 "left": "", 14712 "bottom": "" 14713 }); 14714 } 14715 if (options.range === "min" || options.range === "max") { 14716 this._addClass(this.range, "ui-slider-range-" + options.range); 14717 } 14718 } else { 14719 if (this.range) { 14720 this.range.remove(); 14721 } 14722 this.range = null; 14723 } 14724 }, 14725 14726 _setupEvents: function () { 14727 this._off(this.handles); 14728 this._on(this.handles, this._handleEvents); 14729 this._hoverable(this.handles); 14730 this._focusable(this.handles); 14731 }, 14732 14733 _destroy: function () { 14734 this.handles.remove(); 14735 if (this.range) { 14736 this.range.remove(); 14737 } 14738 14739 this._mouseDestroy(); 14740 }, 14741 14742 _mouseCapture: function (event) { 14743 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, 14744 that = this, 14745 o = this.options; 14746 14747 if (o.disabled) { 14748 return false; 14749 } 14750 14751 this.elementSize = { 14752 width: this.element.outerWidth(), 14753 height: this.element.outerHeight() 14754 }; 14755 this.elementOffset = this.element.offset(); 14756 14757 position = { x: event.pageX, y: event.pageY }; 14758 normValue = this._normValueFromMouse(position); 14759 distance = this._valueMax() - this._valueMin() + 1; 14760 this.handles.each(function (i) { 14761 var thisDistance = Math.abs(normValue - that.values(i)); 14762 if ((distance > thisDistance) || 14763 (distance === thisDistance && 14764 (i === that._lastChangedValue || that.values(i) === o.min))) { 14765 distance = thisDistance; 14766 closestHandle = $(this); 14767 index = i; 14768 } 14769 }); 14770 14771 allowed = this._start(event, index); 14772 if (allowed === false) { 14773 return false; 14774 } 14775 this._mouseSliding = true; 14776 14777 this._handleIndex = index; 14778 14779 this._addClass(closestHandle, null, "ui-state-active"); 14780 closestHandle.trigger("focus"); 14781 14782 offset = closestHandle.offset(); 14783 mouseOverHandle = !$(event.target).parents().addBack().is(".ui-slider-handle"); 14784 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { 14785 left: event.pageX - offset.left - (closestHandle.width() / 2), 14786 top: event.pageY - offset.top - 14787 (closestHandle.height() / 2) - 14788 (parseInt(closestHandle.css("borderTopWidth"), 10) || 0) - 14789 (parseInt(closestHandle.css("borderBottomWidth"), 10) || 0) + 14790 (parseInt(closestHandle.css("marginTop"), 10) || 0) 14791 }; 14792 14793 if (!this.handles.hasClass("ui-state-hover")) { 14794 this._slide(event, index, normValue); 14795 } 14796 this._animateOff = true; 14797 return true; 14798 }, 14799 14800 _mouseStart: function () { 14801 return true; 14802 }, 14803 14804 _mouseDrag: function (event) { 14805 var position = { x: event.pageX, y: event.pageY }, 14806 normValue = this._normValueFromMouse(position); 14807 14808 this._slide(event, this._handleIndex, normValue); 14809 14810 return false; 14811 }, 14812 14813 _mouseStop: function (event) { 14814 this._removeClass(this.handles, null, "ui-state-active"); 14815 this._mouseSliding = false; 14816 14817 this._stop(event, this._handleIndex); 14818 this._change(event, this._handleIndex); 14819 14820 this._handleIndex = null; 14821 this._clickOffset = null; 14822 this._animateOff = false; 14823 14824 return false; 14825 }, 14826 14827 _detectOrientation: function () { 14828 this.orientation = (this.options.orientation === "vertical") ? "vertical" : "horizontal"; 14829 }, 14830 14831 _normValueFromMouse: function (position) { 14832 var pixelTotal, 14833 pixelMouse, 14834 percentMouse, 14835 valueTotal, 14836 valueMouse; 14837 14838 if (this.orientation === "horizontal") { 14839 pixelTotal = this.elementSize.width; 14840 pixelMouse = position.x - this.elementOffset.left - 14841 (this._clickOffset ? this._clickOffset.left : 0); 14842 } else { 14843 pixelTotal = this.elementSize.height; 14844 pixelMouse = position.y - this.elementOffset.top - 14845 (this._clickOffset ? this._clickOffset.top : 0); 14846 } 14847 14848 percentMouse = (pixelMouse / pixelTotal); 14849 if (percentMouse > 1) { 14850 percentMouse = 1; 14851 } 14852 if (percentMouse < 0) { 14853 percentMouse = 0; 14854 } 14855 if (this.orientation === "vertical") { 14856 percentMouse = 1 - percentMouse; 14857 } 14858 14859 valueTotal = this._valueMax() - this._valueMin(); 14860 valueMouse = this._valueMin() + percentMouse * valueTotal; 14861 14862 return this._trimAlignValue(valueMouse); 14863 }, 14864 14865 _uiHash: function (index, value, values) { 14866 var uiHash = { 14867 handle: this.handles[index], 14868 handleIndex: index, 14869 value: value !== undefined ? value : this.value() 14870 }; 14871 14872 if (this._hasMultipleValues()) { 14873 uiHash.value = value !== undefined ? value : this.values(index); 14874 uiHash.values = values || this.values(); 14875 } 14876 14877 return uiHash; 14878 }, 14879 14880 _hasMultipleValues: function () { 14881 return this.options.values && this.options.values.length; 14882 }, 14883 14884 _start: function (event, index) { 14885 return this._trigger("start", event, this._uiHash(index)); 14886 }, 14887 14888 _slide: function (event, index, newVal) { 14889 var allowed, otherVal, 14890 currentValue = this.value(), 14891 newValues = this.values(); 14892 14893 if (this._hasMultipleValues()) { 14894 otherVal = this.values(index ? 0 : 1); 14895 currentValue = this.values(index); 14896 14897 if (this.options.values.length === 2 && this.options.range === true) { 14898 newVal = index === 0 ? Math.min(otherVal, newVal) : Math.max(otherVal, newVal); 14899 } 14900 14901 newValues[index] = newVal; 14902 } 14903 14904 if (newVal === currentValue) { 14905 return; 14906 } 14907 14908 allowed = this._trigger("slide", event, this._uiHash(index, newVal, newValues)); 14909 14910 // A slide can be canceled by returning false from the slide callback 14911 if (allowed === false) { 14912 return; 14913 } 14914 14915 if (this._hasMultipleValues()) { 14916 this.values(index, newVal); 14917 } else { 14918 this.value(newVal); 14919 } 14920 }, 14921 14922 _stop: function (event, index) { 14923 this._trigger("stop", event, this._uiHash(index)); 14924 }, 14925 14926 _change: function (event, index) { 14927 if (!this._keySliding && !this._mouseSliding) { 14928 14929 //store the last changed value index for reference when handles overlap 14930 this._lastChangedValue = index; 14931 this._trigger("change", event, this._uiHash(index)); 14932 } 14933 }, 14934 14935 value: function (newValue) { 14936 if (arguments.length) { 14937 this.options.value = this._trimAlignValue(newValue); 14938 this._refreshValue(); 14939 this._change(null, 0); 14940 return; 14941 } 14942 14943 return this._value(); 14944 }, 14945 14946 values: function (index, newValue) { 14947 var vals, 14948 newValues, 14949 i; 14950 14951 if (arguments.length > 1) { 14952 this.options.values[index] = this._trimAlignValue(newValue); 14953 this._refreshValue(); 14954 this._change(null, index); 14955 return; 14956 } 14957 14958 if (arguments.length) { 14959 if (Array.isArray(arguments[0])) { 14960 vals = this.options.values; 14961 newValues = arguments[0]; 14962 for (i = 0; i < vals.length; i += 1) { 14963 vals[i] = this._trimAlignValue(newValues[i]); 14964 this._change(null, i); 14965 } 14966 this._refreshValue(); 14967 } else { 14968 if (this._hasMultipleValues()) { 14969 return this._values(index); 14970 } else { 14971 return this.value(); 14972 } 14973 } 14974 } else { 14975 return this._values(); 14976 } 14977 }, 14978 14979 _setOption: function (key, value) { 14980 var i, 14981 valsLength = 0; 14982 14983 if (key === "range" && this.options.range === true) { 14984 if (value === "min") { 14985 this.options.value = this._values(0); 14986 this.options.values = null; 14987 } else if (value === "max") { 14988 this.options.value = this._values(this.options.values.length - 1); 14989 this.options.values = null; 14990 } 14991 } 14992 14993 if (Array.isArray(this.options.values)) { 14994 valsLength = this.options.values.length; 14995 } 14996 14997 this._super(key, value); 14998 14999 switch (key) { 15000 case "orientation": 15001 this._detectOrientation(); 15002 this._removeClass("ui-slider-horizontal ui-slider-vertical") 15003 ._addClass("ui-slider-" + this.orientation); 15004 this._refreshValue(); 15005 if (this.options.range) { 15006 this._refreshRange(value); 15007 } 15008 15009 // Reset positioning from previous orientation 15010 this.handles.css(value === "horizontal" ? "bottom" : "left", ""); 15011 break; 15012 case "value": 15013 this._animateOff = true; 15014 this._refreshValue(); 15015 this._change(null, 0); 15016 this._animateOff = false; 15017 break; 15018 case "values": 15019 this._animateOff = true; 15020 this._refreshValue(); 15021 15022 // Start from the last handle to prevent unreachable handles (#9046) 15023 for (i = valsLength - 1; i >= 0; i--) { 15024 this._change(null, i); 15025 } 15026 this._animateOff = false; 15027 break; 15028 case "step": 15029 case "min": 15030 case "max": 15031 this._animateOff = true; 15032 this._calculateNewMax(); 15033 this._refreshValue(); 15034 this._animateOff = false; 15035 break; 15036 case "range": 15037 this._animateOff = true; 15038 this._refresh(); 15039 this._animateOff = false; 15040 break; 15041 } 15042 }, 15043 15044 _setOptionDisabled: function (value) { 15045 this._super(value); 15046 15047 this._toggleClass(null, "ui-state-disabled", !!value); 15048 }, 15049 15050 //internal value getter 15051 // _value() returns value trimmed by min and max, aligned by step 15052 _value: function () { 15053 var val = this.options.value; 15054 val = this._trimAlignValue(val); 15055 15056 return val; 15057 }, 15058 15059 //internal values getter 15060 // _values() returns array of values trimmed by min and max, aligned by step 15061 // _values( index ) returns single value trimmed by min and max, aligned by step 15062 _values: function (index) { 15063 var val, 15064 vals, 15065 i; 15066 15067 if (arguments.length) { 15068 val = this.options.values[index]; 15069 val = this._trimAlignValue(val); 15070 15071 return val; 15072 } else if (this._hasMultipleValues()) { 15073 15074 // .slice() creates a copy of the array 15075 // this copy gets trimmed by min and max and then returned 15076 vals = this.options.values.slice(); 15077 for (i = 0; i < vals.length; i += 1) { 15078 vals[i] = this._trimAlignValue(vals[i]); 15079 } 15080 15081 return vals; 15082 } else { 15083 return []; 15084 } 15085 }, 15086 15087 // Returns the step-aligned value that val is closest to, between (inclusive) min and max 15088 _trimAlignValue: function (val) { 15089 if (val <= this._valueMin()) { 15090 return this._valueMin(); 15091 } 15092 if (val >= this._valueMax()) { 15093 return this._valueMax(); 15094 } 15095 var step = (this.options.step > 0) ? this.options.step : 1, 15096 valModStep = (val - this._valueMin()) % step, 15097 alignValue = val - valModStep; 15098 15099 if (Math.abs(valModStep) * 2 >= step) { 15100 alignValue += (valModStep > 0) ? step : (-step); 15101 } 15102 15103 // Since JavaScript has problems with large floats, round 15104 // the final value to 5 digits after the decimal point (see #4124) 15105 return parseFloat(alignValue.toFixed(5)); 15106 }, 15107 15108 _calculateNewMax: function () { 15109 var max = this.options.max, 15110 min = this._valueMin(), 15111 step = this.options.step, 15112 aboveMin = Math.round((max - min) / step) * step; 15113 max = aboveMin + min; 15114 if (max > this.options.max) { 15115 15116 //If max is not divisible by step, rounding off may increase its value 15117 max -= step; 15118 } 15119 this.max = parseFloat(max.toFixed(this._precision())); 15120 }, 15121 15122 _precision: function () { 15123 var precision = this._precisionOf(this.options.step); 15124 if (this.options.min !== null) { 15125 precision = Math.max(precision, this._precisionOf(this.options.min)); 15126 } 15127 return precision; 15128 }, 15129 15130 _precisionOf: function (num) { 15131 var str = num.toString(), 15132 decimal = str.indexOf("."); 15133 return decimal === -1 ? 0 : str.length - decimal - 1; 15134 }, 15135 15136 _valueMin: function () { 15137 return this.options.min; 15138 }, 15139 15140 _valueMax: function () { 15141 return this.max; 15142 }, 15143 15144 _refreshRange: function (orientation) { 15145 if (orientation === "vertical") { 15146 this.range.css({ "width": "", "left": "" }); 15147 } 15148 if (orientation === "horizontal") { 15149 this.range.css({ "height": "", "bottom": "" }); 15150 } 15151 }, 15152 15153 _refreshValue: function () { 15154 var lastValPercent, valPercent, value, valueMin, valueMax, 15155 oRange = this.options.range, 15156 o = this.options, 15157 that = this, 15158 animate = (!this._animateOff) ? o.animate : false, 15159 _set = {}; 15160 15161 if (this._hasMultipleValues()) { 15162 this.handles.each(function (i) { 15163 valPercent = (that.values(i) - that._valueMin()) / (that._valueMax() - 15164 that._valueMin()) * 100; 15165 _set[that.orientation === "horizontal" ? "left" : "bottom"] = valPercent + "%"; 15166 $(this).stop(1, 1)[animate ? "animate" : "css"](_set, o.animate); 15167 if (that.options.range === true) { 15168 if (that.orientation === "horizontal") { 15169 if (i === 0) { 15170 that.range.stop(1, 1)[animate ? "animate" : "css"]({ 15171 left: valPercent + "%" 15172 }, o.animate); 15173 } 15174 if (i === 1) { 15175 that.range[animate ? "animate" : "css"]({ 15176 width: (valPercent - lastValPercent) + "%" 15177 }, { 15178 queue: false, 15179 duration: o.animate 15180 }); 15181 } 15182 } else { 15183 if (i === 0) { 15184 that.range.stop(1, 1)[animate ? "animate" : "css"]({ 15185 bottom: (valPercent) + "%" 15186 }, o.animate); 15187 } 15188 if (i === 1) { 15189 that.range[animate ? "animate" : "css"]({ 15190 height: (valPercent - lastValPercent) + "%" 15191 }, { 15192 queue: false, 15193 duration: o.animate 15194 }); 15195 } 15196 } 15197 } 15198 lastValPercent = valPercent; 15199 }); 15200 } else { 15201 value = this.value(); 15202 valueMin = this._valueMin(); 15203 valueMax = this._valueMax(); 15204 valPercent = (valueMax !== valueMin) ? 15205 (value - valueMin) / (valueMax - valueMin) * 100 : 15206 0; 15207 _set[this.orientation === "horizontal" ? "left" : "bottom"] = valPercent + "%"; 15208 this.handle.stop(1, 1)[animate ? "animate" : "css"](_set, o.animate); 15209 15210 if (oRange === "min" && this.orientation === "horizontal") { 15211 this.range.stop(1, 1)[animate ? "animate" : "css"]({ 15212 width: valPercent + "%" 15213 }, o.animate); 15214 } 15215 if (oRange === "max" && this.orientation === "horizontal") { 15216 this.range.stop(1, 1)[animate ? "animate" : "css"]({ 15217 width: (100 - valPercent) + "%" 15218 }, o.animate); 15219 } 15220 if (oRange === "min" && this.orientation === "vertical") { 15221 this.range.stop(1, 1)[animate ? "animate" : "css"]({ 15222 height: valPercent + "%" 15223 }, o.animate); 15224 } 15225 if (oRange === "max" && this.orientation === "vertical") { 15226 this.range.stop(1, 1)[animate ? "animate" : "css"]({ 15227 height: (100 - valPercent) + "%" 15228 }, o.animate); 15229 } 15230 } 15231 }, 15232 15233 _handleEvents: { 15234 keydown: function (event) { 15235 var allowed, curVal, newVal, step, 15236 index = $(event.target).data("ui-slider-handle-index"); 15237 15238 switch (event.keyCode) { 15239 case $.ui.keyCode.HOME: 15240 case $.ui.keyCode.END: 15241 case $.ui.keyCode.PAGE_UP: 15242 case $.ui.keyCode.PAGE_DOWN: 15243 case $.ui.keyCode.UP: 15244 case $.ui.keyCode.RIGHT: 15245 case $.ui.keyCode.DOWN: 15246 case $.ui.keyCode.LEFT: 15247 event.preventDefault(); 15248 if (!this._keySliding) { 15249 this._keySliding = true; 15250 this._addClass($(event.target), null, "ui-state-active"); 15251 allowed = this._start(event, index); 15252 if (allowed === false) { 15253 return; 15254 } 15255 } 15256 break; 15257 } 15258 15259 step = this.options.step; 15260 if (this._hasMultipleValues()) { 15261 curVal = newVal = this.values(index); 15262 } else { 15263 curVal = newVal = this.value(); 15264 } 15265 15266 switch (event.keyCode) { 15267 case $.ui.keyCode.HOME: 15268 newVal = this._valueMin(); 15269 break; 15270 case $.ui.keyCode.END: 15271 newVal = this._valueMax(); 15272 break; 15273 case $.ui.keyCode.PAGE_UP: 15274 newVal = this._trimAlignValue( 15275 curVal + ((this._valueMax() - this._valueMin()) / this.numPages) 15276 ); 15277 break; 15278 case $.ui.keyCode.PAGE_DOWN: 15279 newVal = this._trimAlignValue( 15280 curVal - ((this._valueMax() - this._valueMin()) / this.numPages)); 15281 break; 15282 case $.ui.keyCode.UP: 15283 case $.ui.keyCode.RIGHT: 15284 if (curVal === this._valueMax()) { 15285 return; 15286 } 15287 newVal = this._trimAlignValue(curVal + step); 15288 break; 15289 case $.ui.keyCode.DOWN: 15290 case $.ui.keyCode.LEFT: 15291 if (curVal === this._valueMin()) { 15292 return; 15293 } 15294 newVal = this._trimAlignValue(curVal - step); 15295 break; 15296 } 15297 15298 this._slide(event, index, newVal); 15299 }, 15300 keyup: function (event) { 15301 var index = $(event.target).data("ui-slider-handle-index"); 15302 15303 if (this._keySliding) { 15304 this._keySliding = false; 15305 this._stop(event, index); 15306 this._change(event, index); 15307 this._removeClass($(event.target), null, "ui-state-active"); 15308 } 15309 } 15310 } 15311 }); 15312 15313 15314 /*! 15315 * jQuery UI Sortable 1.14.1 15316 * https://jqueryui.com 15317 * 15318 * Copyright OpenJS Foundation and other contributors 15319 * Released under the MIT license. 15320 * https://jquery.org/license 15321 */ 15322 15323 //>>label: Sortable 15324 //>>group: Interactions 15325 //>>description: Enables items in a list to be sorted using the mouse. 15326 //>>docs: https://api.jqueryui.com/sortable/ 15327 //>>demos: https://jqueryui.com/sortable/ 15328 //>>css.structure: ../../themes/base/sortable.css 15329 15330 15331 var widgetsSortable = $.widget("ui.sortable", $.ui.mouse, { 15332 version: "1.14.1", 15333 widgetEventPrefix: "sort", 15334 ready: false, 15335 options: { 15336 appendTo: "parent", 15337 axis: false, 15338 connectWith: false, 15339 containment: false, 15340 cursor: "auto", 15341 cursorAt: false, 15342 dropOnEmpty: true, 15343 forcePlaceholderSize: false, 15344 forceHelperSize: false, 15345 grid: false, 15346 handle: false, 15347 helper: "original", 15348 items: "> *", 15349 opacity: false, 15350 placeholder: false, 15351 revert: false, 15352 scroll: true, 15353 scrollSensitivity: 20, 15354 scrollSpeed: 20, 15355 scope: "default", 15356 tolerance: "intersect", 15357 zIndex: 1000, 15358 15359 // Callbacks 15360 activate: null, 15361 beforeStop: null, 15362 change: null, 15363 deactivate: null, 15364 out: null, 15365 over: null, 15366 receive: null, 15367 remove: null, 15368 sort: null, 15369 start: null, 15370 stop: null, 15371 update: null 15372 }, 15373 15374 _isOverAxis: function (x, reference, size) { 15375 return (x >= reference) && (x < (reference + size)); 15376 }, 15377 15378 _isFloating: function (item) { 15379 return (/left|right/).test(item.css("float")) || 15380 (/inline|table-cell/).test(item.css("display")); 15381 }, 15382 15383 _create: function () { 15384 this.containerCache = {}; 15385 this._addClass("ui-sortable"); 15386 15387 //Get the items 15388 this.refresh(); 15389 15390 //Let's determine the parent's offset 15391 this.offset = this.element.offset(); 15392 15393 //Initialize mouse events for interaction 15394 this._mouseInit(); 15395 15396 this._setHandleClassName(); 15397 15398 //We're ready to go 15399 this.ready = true; 15400 15401 }, 15402 15403 _setOption: function (key, value) { 15404 this._super(key, value); 15405 15406 if (key === "handle") { 15407 this._setHandleClassName(); 15408 } 15409 }, 15410 15411 _setHandleClassName: function () { 15412 var that = this; 15413 this._removeClass(this.element.find(".ui-sortable-handle"), "ui-sortable-handle"); 15414 $.each(this.items, function () { 15415 that._addClass( 15416 this.instance.options.handle ? 15417 this.item.find(this.instance.options.handle) : 15418 this.item, 15419 "ui-sortable-handle" 15420 ); 15421 }); 15422 }, 15423 15424 _destroy: function () { 15425 this._mouseDestroy(); 15426 15427 for (var i = this.items.length - 1; i >= 0; i--) { 15428 this.items[i].item.removeData(this.widgetName + "-item"); 15429 } 15430 15431 return this; 15432 }, 15433 15434 _mouseCapture: function (event, overrideHandle) { 15435 var currentItem = null, 15436 validHandle = false, 15437 that = this; 15438 15439 if (this.reverting) { 15440 return false; 15441 } 15442 15443 if (this.options.disabled || this.options.type === "static") { 15444 return false; 15445 } 15446 15447 //We have to refresh the items data once first 15448 this._refreshItems(event); 15449 15450 //Find out if the clicked node (or one of its parents) is a actual item in this.items 15451 $(event.target).parents().each(function () { 15452 if ($.data(this, that.widgetName + "-item") === that) { 15453 currentItem = $(this); 15454 return false; 15455 } 15456 }); 15457 if ($.data(event.target, that.widgetName + "-item") === that) { 15458 currentItem = $(event.target); 15459 } 15460 15461 if (!currentItem) { 15462 return false; 15463 } 15464 if (this.options.handle && !overrideHandle) { 15465 $(this.options.handle, currentItem).find("*").addBack().each(function () { 15466 if (this === event.target) { 15467 validHandle = true; 15468 } 15469 }); 15470 if (!validHandle) { 15471 return false; 15472 } 15473 } 15474 15475 this.currentItem = currentItem; 15476 this._removeCurrentsFromItems(); 15477 return true; 15478 15479 }, 15480 15481 _mouseStart: function (event, overrideHandle, noActivation) { 15482 15483 var i, body, 15484 o = this.options; 15485 15486 this.currentContainer = this; 15487 15488 //We only need to call refreshPositions, because the refreshItems call has been moved to 15489 // mouseCapture 15490 this.refreshPositions(); 15491 15492 //Prepare the dragged items parent 15493 this.appendTo = $(o.appendTo !== "parent" ? 15494 o.appendTo : 15495 this.currentItem.parent()); 15496 15497 //Create and append the visible helper 15498 this.helper = this._createHelper(event); 15499 15500 //Cache the helper size 15501 this._cacheHelperProportions(); 15502 15503 /* 15504 * - Position generation - 15505 * This block generates everything position related - it's the core of draggables. 15506 */ 15507 15508 //Cache the margins of the original element 15509 this._cacheMargins(); 15510 15511 //The element's absolute position on the page minus margins 15512 this.offset = this.currentItem.offset(); 15513 this.offset = { 15514 top: this.offset.top - this.margins.top, 15515 left: this.offset.left - this.margins.left 15516 }; 15517 15518 $.extend(this.offset, { 15519 click: { //Where the click happened, relative to the element 15520 left: event.pageX - this.offset.left, 15521 top: event.pageY - this.offset.top 15522 }, 15523 15524 // This is a relative to absolute position minus the actual position calculation - 15525 // only used for relative positioned helper 15526 relative: this._getRelativeOffset() 15527 }); 15528 15529 // After we get the helper offset, but before we get the parent offset we can 15530 // change the helper's position to absolute 15531 // TODO: Still need to figure out a way to make relative sorting possible 15532 this.helper.css("position", "absolute"); 15533 this.cssPosition = this.helper.css("position"); 15534 15535 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 15536 if (o.cursorAt) { 15537 this._adjustOffsetFromHelper(o.cursorAt); 15538 } 15539 15540 //Cache the former DOM position 15541 this.domPosition = { 15542 prev: this.currentItem.prev()[0], 15543 parent: this.currentItem.parent()[0] 15544 }; 15545 15546 // If the helper is not the original, hide the original so it's not playing any role during 15547 // the drag, won't cause anything bad this way 15548 if (this.helper[0] !== this.currentItem[0]) { 15549 this.currentItem.hide(); 15550 } 15551 15552 //Create the placeholder 15553 this._createPlaceholder(); 15554 15555 //Get the next scrolling parent 15556 this.scrollParent = this.placeholder.scrollParent(); 15557 15558 $.extend(this.offset, { 15559 parent: this._getParentOffset() 15560 }); 15561 15562 //Set a containment if given in the options 15563 if (o.containment) { 15564 this._setContainment(); 15565 } 15566 15567 if (o.cursor && o.cursor !== "auto") { // cursor option 15568 body = this.document.find("body"); 15569 15570 this._storedStylesheet = 15571 $("<style>*{ cursor: " + o.cursor + " !important; }</style>").appendTo(body); 15572 } 15573 15574 // We need to make sure to grab the zIndex before setting the 15575 // opacity, because setting the opacity to anything lower than 1 15576 // causes the zIndex to change from "auto" to 0. 15577 if (o.zIndex) { // zIndex option 15578 if (this.helper.css("zIndex")) { 15579 this._storedZIndex = this.helper.css("zIndex"); 15580 } 15581 this.helper.css("zIndex", o.zIndex); 15582 } 15583 15584 if (o.opacity) { // opacity option 15585 if (this.helper.css("opacity")) { 15586 this._storedOpacity = this.helper.css("opacity"); 15587 } 15588 this.helper.css("opacity", o.opacity); 15589 } 15590 15591 //Prepare scrolling 15592 if (this.scrollParent[0] !== this.document[0] && 15593 this.scrollParent[0].tagName !== "HTML") { 15594 this.overflowOffset = this.scrollParent.offset(); 15595 } 15596 15597 //Call callbacks 15598 this._trigger("start", event, this._uiHash()); 15599 15600 //Recache the helper size 15601 if (!this._preserveHelperProportions) { 15602 this._cacheHelperProportions(); 15603 } 15604 15605 //Post "activate" events to possible containers 15606 if (!noActivation) { 15607 for (i = this.containers.length - 1; i >= 0; i--) { 15608 this.containers[i]._trigger("activate", event, this._uiHash(this)); 15609 } 15610 } 15611 15612 //Prepare possible droppables 15613 if ($.ui.ddmanager) { 15614 $.ui.ddmanager.current = this; 15615 } 15616 15617 if ($.ui.ddmanager && !o.dropBehaviour) { 15618 $.ui.ddmanager.prepareOffsets(this, event); 15619 } 15620 15621 this.dragging = true; 15622 15623 this._addClass(this.helper, "ui-sortable-helper"); 15624 15625 //Move the helper, if needed 15626 if (!this.helper.parent().is(this.appendTo)) { 15627 this.helper.detach().appendTo(this.appendTo); 15628 15629 //Update position 15630 this.offset.parent = this._getParentOffset(); 15631 } 15632 15633 //Generate the original position 15634 this.position = this.originalPosition = this._generatePosition(event); 15635 this.originalPageX = event.pageX; 15636 this.originalPageY = event.pageY; 15637 this.lastPositionAbs = this.positionAbs = this._convertPositionTo("absolute"); 15638 15639 this._mouseDrag(event); 15640 15641 return true; 15642 15643 }, 15644 15645 _scroll: function (event) { 15646 var o = this.options, 15647 scrolled = false; 15648 15649 if (this.scrollParent[0] !== this.document[0] && 15650 this.scrollParent[0].tagName !== "HTML") { 15651 15652 if ((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - 15653 event.pageY < o.scrollSensitivity) { 15654 this.scrollParent[0].scrollTop = 15655 scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; 15656 } else if (event.pageY - this.overflowOffset.top < o.scrollSensitivity) { 15657 this.scrollParent[0].scrollTop = 15658 scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; 15659 } 15660 15661 if ((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - 15662 event.pageX < o.scrollSensitivity) { 15663 this.scrollParent[0].scrollLeft = scrolled = 15664 this.scrollParent[0].scrollLeft + o.scrollSpeed; 15665 } else if (event.pageX - this.overflowOffset.left < o.scrollSensitivity) { 15666 this.scrollParent[0].scrollLeft = scrolled = 15667 this.scrollParent[0].scrollLeft - o.scrollSpeed; 15668 } 15669 15670 } else { 15671 15672 if (event.pageY - this.document.scrollTop() < o.scrollSensitivity) { 15673 scrolled = this.document.scrollTop(this.document.scrollTop() - o.scrollSpeed); 15674 } else if (this.window.height() - (event.pageY - this.document.scrollTop()) < 15675 o.scrollSensitivity) { 15676 scrolled = this.document.scrollTop(this.document.scrollTop() + o.scrollSpeed); 15677 } 15678 15679 if (event.pageX - this.document.scrollLeft() < o.scrollSensitivity) { 15680 scrolled = this.document.scrollLeft( 15681 this.document.scrollLeft() - o.scrollSpeed 15682 ); 15683 } else if (this.window.width() - (event.pageX - this.document.scrollLeft()) < 15684 o.scrollSensitivity) { 15685 scrolled = this.document.scrollLeft( 15686 this.document.scrollLeft() + o.scrollSpeed 15687 ); 15688 } 15689 15690 } 15691 15692 return scrolled; 15693 }, 15694 15695 _mouseDrag: function (event) { 15696 var i, item, itemElement, intersection, 15697 o = this.options; 15698 15699 //Compute the helpers position 15700 this.position = this._generatePosition(event); 15701 this.positionAbs = this._convertPositionTo("absolute"); 15702 15703 //Set the helper position 15704 if (!this.options.axis || this.options.axis !== "y") { 15705 this.helper[0].style.left = this.position.left + "px"; 15706 } 15707 if (!this.options.axis || this.options.axis !== "x") { 15708 this.helper[0].style.top = this.position.top + "px"; 15709 } 15710 15711 //Do scrolling 15712 if (o.scroll) { 15713 if (this._scroll(event) !== false) { 15714 15715 //Update item positions used in position checks 15716 this._refreshItemPositions(true); 15717 15718 if ($.ui.ddmanager && !o.dropBehaviour) { 15719 $.ui.ddmanager.prepareOffsets(this, event); 15720 } 15721 } 15722 } 15723 15724 this.dragDirection = { 15725 vertical: this._getDragVerticalDirection(), 15726 horizontal: this._getDragHorizontalDirection() 15727 }; 15728 15729 //Rearrange 15730 for (i = this.items.length - 1; i >= 0; i--) { 15731 15732 //Cache variables and intersection, continue if no intersection 15733 item = this.items[i]; 15734 itemElement = item.item[0]; 15735 intersection = this._intersectsWithPointer(item); 15736 if (!intersection) { 15737 continue; 15738 } 15739 15740 // Only put the placeholder inside the current Container, skip all 15741 // items from other containers. This works because when moving 15742 // an item from one container to another the 15743 // currentContainer is switched before the placeholder is moved. 15744 // 15745 // Without this, moving items in "sub-sortables" can cause 15746 // the placeholder to jitter between the outer and inner container. 15747 if (item.instance !== this.currentContainer) { 15748 continue; 15749 } 15750 15751 // Cannot intersect with itself 15752 // no useless actions that have been done before 15753 // no action if the item moved is the parent of the item checked 15754 if (itemElement !== this.currentItem[0] && 15755 this.placeholder[intersection === 1 ? 15756 "next" : "prev"]()[0] !== itemElement && 15757 !$.contains(this.placeholder[0], itemElement) && 15758 (this.options.type === "semi-dynamic" ? 15759 !$.contains(this.element[0], itemElement) : 15760 true 15761 ) 15762 ) { 15763 15764 this.direction = intersection === 1 ? "down" : "up"; 15765 15766 if (this.options.tolerance === "pointer" || 15767 this._intersectsWithSides(item)) { 15768 this._rearrange(event, item); 15769 } else { 15770 break; 15771 } 15772 15773 this._trigger("change", event, this._uiHash()); 15774 break; 15775 } 15776 } 15777 15778 //Post events to containers 15779 this._contactContainers(event); 15780 15781 //Interconnect with droppables 15782 if ($.ui.ddmanager) { 15783 $.ui.ddmanager.drag(this, event); 15784 } 15785 15786 //Call callbacks 15787 this._trigger("sort", event, this._uiHash()); 15788 15789 this.lastPositionAbs = this.positionAbs; 15790 return false; 15791 15792 }, 15793 15794 _mouseStop: function (event, noPropagation) { 15795 15796 if (!event) { 15797 return; 15798 } 15799 15800 //If we are using droppables, inform the manager about the drop 15801 if ($.ui.ddmanager && !this.options.dropBehaviour) { 15802 $.ui.ddmanager.drop(this, event); 15803 } 15804 15805 if (this.options.revert) { 15806 var that = this, 15807 cur = this.placeholder.offset(), 15808 axis = this.options.axis, 15809 animation = {}; 15810 15811 if (!axis || axis === "x") { 15812 animation.left = cur.left - this.offset.parent.left - this.margins.left + 15813 (this.offsetParent[0] === this.document[0].body ? 15814 0 : 15815 this.offsetParent[0].scrollLeft 15816 ); 15817 } 15818 if (!axis || axis === "y") { 15819 animation.top = cur.top - this.offset.parent.top - this.margins.top + 15820 (this.offsetParent[0] === this.document[0].body ? 15821 0 : 15822 this.offsetParent[0].scrollTop 15823 ); 15824 } 15825 this.reverting = true; 15826 $(this.helper).animate( 15827 animation, 15828 parseInt(this.options.revert, 10) || 500, 15829 function () { 15830 that._clear(event); 15831 } 15832 ); 15833 } else { 15834 this._clear(event, noPropagation); 15835 } 15836 15837 return false; 15838 15839 }, 15840 15841 cancel: function () { 15842 15843 if (this.dragging) { 15844 15845 this._mouseUp(new $.Event("mouseup", { target: null })); 15846 15847 if (this.options.helper === "original") { 15848 this.currentItem.css(this._storedCSS); 15849 this._removeClass(this.currentItem, "ui-sortable-helper"); 15850 } else { 15851 this.currentItem.show(); 15852 } 15853 15854 //Post deactivating events to containers 15855 for (var i = this.containers.length - 1; i >= 0; i--) { 15856 this.containers[i]._trigger("deactivate", null, this._uiHash(this)); 15857 if (this.containers[i].containerCache.over) { 15858 this.containers[i]._trigger("out", null, this._uiHash(this)); 15859 this.containers[i].containerCache.over = 0; 15860 } 15861 } 15862 15863 } 15864 15865 if (this.placeholder) { 15866 15867 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, 15868 // it unbinds ALL events from the original node! 15869 if (this.placeholder[0].parentNode) { 15870 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 15871 } 15872 if (this.options.helper !== "original" && this.helper && 15873 this.helper[0].parentNode) { 15874 this.helper.remove(); 15875 } 15876 15877 $.extend(this, { 15878 helper: null, 15879 dragging: false, 15880 reverting: false, 15881 _noFinalSort: null 15882 }); 15883 15884 if (this.domPosition.prev) { 15885 $(this.domPosition.prev).after(this.currentItem); 15886 } else { 15887 $(this.domPosition.parent).prepend(this.currentItem); 15888 } 15889 } 15890 15891 return this; 15892 15893 }, 15894 15895 serialize: function (o) { 15896 15897 var items = this._getItemsAsjQuery(o && o.connected), 15898 str = []; 15899 o = o || {}; 15900 15901 $(items).each(function () { 15902 var res = ($(o.item || this).attr(o.attribute || "id") || "") 15903 .match(o.expression || (/(.+)[\-=_](.+)/)); 15904 if (res) { 15905 str.push( 15906 (o.key || res[1] + "[]") + 15907 "=" + (o.key && o.expression ? res[1] : res[2])); 15908 } 15909 }); 15910 15911 if (!str.length && o.key) { 15912 str.push(o.key + "="); 15913 } 15914 15915 return str.join("&"); 15916 15917 }, 15918 15919 toArray: function (o) { 15920 15921 var items = this._getItemsAsjQuery(o && o.connected), 15922 ret = []; 15923 15924 o = o || {}; 15925 15926 items.each(function () { 15927 ret.push($(o.item || this).attr(o.attribute || "id") || ""); 15928 }); 15929 return ret; 15930 15931 }, 15932 15933 /* Be careful with the following core functions */ 15934 _intersectsWith: function (item) { 15935 15936 var x1 = this.positionAbs.left, 15937 x2 = x1 + this.helperProportions.width, 15938 y1 = this.positionAbs.top, 15939 y2 = y1 + this.helperProportions.height, 15940 l = item.left, 15941 r = l + item.width, 15942 t = item.top, 15943 b = t + item.height, 15944 dyClick = this.offset.click.top, 15945 dxClick = this.offset.click.left, 15946 isOverElementHeight = (this.options.axis === "x") || ((y1 + dyClick) > t && 15947 (y1 + dyClick) < b), 15948 isOverElementWidth = (this.options.axis === "y") || ((x1 + dxClick) > l && 15949 (x1 + dxClick) < r), 15950 isOverElement = isOverElementHeight && isOverElementWidth; 15951 15952 if (this.options.tolerance === "pointer" || 15953 this.options.forcePointerForContainers || 15954 (this.options.tolerance !== "pointer" && 15955 this.helperProportions[this.floating ? "width" : "height"] > 15956 item[this.floating ? "width" : "height"]) 15957 ) { 15958 return isOverElement; 15959 } else { 15960 15961 return (l < x1 + (this.helperProportions.width / 2) && // Right Half 15962 x2 - (this.helperProportions.width / 2) < r && // Left Half 15963 t < y1 + (this.helperProportions.height / 2) && // Bottom Half 15964 y2 - (this.helperProportions.height / 2) < b); // Top Half 15965 15966 } 15967 }, 15968 15969 _intersectsWithPointer: function (item) { 15970 var verticalDirection, horizontalDirection, 15971 isOverElementHeight = (this.options.axis === "x") || 15972 this._isOverAxis( 15973 this.positionAbs.top + this.offset.click.top, item.top, item.height), 15974 isOverElementWidth = (this.options.axis === "y") || 15975 this._isOverAxis( 15976 this.positionAbs.left + this.offset.click.left, item.left, item.width), 15977 isOverElement = isOverElementHeight && isOverElementWidth; 15978 15979 if (!isOverElement) { 15980 return false; 15981 } 15982 15983 verticalDirection = this.dragDirection.vertical; 15984 horizontalDirection = this.dragDirection.horizontal; 15985 15986 return this.floating ? 15987 ((horizontalDirection === "right" || verticalDirection === "down") ? 2 : 1) : 15988 (verticalDirection && (verticalDirection === "down" ? 2 : 1)); 15989 15990 }, 15991 15992 _intersectsWithSides: function (item) { 15993 15994 var isOverBottomHalf = this._isOverAxis(this.positionAbs.top + 15995 this.offset.click.top, item.top + (item.height / 2), item.height), 15996 isOverRightHalf = this._isOverAxis(this.positionAbs.left + 15997 this.offset.click.left, item.left + (item.width / 2), item.width), 15998 verticalDirection = this.dragDirection.vertical, 15999 horizontalDirection = this.dragDirection.horizontal; 16000 16001 if (this.floating && horizontalDirection) { 16002 return ((horizontalDirection === "right" && isOverRightHalf) || 16003 (horizontalDirection === "left" && !isOverRightHalf)); 16004 } else { 16005 return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || 16006 (verticalDirection === "up" && !isOverBottomHalf)); 16007 } 16008 16009 }, 16010 16011 _getDragVerticalDirection: function () { 16012 var delta = this.positionAbs.top - this.lastPositionAbs.top; 16013 return delta !== 0 && (delta > 0 ? "down" : "up"); 16014 }, 16015 16016 _getDragHorizontalDirection: function () { 16017 var delta = this.positionAbs.left - this.lastPositionAbs.left; 16018 return delta !== 0 && (delta > 0 ? "right" : "left"); 16019 }, 16020 16021 refresh: function (event) { 16022 this._refreshItems(event); 16023 this._setHandleClassName(); 16024 this.refreshPositions(); 16025 return this; 16026 }, 16027 16028 _connectWith: function () { 16029 var options = this.options; 16030 return options.connectWith.constructor === String ? 16031 [options.connectWith] : 16032 options.connectWith; 16033 }, 16034 16035 _getItemsAsjQuery: function (connected) { 16036 16037 var i, j, cur, inst, 16038 items = [], 16039 queries = [], 16040 connectWith = this._connectWith(); 16041 16042 if (connectWith && connected) { 16043 for (i = connectWith.length - 1; i >= 0; i--) { 16044 cur = $(connectWith[i], this.document[0]); 16045 for (j = cur.length - 1; j >= 0; j--) { 16046 inst = $.data(cur[j], this.widgetFullName); 16047 if (inst && inst !== this && !inst.options.disabled) { 16048 queries.push([typeof inst.options.items === "function" ? 16049 inst.options.items.call(inst.element) : 16050 $(inst.options.items, inst.element) 16051 .not(".ui-sortable-helper") 16052 .not(".ui-sortable-placeholder"), inst]); 16053 } 16054 } 16055 } 16056 } 16057 16058 queries.push([typeof this.options.items === "function" ? 16059 this.options.items 16060 .call(this.element, null, { options: this.options, item: this.currentItem }) : 16061 $(this.options.items, this.element) 16062 .not(".ui-sortable-helper") 16063 .not(".ui-sortable-placeholder"), this]); 16064 16065 function addItems() { 16066 items.push(this); 16067 } 16068 for (i = queries.length - 1; i >= 0; i--) { 16069 queries[i][0].each(addItems); 16070 } 16071 16072 return $(items); 16073 16074 }, 16075 16076 _removeCurrentsFromItems: function () { 16077 16078 var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); 16079 16080 this.items = $.grep(this.items, function (item) { 16081 for (var j = 0; j < list.length; j++) { 16082 if (list[j] === item.item[0]) { 16083 return false; 16084 } 16085 } 16086 return true; 16087 }); 16088 16089 }, 16090 16091 _refreshItems: function (event) { 16092 16093 this.items = []; 16094 this.containers = [this]; 16095 16096 var i, j, cur, inst, targetData, _queries, item, queriesLength, 16097 items = this.items, 16098 queries = [[typeof this.options.items === "function" ? 16099 this.options.items.call(this.element[0], event, { item: this.currentItem }) : 16100 $(this.options.items, this.element), this]], 16101 connectWith = this._connectWith(); 16102 16103 //Shouldn't be run the first time through due to massive slow-down 16104 if (connectWith && this.ready) { 16105 for (i = connectWith.length - 1; i >= 0; i--) { 16106 cur = $(connectWith[i], this.document[0]); 16107 for (j = cur.length - 1; j >= 0; j--) { 16108 inst = $.data(cur[j], this.widgetFullName); 16109 if (inst && inst !== this && !inst.options.disabled) { 16110 queries.push([typeof inst.options.items === "function" ? 16111 inst.options.items 16112 .call(inst.element[0], event, { item: this.currentItem }) : 16113 $(inst.options.items, inst.element), inst]); 16114 this.containers.push(inst); 16115 } 16116 } 16117 } 16118 } 16119 16120 for (i = queries.length - 1; i >= 0; i--) { 16121 targetData = queries[i][1]; 16122 _queries = queries[i][0]; 16123 16124 for (j = 0, queriesLength = _queries.length; j < queriesLength; j++) { 16125 item = $(_queries[j]); 16126 16127 // Data for target checking (mouse manager) 16128 item.data(this.widgetName + "-item", targetData); 16129 16130 items.push({ 16131 item: item, 16132 instance: targetData, 16133 width: 0, height: 0, 16134 left: 0, top: 0 16135 }); 16136 } 16137 } 16138 16139 }, 16140 16141 _refreshItemPositions: function (fast) { 16142 var i, item, t, p; 16143 16144 for (i = this.items.length - 1; i >= 0; i--) { 16145 item = this.items[i]; 16146 16147 //We ignore calculating positions of all connected containers when we're not over them 16148 if (this.currentContainer && item.instance !== this.currentContainer && 16149 item.item[0] !== this.currentItem[0]) { 16150 continue; 16151 } 16152 16153 t = this.options.toleranceElement ? 16154 $(this.options.toleranceElement, item.item) : 16155 item.item; 16156 16157 if (!fast) { 16158 item.width = t.outerWidth(); 16159 item.height = t.outerHeight(); 16160 } 16161 16162 p = t.offset(); 16163 item.left = p.left; 16164 item.top = p.top; 16165 } 16166 }, 16167 16168 refreshPositions: function (fast) { 16169 16170 // Determine whether items are being displayed horizontally 16171 this.floating = this.items.length ? 16172 this.options.axis === "x" || this._isFloating(this.items[0].item) : 16173 false; 16174 16175 // This has to be redone because due to the item being moved out/into the offsetParent, 16176 // the offsetParent's position will change 16177 if (this.offsetParent && this.helper) { 16178 this.offset.parent = this._getParentOffset(); 16179 } 16180 16181 this._refreshItemPositions(fast); 16182 16183 var i, p; 16184 16185 if (this.options.custom && this.options.custom.refreshContainers) { 16186 this.options.custom.refreshContainers.call(this); 16187 } else { 16188 for (i = this.containers.length - 1; i >= 0; i--) { 16189 p = this.containers[i].element.offset(); 16190 this.containers[i].containerCache.left = p.left; 16191 this.containers[i].containerCache.top = p.top; 16192 this.containers[i].containerCache.width = 16193 this.containers[i].element.outerWidth(); 16194 this.containers[i].containerCache.height = 16195 this.containers[i].element.outerHeight(); 16196 } 16197 } 16198 16199 return this; 16200 }, 16201 16202 _createPlaceholder: function (that) { 16203 that = that || this; 16204 var className, nodeName, 16205 o = that.options; 16206 16207 if (!o.placeholder || o.placeholder.constructor === String) { 16208 className = o.placeholder; 16209 nodeName = that.currentItem[0].nodeName.toLowerCase(); 16210 o.placeholder = { 16211 element: function () { 16212 16213 var element = $("<" + nodeName + ">", that.document[0]); 16214 16215 that._addClass(element, "ui-sortable-placeholder", 16216 className || that.currentItem[0].className) 16217 ._removeClass(element, "ui-sortable-helper"); 16218 16219 if (nodeName === "tbody") { 16220 that._createTrPlaceholder( 16221 that.currentItem.find("tr").eq(0), 16222 $("<tr>", that.document[0]).appendTo(element) 16223 ); 16224 } else if (nodeName === "tr") { 16225 that._createTrPlaceholder(that.currentItem, element); 16226 } else if (nodeName === "img") { 16227 element.attr("src", that.currentItem.attr("src")); 16228 } 16229 16230 if (!className) { 16231 element.css("visibility", "hidden"); 16232 } 16233 16234 return element; 16235 }, 16236 update: function (container, p) { 16237 16238 // 1. If a className is set as 'placeholder option, we don't force sizes - 16239 // the class is responsible for that 16240 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a 16241 // class name is specified 16242 if (className && !o.forcePlaceholderSize) { 16243 return; 16244 } 16245 16246 // If the element doesn't have a actual height or width by itself (without 16247 // styles coming from a stylesheet), it receives the inline height and width 16248 // from the dragged item. Or, if it's a tbody or tr, it's going to have a height 16249 // anyway since we're populating them with <td>s above, but they're unlikely to 16250 // be the correct height on their own if the row heights are dynamic, so we'll 16251 // always assign the height of the dragged item given forcePlaceholderSize 16252 // is true. 16253 if (!p.height() || (o.forcePlaceholderSize && 16254 (nodeName === "tbody" || nodeName === "tr"))) { 16255 p.height( 16256 that.currentItem.innerHeight() - 16257 parseInt(that.currentItem.css("paddingTop") || 0, 10) - 16258 parseInt(that.currentItem.css("paddingBottom") || 0, 10)); 16259 } 16260 if (!p.width()) { 16261 p.width( 16262 that.currentItem.innerWidth() - 16263 parseInt(that.currentItem.css("paddingLeft") || 0, 10) - 16264 parseInt(that.currentItem.css("paddingRight") || 0, 10)); 16265 } 16266 } 16267 }; 16268 } 16269 16270 //Create the placeholder 16271 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem)); 16272 16273 //Append it after the actual current item 16274 that.currentItem.after(that.placeholder); 16275 16276 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) 16277 o.placeholder.update(that, that.placeholder); 16278 16279 }, 16280 16281 _createTrPlaceholder: function (sourceTr, targetTr) { 16282 var that = this; 16283 16284 sourceTr.children().each(function () { 16285 $("<td> </td>", that.document[0]) 16286 .attr("colspan", $(this).attr("colspan") || 1) 16287 .appendTo(targetTr); 16288 }); 16289 }, 16290 16291 _contactContainers: function (event) { 16292 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, 16293 floating, axis, 16294 innermostContainer = null, 16295 innermostIndex = null; 16296 16297 // Get innermost container that intersects with item 16298 for (i = this.containers.length - 1; i >= 0; i--) { 16299 16300 // Never consider a container that's located within the item itself 16301 if ($.contains(this.currentItem[0], this.containers[i].element[0])) { 16302 continue; 16303 } 16304 16305 if (this._intersectsWith(this.containers[i].containerCache)) { 16306 16307 // If we've already found a container and it's more "inner" than this, then continue 16308 if (innermostContainer && 16309 $.contains( 16310 this.containers[i].element[0], 16311 innermostContainer.element[0])) { 16312 continue; 16313 } 16314 16315 innermostContainer = this.containers[i]; 16316 innermostIndex = i; 16317 16318 } else { 16319 16320 // container doesn't intersect. trigger "out" event if necessary 16321 if (this.containers[i].containerCache.over) { 16322 this.containers[i]._trigger("out", event, this._uiHash(this)); 16323 this.containers[i].containerCache.over = 0; 16324 } 16325 } 16326 16327 } 16328 16329 // If no intersecting containers found, return 16330 if (!innermostContainer) { 16331 return; 16332 } 16333 16334 // Move the item into the container if it's not there already 16335 if (this.containers.length === 1) { 16336 if (!this.containers[innermostIndex].containerCache.over) { 16337 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 16338 this.containers[innermostIndex].containerCache.over = 1; 16339 } 16340 } else { 16341 16342 // When entering a new container, we will find the item with the least distance and 16343 // append our item near it 16344 dist = 10000; 16345 itemWithLeastDistance = null; 16346 floating = innermostContainer.floating || this._isFloating(this.currentItem); 16347 posProperty = floating ? "left" : "top"; 16348 sizeProperty = floating ? "width" : "height"; 16349 axis = floating ? "pageX" : "pageY"; 16350 16351 for (j = this.items.length - 1; j >= 0; j--) { 16352 if (!$.contains( 16353 this.containers[innermostIndex].element[0], this.items[j].item[0]) 16354 ) { 16355 continue; 16356 } 16357 if (this.items[j].item[0] === this.currentItem[0]) { 16358 continue; 16359 } 16360 16361 cur = this.items[j].item.offset()[posProperty]; 16362 nearBottom = false; 16363 if (event[axis] - cur > this.items[j][sizeProperty] / 2) { 16364 nearBottom = true; 16365 } 16366 16367 if (Math.abs(event[axis] - cur) < dist) { 16368 dist = Math.abs(event[axis] - cur); 16369 itemWithLeastDistance = this.items[j]; 16370 this.direction = nearBottom ? "up" : "down"; 16371 } 16372 } 16373 16374 //Check if dropOnEmpty is enabled 16375 if (!itemWithLeastDistance && !this.options.dropOnEmpty) { 16376 return; 16377 } 16378 16379 if (this.currentContainer === this.containers[innermostIndex]) { 16380 if (!this.currentContainer.containerCache.over) { 16381 this.containers[innermostIndex]._trigger("over", event, this._uiHash()); 16382 this.currentContainer.containerCache.over = 1; 16383 } 16384 return; 16385 } 16386 16387 if (itemWithLeastDistance) { 16388 this._rearrange(event, itemWithLeastDistance, null, true); 16389 } else { 16390 this._rearrange(event, null, this.containers[innermostIndex].element, true); 16391 } 16392 this._trigger("change", event, this._uiHash()); 16393 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 16394 this.currentContainer = this.containers[innermostIndex]; 16395 16396 //Update the placeholder 16397 this.options.placeholder.update(this.currentContainer, this.placeholder); 16398 16399 //Update scrollParent 16400 this.scrollParent = this.placeholder.scrollParent(); 16401 16402 //Update overflowOffset 16403 if (this.scrollParent[0] !== this.document[0] && 16404 this.scrollParent[0].tagName !== "HTML") { 16405 this.overflowOffset = this.scrollParent.offset(); 16406 } 16407 16408 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 16409 this.containers[innermostIndex].containerCache.over = 1; 16410 } 16411 16412 }, 16413 16414 _createHelper: function (event) { 16415 16416 var o = this.options, 16417 helper = typeof o.helper === "function" ? 16418 $(o.helper.apply(this.element[0], [event, this.currentItem])) : 16419 (o.helper === "clone" ? this.currentItem.clone() : this.currentItem); 16420 16421 //Add the helper to the DOM if that didn't happen already 16422 if (!helper.parents("body").length) { 16423 this.appendTo[0].appendChild(helper[0]); 16424 } 16425 16426 if (helper[0] === this.currentItem[0]) { 16427 this._storedCSS = { 16428 width: this.currentItem[0].style.width, 16429 height: this.currentItem[0].style.height, 16430 position: this.currentItem.css("position"), 16431 top: this.currentItem.css("top"), 16432 left: this.currentItem.css("left") 16433 }; 16434 } 16435 16436 if (!helper[0].style.width || o.forceHelperSize) { 16437 helper.width(this.currentItem.width()); 16438 } 16439 if (!helper[0].style.height || o.forceHelperSize) { 16440 helper.height(this.currentItem.height()); 16441 } 16442 16443 return helper; 16444 16445 }, 16446 16447 _adjustOffsetFromHelper: function (obj) { 16448 if (typeof obj === "string") { 16449 obj = obj.split(" "); 16450 } 16451 if (Array.isArray(obj)) { 16452 obj = { left: +obj[0], top: +obj[1] || 0 }; 16453 } 16454 if ("left" in obj) { 16455 this.offset.click.left = obj.left + this.margins.left; 16456 } 16457 if ("right" in obj) { 16458 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 16459 } 16460 if ("top" in obj) { 16461 this.offset.click.top = obj.top + this.margins.top; 16462 } 16463 if ("bottom" in obj) { 16464 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 16465 } 16466 }, 16467 16468 _getParentOffset: function () { 16469 16470 //Get the offsetParent and cache its position 16471 this.offsetParent = this.helper.offsetParent(); 16472 var po = this.offsetParent.offset(); 16473 16474 // This is a special case where we need to modify a offset calculated on start, since the 16475 // following happened: 16476 // 1. The position of the helper is absolute, so it's position is calculated based on the 16477 // next positioned parent 16478 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't 16479 // the document, which means that the scroll is included in the initial calculation of the 16480 // offset of the parent, and never recalculated upon drag 16481 if (this.cssPosition === "absolute" && this.scrollParent[0] !== this.document[0] && 16482 $.contains(this.scrollParent[0], this.offsetParent[0])) { 16483 po.left += this.scrollParent.scrollLeft(); 16484 po.top += this.scrollParent.scrollTop(); 16485 } 16486 16487 // This needs to be actually done for all browsers, since pageX/pageY includes 16488 // this information. 16489 if (this.offsetParent[0] === this.document[0].body) { 16490 po = { top: 0, left: 0 }; 16491 } 16492 16493 return { 16494 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0), 16495 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0) 16496 }; 16497 16498 }, 16499 16500 _getRelativeOffset: function () { 16501 16502 if (this.cssPosition === "relative") { 16503 var p = this.currentItem.position(); 16504 return { 16505 top: p.top - (parseInt(this.helper.css("top"), 10) || 0) + 16506 this.scrollParent.scrollTop(), 16507 left: p.left - (parseInt(this.helper.css("left"), 10) || 0) + 16508 this.scrollParent.scrollLeft() 16509 }; 16510 } else { 16511 return { top: 0, left: 0 }; 16512 } 16513 16514 }, 16515 16516 _cacheMargins: function () { 16517 this.margins = { 16518 left: (parseInt(this.currentItem.css("marginLeft"), 10) || 0), 16519 top: (parseInt(this.currentItem.css("marginTop"), 10) || 0) 16520 }; 16521 }, 16522 16523 _cacheHelperProportions: function () { 16524 this.helperProportions = { 16525 width: this.helper.outerWidth(), 16526 height: this.helper.outerHeight() 16527 }; 16528 }, 16529 16530 _setContainment: function () { 16531 16532 var ce, co, over, 16533 o = this.options; 16534 if (o.containment === "parent") { 16535 o.containment = this.helper[0].parentNode; 16536 } 16537 if (o.containment === "document" || o.containment === "window") { 16538 this.containment = [ 16539 0 - this.offset.relative.left - this.offset.parent.left, 16540 0 - this.offset.relative.top - this.offset.parent.top, 16541 o.containment === "document" ? 16542 this.document.width() : 16543 this.window.width() - this.helperProportions.width - this.margins.left, 16544 (o.containment === "document" ? 16545 (this.document.height() || document.body.parentNode.scrollHeight) : 16546 this.window.height() || this.document[0].body.parentNode.scrollHeight 16547 ) - this.helperProportions.height - this.margins.top 16548 ]; 16549 } 16550 16551 if (!(/^(document|window|parent)$/).test(o.containment)) { 16552 ce = $(o.containment)[0]; 16553 co = $(o.containment).offset(); 16554 over = ($(ce).css("overflow") !== "hidden"); 16555 16556 this.containment = [ 16557 co.left + (parseInt($(ce).css("borderLeftWidth"), 10) || 0) + 16558 (parseInt($(ce).css("paddingLeft"), 10) || 0) - this.margins.left, 16559 co.top + (parseInt($(ce).css("borderTopWidth"), 10) || 0) + 16560 (parseInt($(ce).css("paddingTop"), 10) || 0) - this.margins.top, 16561 co.left + (over ? Math.max(ce.scrollWidth, ce.offsetWidth) : ce.offsetWidth) - 16562 (parseInt($(ce).css("borderLeftWidth"), 10) || 0) - 16563 (parseInt($(ce).css("paddingRight"), 10) || 0) - 16564 this.helperProportions.width - this.margins.left, 16565 co.top + (over ? Math.max(ce.scrollHeight, ce.offsetHeight) : ce.offsetHeight) - 16566 (parseInt($(ce).css("borderTopWidth"), 10) || 0) - 16567 (parseInt($(ce).css("paddingBottom"), 10) || 0) - 16568 this.helperProportions.height - this.margins.top 16569 ]; 16570 } 16571 16572 }, 16573 16574 _convertPositionTo: function (d, pos) { 16575 16576 if (!pos) { 16577 pos = this.position; 16578 } 16579 var mod = d === "absolute" ? 1 : -1, 16580 scroll = this.cssPosition === "absolute" && 16581 !(this.scrollParent[0] !== this.document[0] && 16582 $.contains(this.scrollParent[0], this.offsetParent[0])) ? 16583 this.offsetParent : 16584 this.scrollParent, 16585 scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 16586 16587 return { 16588 top: ( 16589 16590 // The absolute mouse position 16591 pos.top + 16592 16593 // Only for relative positioned nodes: Relative offset from element to offset parent 16594 this.offset.relative.top * mod + 16595 16596 // The offsetParent's offset without borders (offset + border) 16597 this.offset.parent.top * mod - 16598 ((this.cssPosition === "fixed" ? 16599 -this.scrollParent.scrollTop() : 16600 (scrollIsRootNode ? 0 : scroll.scrollTop())) * mod) 16601 ), 16602 left: ( 16603 16604 // The absolute mouse position 16605 pos.left + 16606 16607 // Only for relative positioned nodes: Relative offset from element to offset parent 16608 this.offset.relative.left * mod + 16609 16610 // The offsetParent's offset without borders (offset + border) 16611 this.offset.parent.left * mod - 16612 ((this.cssPosition === "fixed" ? 16613 -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : 16614 scroll.scrollLeft()) * mod) 16615 ) 16616 }; 16617 16618 }, 16619 16620 _generatePosition: function (event) { 16621 16622 var top, left, 16623 o = this.options, 16624 pageX = event.pageX, 16625 pageY = event.pageY, 16626 scroll = this.cssPosition === "absolute" && 16627 !(this.scrollParent[0] !== this.document[0] && 16628 $.contains(this.scrollParent[0], this.offsetParent[0])) ? 16629 this.offsetParent : 16630 this.scrollParent, 16631 scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 16632 16633 // This is another very weird special case that only happens for relative elements: 16634 // 1. If the css position is relative 16635 // 2. and the scroll parent is the document or similar to the offset parent 16636 // we have to refresh the relative offset during the scroll so there are no jumps 16637 if (this.cssPosition === "relative" && !(this.scrollParent[0] !== this.document[0] && 16638 this.scrollParent[0] !== this.offsetParent[0])) { 16639 this.offset.relative = this._getRelativeOffset(); 16640 } 16641 16642 /* 16643 * - Position constraining - 16644 * Constrain the position to a mix of grid, containment. 16645 */ 16646 16647 if (this.originalPosition) { //If we are not dragging yet, we won't check for options 16648 16649 if (this.containment) { 16650 if (event.pageX - this.offset.click.left < this.containment[0]) { 16651 pageX = this.containment[0] + this.offset.click.left; 16652 } 16653 if (event.pageY - this.offset.click.top < this.containment[1]) { 16654 pageY = this.containment[1] + this.offset.click.top; 16655 } 16656 if (event.pageX - this.offset.click.left > this.containment[2]) { 16657 pageX = this.containment[2] + this.offset.click.left; 16658 } 16659 if (event.pageY - this.offset.click.top > this.containment[3]) { 16660 pageY = this.containment[3] + this.offset.click.top; 16661 } 16662 } 16663 16664 if (o.grid) { 16665 top = this.originalPageY + Math.round((pageY - this.originalPageY) / 16666 o.grid[1]) * o.grid[1]; 16667 pageY = this.containment ? 16668 ((top - this.offset.click.top >= this.containment[1] && 16669 top - this.offset.click.top <= this.containment[3]) ? 16670 top : 16671 ((top - this.offset.click.top >= this.containment[1]) ? 16672 top - o.grid[1] : top + o.grid[1])) : 16673 top; 16674 16675 left = this.originalPageX + Math.round((pageX - this.originalPageX) / 16676 o.grid[0]) * o.grid[0]; 16677 pageX = this.containment ? 16678 ((left - this.offset.click.left >= this.containment[0] && 16679 left - this.offset.click.left <= this.containment[2]) ? 16680 left : 16681 ((left - this.offset.click.left >= this.containment[0]) ? 16682 left - o.grid[0] : left + o.grid[0])) : 16683 left; 16684 } 16685 16686 } 16687 16688 return { 16689 top: ( 16690 16691 // The absolute mouse position 16692 pageY - 16693 16694 // Click offset (relative to the element) 16695 this.offset.click.top - 16696 16697 // Only for relative positioned nodes: Relative offset from element to offset parent 16698 this.offset.relative.top - 16699 16700 // The offsetParent's offset without borders (offset + border) 16701 this.offset.parent.top + 16702 ((this.cssPosition === "fixed" ? 16703 -this.scrollParent.scrollTop() : 16704 (scrollIsRootNode ? 0 : scroll.scrollTop()))) 16705 ), 16706 left: ( 16707 16708 // The absolute mouse position 16709 pageX - 16710 16711 // Click offset (relative to the element) 16712 this.offset.click.left - 16713 16714 // Only for relative positioned nodes: Relative offset from element to offset parent 16715 this.offset.relative.left - 16716 16717 // The offsetParent's offset without borders (offset + border) 16718 this.offset.parent.left + 16719 ((this.cssPosition === "fixed" ? 16720 -this.scrollParent.scrollLeft() : 16721 scrollIsRootNode ? 0 : scroll.scrollLeft())) 16722 ) 16723 }; 16724 16725 }, 16726 16727 _rearrange: function (event, i, a, hardRefresh) { 16728 16729 if (a) { 16730 a[0].appendChild(this.placeholder[0]); 16731 } else { 16732 i.item[0].parentNode.insertBefore(this.placeholder[0], 16733 (this.direction === "down" ? i.item[0] : i.item[0].nextSibling)); 16734 } 16735 16736 //Various things done here to improve the performance: 16737 // 1. we create a setTimeout, that calls refreshPositions 16738 // 2. on the instance, we have a counter variable, that get's higher after every append 16739 // 3. on the local scope, we copy the counter variable, and check in the timeout, 16740 // if it's still the same 16741 // 4. this lets only the last addition to the timeout stack through 16742 this.counter = this.counter ? ++this.counter : 1; 16743 var counter = this.counter; 16744 16745 this._delay(function () { 16746 if (counter === this.counter) { 16747 16748 //Precompute after each DOM insertion, NOT on mousemove 16749 this.refreshPositions(!hardRefresh); 16750 } 16751 }); 16752 16753 }, 16754 16755 _clear: function (event, noPropagation) { 16756 16757 this.reverting = false; 16758 16759 // We delay all events that have to be triggered to after the point where the placeholder 16760 // has been removed and everything else normalized again 16761 var i, 16762 delayedTriggers = []; 16763 16764 // We first have to update the dom position of the actual currentItem 16765 // Note: don't do it if the current item is already removed (by a user), or it gets 16766 // reappended (see #4088) 16767 if (!this._noFinalSort && this.currentItem.parent().length) { 16768 this.placeholder.before(this.currentItem); 16769 } 16770 this._noFinalSort = null; 16771 16772 if (this.helper[0] === this.currentItem[0]) { 16773 for (i in this._storedCSS) { 16774 if (this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") { 16775 this._storedCSS[i] = ""; 16776 } 16777 } 16778 this.currentItem.css(this._storedCSS); 16779 this._removeClass(this.currentItem, "ui-sortable-helper"); 16780 } else { 16781 this.currentItem.show(); 16782 } 16783 16784 if (this.fromOutside && !noPropagation) { 16785 delayedTriggers.push(function (event) { 16786 this._trigger("receive", event, this._uiHash(this.fromOutside)); 16787 }); 16788 } 16789 if ((this.fromOutside || 16790 this.domPosition.prev !== 16791 this.currentItem.prev().not(".ui-sortable-helper")[0] || 16792 this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) { 16793 16794 // Trigger update callback if the DOM position has changed 16795 delayedTriggers.push(function (event) { 16796 this._trigger("update", event, this._uiHash()); 16797 }); 16798 } 16799 16800 // Check if the items Container has Changed and trigger appropriate 16801 // events. 16802 if (this !== this.currentContainer) { 16803 if (!noPropagation) { 16804 delayedTriggers.push(function (event) { 16805 this._trigger("remove", event, this._uiHash()); 16806 }); 16807 delayedTriggers.push((function (c) { 16808 return function (event) { 16809 c._trigger("receive", event, this._uiHash(this)); 16810 }; 16811 }).call(this, this.currentContainer)); 16812 delayedTriggers.push((function (c) { 16813 return function (event) { 16814 c._trigger("update", event, this._uiHash(this)); 16815 }; 16816 }).call(this, this.currentContainer)); 16817 } 16818 } 16819 16820 //Post events to containers 16821 function delayEvent(type, instance, container) { 16822 return function (event) { 16823 container._trigger(type, event, instance._uiHash(instance)); 16824 }; 16825 } 16826 for (i = this.containers.length - 1; i >= 0; i--) { 16827 if (!noPropagation) { 16828 delayedTriggers.push(delayEvent("deactivate", this, this.containers[i])); 16829 } 16830 if (this.containers[i].containerCache.over) { 16831 delayedTriggers.push(delayEvent("out", this, this.containers[i])); 16832 this.containers[i].containerCache.over = 0; 16833 } 16834 } 16835 16836 //Do what was originally in plugins 16837 if (this._storedStylesheet) { 16838 this._storedStylesheet.remove(); 16839 this._storedStylesheet = null; 16840 } 16841 if (this._storedOpacity) { 16842 this.helper.css("opacity", this._storedOpacity); 16843 } 16844 if (this._storedZIndex) { 16845 this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex); 16846 } 16847 16848 this.dragging = false; 16849 16850 if (!noPropagation) { 16851 this._trigger("beforeStop", event, this._uiHash()); 16852 } 16853 16854 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, 16855 // it unbinds ALL events from the original node! 16856 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 16857 16858 if (!this.cancelHelperRemoval) { 16859 if (this.helper[0] !== this.currentItem[0]) { 16860 this.helper.remove(); 16861 } 16862 this.helper = null; 16863 } 16864 16865 if (!noPropagation) { 16866 for (i = 0; i < delayedTriggers.length; i++) { 16867 16868 // Trigger all delayed events 16869 delayedTriggers[i].call(this, event); 16870 } 16871 this._trigger("stop", event, this._uiHash()); 16872 } 16873 16874 this.fromOutside = false; 16875 return !this.cancelHelperRemoval; 16876 16877 }, 16878 16879 _trigger: function () { 16880 if ($.Widget.prototype._trigger.apply(this, arguments) === false) { 16881 this.cancel(); 16882 } 16883 }, 16884 16885 _uiHash: function (_inst) { 16886 var inst = _inst || this; 16887 return { 16888 helper: inst.helper, 16889 placeholder: inst.placeholder || $([]), 16890 position: inst.position, 16891 originalPosition: inst.originalPosition, 16892 offset: inst.positionAbs, 16893 item: inst.currentItem, 16894 sender: _inst ? _inst.element : null 16895 }; 16896 } 16897 16898 }); 16899 16900 16901 /*! 16902 * jQuery UI Spinner 1.14.1 16903 * https://jqueryui.com 16904 * 16905 * Copyright OpenJS Foundation and other contributors 16906 * Released under the MIT license. 16907 * https://jquery.org/license 16908 */ 16909 16910 //>>label: Spinner 16911 //>>group: Widgets 16912 //>>description: Displays buttons to easily input numbers via the keyboard or mouse. 16913 //>>docs: https://api.jqueryui.com/spinner/ 16914 //>>demos: https://jqueryui.com/spinner/ 16915 //>>css.structure: ../../themes/base/core.css 16916 //>>css.structure: ../../themes/base/spinner.css 16917 //>>css.theme: ../../themes/base/theme.css 16918 16919 16920 function spinnerModifier(fn) { 16921 return function () { 16922 var previous = this.element.val(); 16923 fn.apply(this, arguments); 16924 this._refresh(); 16925 if (previous !== this.element.val()) { 16926 this._trigger("change"); 16927 } 16928 }; 16929 } 16930 16931 $.widget("ui.spinner", { 16932 version: "1.14.1", 16933 defaultElement: "<input>", 16934 widgetEventPrefix: "spin", 16935 options: { 16936 classes: { 16937 "ui-spinner": "ui-corner-all", 16938 "ui-spinner-down": "ui-corner-br", 16939 "ui-spinner-up": "ui-corner-tr" 16940 }, 16941 culture: null, 16942 icons: { 16943 down: "ui-icon-triangle-1-s", 16944 up: "ui-icon-triangle-1-n" 16945 }, 16946 incremental: true, 16947 max: null, 16948 min: null, 16949 numberFormat: null, 16950 page: 10, 16951 step: 1, 16952 16953 change: null, 16954 spin: null, 16955 start: null, 16956 stop: null 16957 }, 16958 16959 _create: function () { 16960 16961 // handle string values that need to be parsed 16962 this._setOption("max", this.options.max); 16963 this._setOption("min", this.options.min); 16964 this._setOption("step", this.options.step); 16965 16966 // Only format if there is a value, prevents the field from being marked 16967 // as invalid in Firefox, see #9573. 16968 if (this.value() !== "") { 16969 16970 // Format the value, but don't constrain. 16971 this._value(this.element.val(), true); 16972 } 16973 16974 this._draw(); 16975 this._on(this._events); 16976 this._refresh(); 16977 16978 // Turning off autocomplete prevents the browser from remembering the 16979 // value when navigating through history, so we re-enable autocomplete 16980 // if the page is unloaded before the widget is destroyed. #7790 16981 this._on(this.window, { 16982 beforeunload: function () { 16983 this.element.removeAttr("autocomplete"); 16984 } 16985 }); 16986 }, 16987 16988 _getCreateOptions: function () { 16989 var options = this._super(); 16990 var element = this.element; 16991 16992 $.each(["min", "max", "step"], function (i, option) { 16993 var value = element.attr(option); 16994 if (value != null && value.length) { 16995 options[option] = value; 16996 } 16997 }); 16998 16999 return options; 17000 }, 17001 17002 _events: { 17003 keydown: function (event) { 17004 if (this._start(event) && this._keydown(event)) { 17005 event.preventDefault(); 17006 } 17007 }, 17008 keyup: "_stop", 17009 focus: function () { 17010 this.previous = this.element.val(); 17011 }, 17012 blur: function (event) { 17013 this._stop(); 17014 this._refresh(); 17015 if (this.previous !== this.element.val()) { 17016 this._trigger("change", event); 17017 } 17018 }, 17019 mousewheel: function (event, delta) { 17020 var activeElement = this.document[0].activeElement; 17021 var isActive = this.element[0] === activeElement; 17022 17023 if (!isActive || !delta) { 17024 return; 17025 } 17026 17027 if (!this.spinning && !this._start(event)) { 17028 return false; 17029 } 17030 17031 this._spin((delta > 0 ? 1 : -1) * this.options.step, event); 17032 clearTimeout(this.mousewheelTimer); 17033 this.mousewheelTimer = this._delay(function () { 17034 if (this.spinning) { 17035 this._stop(event); 17036 } 17037 }, 100); 17038 event.preventDefault(); 17039 }, 17040 "mousedown .ui-spinner-button": function (event) { 17041 var previous; 17042 17043 // We never want the buttons to have focus; whenever the user is 17044 // interacting with the spinner, the focus should be on the input. 17045 // If the input is focused then this.previous is properly set from 17046 // when the input first received focus. If the input is not focused 17047 // then we need to set this.previous based on the value before spinning. 17048 previous = this.element[0] === this.document[0].activeElement ? 17049 this.previous : this.element.val(); 17050 function checkFocus() { 17051 var isActive = this.element[0] === this.document[0].activeElement; 17052 if (!isActive) { 17053 this.element.trigger("focus"); 17054 this.previous = previous; 17055 } 17056 } 17057 17058 // Ensure focus is on (or stays on) the text field 17059 event.preventDefault(); 17060 checkFocus.call(this); 17061 17062 if (this._start(event) === false) { 17063 return; 17064 } 17065 17066 this._repeat(null, $(event.currentTarget) 17067 .hasClass("ui-spinner-up") ? 1 : -1, event); 17068 }, 17069 "mouseup .ui-spinner-button": "_stop", 17070 "mouseenter .ui-spinner-button": function (event) { 17071 17072 // button will add ui-state-active if mouse was down while mouseleave and kept down 17073 if (!$(event.currentTarget).hasClass("ui-state-active")) { 17074 return; 17075 } 17076 17077 if (this._start(event) === false) { 17078 return false; 17079 } 17080 this._repeat(null, $(event.currentTarget) 17081 .hasClass("ui-spinner-up") ? 1 : -1, event); 17082 }, 17083 17084 // TODO: do we really want to consider this a stop? 17085 // shouldn't we just stop the repeater and wait until mouseup before 17086 // we trigger the stop event? 17087 "mouseleave .ui-spinner-button": "_stop" 17088 }, 17089 17090 // Support mobile enhanced option and make backcompat more sane 17091 _enhance: function () { 17092 this.uiSpinner = this.element 17093 .attr("autocomplete", "off") 17094 .wrap("<span>") 17095 .parent() 17096 17097 // Add buttons 17098 .append( 17099 "<a></a><a></a>" 17100 ); 17101 }, 17102 17103 _draw: function () { 17104 this._enhance(); 17105 17106 this._addClass(this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content"); 17107 this._addClass("ui-spinner-input"); 17108 17109 this.element.attr("role", "spinbutton"); 17110 17111 // Button bindings 17112 this.buttons = this.uiSpinner.children("a") 17113 .attr("tabIndex", -1) 17114 .attr("aria-hidden", true) 17115 .button({ 17116 classes: { 17117 "ui-button": "" 17118 } 17119 }); 17120 17121 // TODO: Right now button does not support classes this is already updated in button PR 17122 this._removeClass(this.buttons, "ui-corner-all"); 17123 17124 this._addClass(this.buttons.first(), "ui-spinner-button ui-spinner-up"); 17125 this._addClass(this.buttons.last(), "ui-spinner-button ui-spinner-down"); 17126 this.buttons.first().button({ 17127 "icon": this.options.icons.up, 17128 "showLabel": false 17129 }); 17130 this.buttons.last().button({ 17131 "icon": this.options.icons.down, 17132 "showLabel": false 17133 }); 17134 17135 // IE 6 doesn't understand height: 50% for the buttons 17136 // unless the wrapper has an explicit height 17137 if (this.buttons.height() > Math.ceil(this.uiSpinner.height() * 0.5) && 17138 this.uiSpinner.height() > 0) { 17139 this.uiSpinner.height(this.uiSpinner.height()); 17140 } 17141 }, 17142 17143 _keydown: function (event) { 17144 var options = this.options, 17145 keyCode = $.ui.keyCode; 17146 17147 switch (event.keyCode) { 17148 case keyCode.UP: 17149 this._repeat(null, 1, event); 17150 return true; 17151 case keyCode.DOWN: 17152 this._repeat(null, -1, event); 17153 return true; 17154 case keyCode.PAGE_UP: 17155 this._repeat(null, options.page, event); 17156 return true; 17157 case keyCode.PAGE_DOWN: 17158 this._repeat(null, -options.page, event); 17159 return true; 17160 } 17161 17162 return false; 17163 }, 17164 17165 _start: function (event) { 17166 if (!this.spinning && this._trigger("start", event) === false) { 17167 return false; 17168 } 17169 17170 if (!this.counter) { 17171 this.counter = 1; 17172 } 17173 this.spinning = true; 17174 return true; 17175 }, 17176 17177 _repeat: function (i, steps, event) { 17178 i = i || 500; 17179 17180 clearTimeout(this.timer); 17181 this.timer = this._delay(function () { 17182 this._repeat(40, steps, event); 17183 }, i); 17184 17185 this._spin(steps * this.options.step, event); 17186 }, 17187 17188 _spin: function (step, event) { 17189 var value = this.value() || 0; 17190 17191 if (!this.counter) { 17192 this.counter = 1; 17193 } 17194 17195 value = this._adjustValue(value + step * this._increment(this.counter)); 17196 17197 if (!this.spinning || this._trigger("spin", event, { value: value }) !== false) { 17198 this._value(value); 17199 this.counter++; 17200 } 17201 }, 17202 17203 _increment: function (i) { 17204 var incremental = this.options.incremental; 17205 17206 if (incremental) { 17207 return typeof incremental === "function" ? 17208 incremental(i) : 17209 Math.floor(i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1); 17210 } 17211 17212 return 1; 17213 }, 17214 17215 _precision: function () { 17216 var precision = this._precisionOf(this.options.step); 17217 if (this.options.min !== null) { 17218 precision = Math.max(precision, this._precisionOf(this.options.min)); 17219 } 17220 return precision; 17221 }, 17222 17223 _precisionOf: function (num) { 17224 var str = num.toString(), 17225 decimal = str.indexOf("."); 17226 return decimal === -1 ? 0 : str.length - decimal - 1; 17227 }, 17228 17229 _adjustValue: function (value) { 17230 var base, aboveMin, 17231 options = this.options; 17232 17233 // Make sure we're at a valid step 17234 // - find out where we are relative to the base (min or 0) 17235 base = options.min !== null ? options.min : 0; 17236 aboveMin = value - base; 17237 17238 // - round to the nearest step 17239 aboveMin = Math.round(aboveMin / options.step) * options.step; 17240 17241 // - rounding is based on 0, so adjust back to our base 17242 value = base + aboveMin; 17243 17244 // Fix precision from bad JS floating point math 17245 value = parseFloat(value.toFixed(this._precision())); 17246 17247 // Clamp the value 17248 if (options.max !== null && value > options.max) { 17249 return options.max; 17250 } 17251 if (options.min !== null && value < options.min) { 17252 return options.min; 17253 } 17254 17255 return value; 17256 }, 17257 17258 _stop: function (event) { 17259 if (!this.spinning) { 17260 return; 17261 } 17262 17263 clearTimeout(this.timer); 17264 clearTimeout(this.mousewheelTimer); 17265 this.counter = 0; 17266 this.spinning = false; 17267 this._trigger("stop", event); 17268 }, 17269 17270 _setOption: function (key, value) { 17271 var prevValue, first, last; 17272 17273 if (key === "culture" || key === "numberFormat") { 17274 prevValue = this._parse(this.element.val()); 17275 this.options[key] = value; 17276 this.element.val(this._format(prevValue)); 17277 return; 17278 } 17279
vendor: 12,464 bytes, lines 17280-17752
17280 if (key === "max" || key === "min" || key === "step") { 17281 if (typeof value === "string") { 17282 value = this._parse(value); 17283 } 17284 } 17285 if (key === "icons") { 17286 first = this.buttons.first().find(".ui-icon"); 17287 this._removeClass(first, null, this.options.icons.up); 17288 this._addClass(first, null, value.up); 17289 last = this.buttons.last().find(".ui-icon"); 17290 this._removeClass(last, null, this.options.icons.down); 17291 this._addClass(last, null, value.down); 17292 } 17293 17294 this._super(key, value); 17295 }, 17296 17297 _setOptionDisabled: function (value) { 17298 this._super(value); 17299 17300 this._toggleClass(this.uiSpinner, null, "ui-state-disabled", !!value); 17301 this.element.prop("disabled", !!value); 17302 this.buttons.button(value ? "disable" : "enable"); 17303 }, 17304 17305 _setOptions: spinnerModifier(function (options) { 17306 this._super(options); 17307 }), 17308 17309 _parse: function (val) { 17310 if (typeof val === "string" && val !== "") { 17311 val = window.Globalize && this.options.numberFormat ? 17312 Globalize.parseFloat(val, 10, this.options.culture) : +val; 17313 } 17314 return val === "" || isNaN(val) ? null : val; 17315 }, 17316 17317 _format: function (value) { 17318 if (value === "") { 17319 return ""; 17320 } 17321 return window.Globalize && this.options.numberFormat ? 17322 Globalize.format(value, this.options.numberFormat, this.options.culture) : 17323 value; 17324 }, 17325 17326 _refresh: function () { 17327 this.element.attr({ 17328 "aria-valuemin": this.options.min, 17329 "aria-valuemax": this.options.max, 17330 17331 // TODO: what should we do with values that can't be parsed? 17332 "aria-valuenow": this._parse(this.element.val()) 17333 }); 17334 }, 17335 17336 isValid: function () { 17337 var value = this.value(); 17338 17339 // Null is invalid 17340 if (value === null) { 17341 return false; 17342 } 17343 17344 // If value gets adjusted, it's invalid 17345 return value === this._adjustValue(value); 17346 }, 17347 17348 // Update the value without triggering change 17349 _value: function (value, allowAny) { 17350 var parsed; 17351 if (value !== "") { 17352 parsed = this._parse(value); 17353 if (parsed !== null) { 17354 if (!allowAny) { 17355 parsed = this._adjustValue(parsed); 17356 } 17357 value = this._format(parsed); 17358 } 17359 } 17360 this.element.val(value); 17361 this._refresh(); 17362 }, 17363 17364 _destroy: function () { 17365 this.element 17366 .prop("disabled", false) 17367 .removeAttr("autocomplete role aria-valuemin aria-valuemax aria-valuenow"); 17368 17369 this.uiSpinner.replaceWith(this.element); 17370 }, 17371 17372 stepUp: spinnerModifier(function (steps) { 17373 this._stepUp(steps); 17374 }), 17375 _stepUp: function (steps) { 17376 if (this._start()) { 17377 this._spin((steps || 1) * this.options.step); 17378 this._stop(); 17379 } 17380 }, 17381 17382 stepDown: spinnerModifier(function (steps) { 17383 this._stepDown(steps); 17384 }), 17385 _stepDown: function (steps) { 17386 if (this._start()) { 17387 this._spin((steps || 1) * -this.options.step); 17388 this._stop(); 17389 } 17390 }, 17391 17392 pageUp: spinnerModifier(function (pages) { 17393 this._stepUp((pages || 1) * this.options.page); 17394 }), 17395 17396 pageDown: spinnerModifier(function (pages) { 17397 this._stepDown((pages || 1) * this.options.page); 17398 }), 17399 17400 value: function (newVal) { 17401 if (!arguments.length) { 17402 return this._parse(this.element.val()); 17403 } 17404 spinnerModifier(this._value).call(this, newVal); 17405 }, 17406 17407 widget: function () { 17408 return this.uiSpinner; 17409 } 17410 }); 17411 17412 // DEPRECATED 17413 // TODO: switch return back to widget declaration at top of file when this is removed 17414 if ($.uiBackCompat === true) { 17415 17416 // Backcompat for spinner html extension points 17417 $.widget("ui.spinner", $.ui.spinner, { 17418 _enhance: function () { 17419 this.uiSpinner = this.element 17420 .attr("autocomplete", "off") 17421 .wrap(this._uiSpinnerHtml()) 17422 .parent() 17423 17424 // Add buttons 17425 .append(this._buttonHtml()); 17426 }, 17427 _uiSpinnerHtml: function () { 17428 return "<span>"; 17429 }, 17430 17431 _buttonHtml: function () { 17432 return "<a></a><a></a>"; 17433 } 17434 }); 17435 } 17436 17437 var widgetsSpinner = $.ui.spinner; 17438 17439 17440 /*! 17441 * jQuery UI Tabs 1.14.1 17442 * https://jqueryui.com 17443 * 17444 * Copyright OpenJS Foundation and other contributors 17445 * Released under the MIT license. 17446 * https://jquery.org/license 17447 */ 17448 17449 //>>label: Tabs 17450 //>>group: Widgets 17451 //>>description: Transforms a set of container elements into a tab structure. 17452 //>>docs: https://api.jqueryui.com/tabs/ 17453 //>>demos: https://jqueryui.com/tabs/ 17454 //>>css.structure: ../../themes/base/core.css 17455 //>>css.structure: ../../themes/base/tabs.css 17456 //>>css.theme: ../../themes/base/theme.css 17457 17458 17459 $.widget("ui.tabs", { 17460 version: "1.14.1", 17461 delay: 300, 17462 options: { 17463 active: null, 17464 classes: { 17465 "ui-tabs": "ui-corner-all", 17466 "ui-tabs-nav": "ui-corner-all", 17467 "ui-tabs-panel": "ui-corner-bottom", 17468 "ui-tabs-tab": "ui-corner-top" 17469 }, 17470 collapsible: false, 17471 event: "click", 17472 heightStyle: "content", 17473 hide: null, 17474 show: null, 17475 17476 // Callbacks 17477 activate: null, 17478 beforeActivate: null, 17479 beforeLoad: null, 17480 load: null 17481 }, 17482 17483 _isLocal: (function () { 17484 var rhash = /#.*$/; 17485 17486 return function (anchor) { 17487 var anchorUrl, locationUrl; 17488 17489 anchorUrl = anchor.href.replace(rhash, ""); 17490 locationUrl = location.href.replace(rhash, ""); 17491 17492 // Decoding may throw an error if the URL isn't UTF-8 (#9518) 17493 try { 17494 anchorUrl = decodeURIComponent(anchorUrl); 17495 } catch (error) { } 17496 try { 17497 locationUrl = decodeURIComponent(locationUrl); 17498 } catch (error) { } 17499 17500 return anchor.hash.length > 1 && anchorUrl === locationUrl; 17501 }; 17502 })(), 17503 17504 _create: function () { 17505 var that = this, 17506 options = this.options; 17507 17508 this.running = false; 17509 17510 this._addClass("ui-tabs", "ui-widget ui-widget-content"); 17511 this._toggleClass("ui-tabs-collapsible", null, options.collapsible); 17512 17513 this._processTabs(); 17514 options.active = this._initialActive(); 17515 17516 // Take disabling tabs via class attribute from HTML 17517 // into account and update option properly. 17518 if (Array.isArray(options.disabled)) { 17519 options.disabled = $.uniqueSort(options.disabled.concat( 17520 $.map(this.tabs.filter(".ui-state-disabled"), function (li) { 17521 return that.tabs.index(li); 17522 }) 17523 )).sort(); 17524 } 17525 17526 // Check for length avoids error when initializing empty list 17527 if (this.options.active !== false && this.anchors.length) { 17528 this.active = this._findActive(options.active); 17529 } else { 17530 this.active = $(); 17531 } 17532 17533 this._refresh(); 17534 17535 if (this.active.length) { 17536 this.load(options.active); 17537 } 17538 }, 17539 17540 _initialActive: function () { 17541 var active = this.options.active, 17542 collapsible = this.options.collapsible, 17543 locationHashDecoded = decodeURIComponent(location.hash.substring(1)); 17544 17545 if (active === null) { 17546 17547 // check the fragment identifier in the URL 17548 if (locationHashDecoded) { 17549 this.tabs.each(function (i, tab) { 17550 if ($(tab).attr("aria-controls") === locationHashDecoded) { 17551 active = i; 17552 return false; 17553 } 17554 }); 17555 } 17556 17557 // Check for a tab marked active via a class 17558 if (active === null) { 17559 active = this.tabs.index(this.tabs.filter(".ui-tabs-active")); 17560 } 17561 17562 // No active tab, set to false 17563 if (active === null || active === -1) { 17564 active = this.tabs.length ? 0 : false; 17565 } 17566 } 17567 17568 // Handle numbers: negative, out of range 17569 if (active !== false) { 17570 active = this.tabs.index(this.tabs.eq(active)); 17571 if (active === -1) { 17572 active = collapsible ? false : 0; 17573 } 17574 } 17575 17576 // Don't allow collapsible: false and active: false 17577 if (!collapsible && active === false && this.anchors.length) { 17578 active = 0; 17579 } 17580 17581 return active; 17582 }, 17583 17584 _getCreateEventData: function () { 17585 return { 17586 tab: this.active, 17587 panel: !this.active.length ? $() : this._getPanelForTab(this.active) 17588 }; 17589 }, 17590 17591 _tabKeydown: function (event) { 17592 var focusedTab = $(this.document[0].activeElement).closest("li"), 17593 selectedIndex = this.tabs.index(focusedTab), 17594 goingForward = true; 17595 17596 if (this._handlePageNav(event)) { 17597 return; 17598 } 17599 17600 switch (event.keyCode) { 17601 case $.ui.keyCode.RIGHT: 17602 case $.ui.keyCode.DOWN: 17603 selectedIndex++; 17604 break; 17605 case $.ui.keyCode.UP: 17606 case $.ui.keyCode.LEFT: 17607 goingForward = false; 17608 selectedIndex--; 17609 break; 17610 case $.ui.keyCode.END: 17611 selectedIndex = this.anchors.length - 1; 17612 break; 17613 case $.ui.keyCode.HOME: 17614 selectedIndex = 0; 17615 break; 17616 case $.ui.keyCode.SPACE: 17617 17618 // Activate only, no collapsing 17619 event.preventDefault(); 17620 clearTimeout(this.activating); 17621 this._activate(selectedIndex); 17622 return; 17623 case $.ui.keyCode.ENTER: 17624 17625 // Toggle (cancel delayed activation, allow collapsing) 17626 event.preventDefault(); 17627 clearTimeout(this.activating); 17628 17629 // Determine if we should collapse or activate 17630 this._activate(selectedIndex === this.options.active ? false : selectedIndex); 17631 return; 17632 default: 17633 return; 17634 } 17635 17636 // Focus the appropriate tab, based on which key was pressed 17637 event.preventDefault(); 17638 clearTimeout(this.activating); 17639 selectedIndex = this._focusNextTab(selectedIndex, goingForward); 17640 17641 // Navigating with control/command key will prevent automatic activation 17642 if (!event.ctrlKey && !event.metaKey) { 17643 17644 // Update aria-selected immediately so that AT think the tab is already selected. 17645 // Otherwise AT may confuse the user by stating that they need to activate the tab, 17646 // but the tab will already be activated by the time the announcement finishes. 17647 focusedTab.attr("aria-selected", "false"); 17648 this.tabs.eq(selectedIndex).attr("aria-selected", "true"); 17649 17650 this.activating = this._delay(function () { 17651 this.option("active", selectedIndex); 17652 }, this.delay); 17653 } 17654 }, 17655 17656 _panelKeydown: function (event) { 17657 if (this._handlePageNav(event)) { 17658 return; 17659 } 17660 17661 // Ctrl+up moves focus to the current tab 17662 if (event.ctrlKey && event.keyCode === $.ui.keyCode.UP) { 17663 event.preventDefault(); 17664 this.active.trigger("focus"); 17665 } 17666 }, 17667 17668 // Alt+page up/down moves focus to the previous/next tab (and activates) 17669 _handlePageNav: function (event) { 17670 if (event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP) { 17671 this._activate(this._focusNextTab(this.options.active - 1, false)); 17672 return true; 17673 } 17674 if (event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN) { 17675 this._activate(this._focusNextTab(this.options.active + 1, true)); 17676 return true; 17677 } 17678 }, 17679 17680 _findNextTab: function (index, goingForward) { 17681 var lastTabIndex = this.tabs.length - 1; 17682 17683 function constrain() { 17684 if (index > lastTabIndex) { 17685 index = 0; 17686 } 17687 if (index < 0) { 17688 index = lastTabIndex; 17689 } 17690 return index; 17691 } 17692 17693 while ($.inArray(constrain(), this.options.disabled) !== -1) { 17694 index = goingForward ? index + 1 : index - 1; 17695 } 17696 17697 return index; 17698 }, 17699 17700 _focusNextTab: function (index, goingForward) { 17701 index = this._findNextTab(index, goingForward); 17702 this.tabs.eq(index).trigger("focus"); 17703 return index; 17704 }, 17705 17706 _setOption: function (key, value) { 17707 if (key === "active") { 17708 17709 // _activate() will handle invalid values and update this.options 17710 this._activate(value); 17711 return; 17712 } 17713 17714 this._super(key, value); 17715 17716 if (key === "collapsible") { 17717 this._toggleClass("ui-tabs-collapsible", null, value); 17718 17719 // Setting collapsible: false while collapsed; open first panel 17720 if (!value && this.options.active === false) { 17721 this._activate(0); 17722 } 17723 } 17724 17725 if (key === "event") { 17726 this._setupEvents(value); 17727 } 17728 17729 if (key === "heightStyle") { 17730 this._setupHeightStyle(value); 17731 } 17732 }, 17733 17734 refresh: function () { 17735 var options = this.options, 17736 lis = this.tablist.children(":has(a[href])"); 17737 17738 // Get disabled tabs from class attribute from HTML 17739 // this will get converted to a boolean if needed in _refresh() 17740 options.disabled = $.map(lis.filter(".ui-state-disabled"), function (tab) { 17741 return lis.index(tab); 17742 }); 17743 17744 this._processTabs(); 17745 17746 // Was collapsed or no tabs 17747 if (options.active === false || !this.anchors.length) { 17748 options.active = false; 17749 this.active = $(); 17750 17751 // was active, but active tab is gone 17752 } else if (this.active.length && !$.contains(this.tablist[0], this.active[0])
vendor: 29,050 bytes, lines 17752-18815
17752) { 17753 17754 // all remaining tabs are disabled 17755 if (this.tabs.length === options.disabled.length) { 17756 options.active = false; 17757 this.active = $(); 17758 17759 // activate previous tab 17760 } else { 17761 this._activate(this._findNextTab(Math.max(0, options.active - 1), false)); 17762 } 17763 17764 // was active, active tab still exists 17765 } else { 17766 17767 // make sure active index is correct 17768 options.active = this.tabs.index(this.active); 17769 } 17770 17771 this._refresh(); 17772 }, 17773 17774 _refresh: function () { 17775 this._setOptionDisabled(this.options.disabled); 17776 this._setupEvents(this.options.event); 17777 this._setupHeightStyle(this.options.heightStyle); 17778 17779 this.tabs.not(this.active).attr({ 17780 "aria-selected": "false", 17781 "aria-expanded": "false", 17782 tabIndex: -1 17783 }); 17784 this.panels.not(this._getPanelForTab(this.active)) 17785 .hide() 17786 .attr({ 17787 "aria-hidden": "true" 17788 }); 17789 17790 // Make sure one tab is in the tab order 17791 if (!this.active.length) { 17792 this.tabs.eq(0).attr("tabIndex", 0); 17793 } else { 17794 this.active 17795 .attr({ 17796 "aria-selected": "true", 17797 "aria-expanded": "true", 17798 tabIndex: 0 17799 }); 17800 this._addClass(this.active, "ui-tabs-active", "ui-state-active"); 17801 this._getPanelForTab(this.active) 17802 .show() 17803 .attr({ 17804 "aria-hidden": "false" 17805 }); 17806 } 17807 }, 17808 17809 _processTabs: function () { 17810 var that = this, 17811 prevTabs = this.tabs, 17812 prevAnchors = this.anchors, 17813 prevPanels = this.panels; 17814 17815 this.tablist = this._getList().attr("role", "tablist"); 17816 this._addClass(this.tablist, "ui-tabs-nav", 17817 "ui-helper-reset ui-helper-clearfix ui-widget-header"); 17818 17819 // Prevent users from focusing disabled tabs via click 17820 this.tablist 17821 .on("mousedown" + this.eventNamespace, "> li", function (event) { 17822 if ($(this).is(".ui-state-disabled")) { 17823 event.preventDefault(); 17824 } 17825 }); 17826 17827 this.tabs = this.tablist.find("> li:has(a[href])") 17828 .attr({ 17829 role: "tab", 17830 tabIndex: -1 17831 }); 17832 this._addClass(this.tabs, "ui-tabs-tab", "ui-state-default"); 17833 17834 this.anchors = this.tabs.map(function () { 17835 return $("a", this)[0]; 17836 }) 17837 .attr({ 17838 tabIndex: -1 17839 }); 17840 this._addClass(this.anchors, "ui-tabs-anchor"); 17841 17842 this.panels = $(); 17843 17844 this.anchors.each(function (i, anchor) { 17845 var selector, panel, panelId, 17846 anchorId = $(anchor).uniqueId().attr("id"), 17847 tab = $(anchor).closest("li"), 17848 originalAriaControls = tab.attr("aria-controls"); 17849 17850 // Inline tab 17851 if (that._isLocal(anchor)) { 17852 selector = decodeURIComponent(anchor.hash); 17853 panelId = selector.substring(1); 17854 panel = that.element.find("#" + CSS.escape(panelId)); 17855 17856 // remote tab 17857 } else { 17858 17859 // If the tab doesn't already have aria-controls, 17860 // generate an id by using a throw-away element 17861 panelId = tab.attr("aria-controls") || $({}).uniqueId()[0].id; 17862 selector = "#" + panelId; 17863 panel = that.element.find(selector); 17864 if (!panel.length) { 17865 panel = that._createPanel(panelId); 17866 panel.insertAfter(that.panels[i - 1] || that.tablist); 17867 } 17868 panel.attr("aria-live", "polite"); 17869 } 17870 17871 if (panel.length) { 17872 that.panels = that.panels.add(panel); 17873 } 17874 if (originalAriaControls) { 17875 tab.data("ui-tabs-aria-controls", originalAriaControls); 17876 } 17877 tab.attr({ 17878 "aria-controls": panelId, 17879 "aria-labelledby": anchorId 17880 }); 17881 panel.attr("aria-labelledby", anchorId); 17882 }); 17883 17884 this.panels.attr("role", "tabpanel"); 17885 this._addClass(this.panels, "ui-tabs-panel", "ui-widget-content"); 17886 17887 // Avoid memory leaks (#10056) 17888 if (prevTabs) { 17889 this._off(prevTabs.not(this.tabs)); 17890 this._off(prevAnchors.not(this.anchors)); 17891 this._off(prevPanels.not(this.panels)); 17892 } 17893 }, 17894 17895 // Allow overriding how to find the list for rare usage scenarios (#7715) 17896 _getList: function () { 17897 return this.tablist || this.element.find("ol, ul").eq(0); 17898 }, 17899 17900 _createPanel: function (id) { 17901 return $("<div>") 17902 .attr("id", id) 17903 .data("ui-tabs-destroy", true); 17904 }, 17905 17906 _setOptionDisabled: function (disabled) { 17907 var currentItem, li, i; 17908 17909 if (Array.isArray(disabled)) { 17910 if (!disabled.length) { 17911 disabled = false; 17912 } else if (disabled.length === this.anchors.length) { 17913 disabled = true; 17914 } 17915 } 17916 17917 // Disable tabs 17918 for (i = 0; (li = this.tabs[i]); i++) { 17919 currentItem = $(li); 17920 if (disabled === true || $.inArray(i, disabled) !== -1) { 17921 currentItem.attr("aria-disabled", "true"); 17922 this._addClass(currentItem, null, "ui-state-disabled"); 17923 } else { 17924 currentItem.removeAttr("aria-disabled"); 17925 this._removeClass(currentItem, null, "ui-state-disabled"); 17926 } 17927 } 17928 17929 this.options.disabled = disabled; 17930 17931 this._toggleClass(this.widget(), this.widgetFullName + "-disabled", null, 17932 disabled === true); 17933 }, 17934 17935 _setupEvents: function (event) { 17936 var events = {}; 17937 if (event) { 17938 $.each(event.split(" "), function (index, eventName) { 17939 events[eventName] = "_eventHandler"; 17940 }); 17941 } 17942 17943 this._off(this.anchors.add(this.tabs).add(this.panels)); 17944 17945 // Always prevent the default action, even when disabled 17946 this._on(true, this.anchors, { 17947 click: function (event) { 17948 event.preventDefault(); 17949 } 17950 }); 17951 this._on(this.anchors, events); 17952 this._on(this.tabs, { keydown: "_tabKeydown" }); 17953 this._on(this.panels, { keydown: "_panelKeydown" }); 17954 17955 this._focusable(this.tabs); 17956 this._hoverable(this.tabs); 17957 }, 17958 17959 _setupHeightStyle: function (heightStyle) { 17960 var maxHeight, 17961 parent = this.element.parent(); 17962 17963 if (heightStyle === "fill") { 17964 maxHeight = parent.height(); 17965 maxHeight -= this.element.outerHeight() - this.element.height(); 17966 17967 this.element.siblings(":visible").each(function () { 17968 var elem = $(this), 17969 position = elem.css("position"); 17970 17971 if (position === "absolute" || position === "fixed") { 17972 return; 17973 } 17974 maxHeight -= elem.outerHeight(true); 17975 }); 17976 17977 this.element.children().not(this.panels).each(function () { 17978 maxHeight -= $(this).outerHeight(true); 17979 }); 17980 17981 this.panels.each(function () { 17982 $(this).height(Math.max(0, maxHeight - 17983 $(this).innerHeight() + $(this).height())); 17984 }) 17985 .css("overflow", "auto"); 17986 } else if (heightStyle === "auto") { 17987 maxHeight = 0; 17988 this.panels.each(function () { 17989 maxHeight = Math.max(maxHeight, $(this).height("").height()); 17990 }).height(maxHeight); 17991 } 17992 }, 17993 17994 _eventHandler: function (event) { 17995 var options = this.options, 17996 active = this.active, 17997 anchor = $(event.currentTarget), 17998 tab = anchor.closest("li"), 17999 clickedIsActive = tab[0] === active[0], 18000 collapsing = clickedIsActive && options.collapsible, 18001 toShow = collapsing ? $() : this._getPanelForTab(tab), 18002 toHide = !active.length ? $() : this._getPanelForTab(active), 18003 eventData = { 18004 oldTab: active, 18005 oldPanel: toHide, 18006 newTab: collapsing ? $() : tab, 18007 newPanel: toShow 18008 }; 18009 18010 event.preventDefault(); 18011 18012 if (tab.hasClass("ui-state-disabled") || 18013 18014 // tab is already loading 18015 tab.hasClass("ui-tabs-loading") || 18016 18017 // can't switch durning an animation 18018 this.running || 18019 18020 // click on active header, but not collapsible 18021 (clickedIsActive && !options.collapsible) || 18022 18023 // allow canceling activation 18024 (this._trigger("beforeActivate", event, eventData) === false)) { 18025 return; 18026 } 18027 18028 options.active = collapsing ? false : this.tabs.index(tab); 18029 18030 this.active = clickedIsActive ? $() : tab; 18031 if (this.xhr) { 18032 this.xhr.abort(); 18033 } 18034 18035 if (!toHide.length && !toShow.length) { 18036 $.error("jQuery UI Tabs: Mismatching fragment identifier."); 18037 } 18038 18039 if (toShow.length) { 18040 this.load(this.tabs.index(tab), event); 18041 } 18042 this._toggle(event, eventData); 18043 }, 18044 18045 // Handles show/hide for selecting tabs 18046 _toggle: function (event, eventData) { 18047 var that = this, 18048 toShow = eventData.newPanel, 18049 toHide = eventData.oldPanel; 18050 18051 this.running = true; 18052 18053 function complete() { 18054 that.running = false; 18055 that._trigger("activate", event, eventData); 18056 } 18057 18058 function show() { 18059 that._addClass(eventData.newTab.closest("li"), "ui-tabs-active", "ui-state-active"); 18060 18061 if (toShow.length && that.options.show) { 18062 that._show(toShow, that.options.show, complete); 18063 } else { 18064 toShow.show(); 18065 complete(); 18066 } 18067 } 18068 18069 // Start out by hiding, then showing, then completing 18070 if (toHide.length && this.options.hide) { 18071 this._hide(toHide, this.options.hide, function () { 18072 that._removeClass(eventData.oldTab.closest("li"), 18073 "ui-tabs-active", "ui-state-active"); 18074 show(); 18075 }); 18076 } else { 18077 this._removeClass(eventData.oldTab.closest("li"), 18078 "ui-tabs-active", "ui-state-active"); 18079 toHide.hide(); 18080 show(); 18081 } 18082 18083 toHide.attr("aria-hidden", "true"); 18084 eventData.oldTab.attr({ 18085 "aria-selected": "false", 18086 "aria-expanded": "false" 18087 }); 18088 18089 // If we're switching tabs, remove the old tab from the tab order. 18090 // If we're opening from collapsed state, remove the previous tab from the tab order. 18091 // If we're collapsing, then keep the collapsing tab in the tab order. 18092 if (toShow.length && toHide.length) { 18093 eventData.oldTab.attr("tabIndex", -1); 18094 } else if (toShow.length) { 18095 this.tabs.filter(function () { 18096 return $(this).attr("tabIndex") === 0; 18097 }) 18098 .attr("tabIndex", -1); 18099 } 18100 18101 toShow.attr("aria-hidden", "false"); 18102 eventData.newTab.attr({ 18103 "aria-selected": "true", 18104 "aria-expanded": "true", 18105 tabIndex: 0 18106 }); 18107 }, 18108 18109 _activate: function (index) { 18110 var anchor, 18111 active = this._findActive(index); 18112 18113 // Trying to activate the already active panel 18114 if (active[0] === this.active[0]) { 18115 return; 18116 } 18117 18118 // Trying to collapse, simulate a click on the current active header 18119 if (!active.length) { 18120 active = this.active; 18121 } 18122 18123 anchor = active.find(".ui-tabs-anchor")[0]; 18124 this._eventHandler({ 18125 target: anchor, 18126 currentTarget: anchor, 18127 preventDefault: $.noop 18128 }); 18129 }, 18130 18131 _findActive: function (index) { 18132 return index === false ? $() : this.tabs.eq(index); 18133 }, 18134 18135 _getIndex: function (index) { 18136 18137 // meta-function to give users option to provide a href string instead of a numerical index. 18138 if (typeof index === "string") { 18139 index = this.anchors.index(this.anchors.filter("[href$='" + 18140 CSS.escape(index) + "']")); 18141 } 18142 18143 return index; 18144 }, 18145 18146 _destroy: function () { 18147 if (this.xhr) { 18148 this.xhr.abort(); 18149 } 18150 18151 this.tablist 18152 .removeAttr("role") 18153 .off(this.eventNamespace); 18154 18155 this.anchors 18156 .removeAttr("role tabIndex") 18157 .removeUniqueId(); 18158 18159 this.tabs.add(this.panels).each(function () { 18160 if ($.data(this, "ui-tabs-destroy")) { 18161 $(this).remove(); 18162 } else { 18163 $(this).removeAttr("role tabIndex " + 18164 "aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded"); 18165 } 18166 }); 18167 18168 this.tabs.each(function () { 18169 var li = $(this), 18170 prev = li.data("ui-tabs-aria-controls"); 18171 if (prev) { 18172 li 18173 .attr("aria-controls", prev) 18174 .removeData("ui-tabs-aria-controls"); 18175 } else { 18176 li.removeAttr("aria-controls"); 18177 } 18178 }); 18179 18180 this.panels.show(); 18181 18182 if (this.options.heightStyle !== "content") { 18183 this.panels.css("height", ""); 18184 } 18185 }, 18186 18187 enable: function (index) { 18188 var disabled = this.options.disabled; 18189 if (disabled === false) { 18190 return; 18191 } 18192 18193 if (index === undefined) { 18194 disabled = false; 18195 } else { 18196 index = this._getIndex(index); 18197 if (Array.isArray(disabled)) { 18198 disabled = $.map(disabled, function (num) { 18199 return num !== index ? num : null; 18200 }); 18201 } else { 18202 disabled = $.map(this.tabs, function (li, num) { 18203 return num !== index ? num : null; 18204 }); 18205 } 18206 } 18207 this._setOptionDisabled(disabled); 18208 }, 18209 18210 disable: function (index) { 18211 var disabled = this.options.disabled; 18212 if (disabled === true) { 18213 return; 18214 } 18215 18216 if (index === undefined) { 18217 disabled = true; 18218 } else { 18219 index = this._getIndex(index); 18220 if ($.inArray(index, disabled) !== -1) { 18221 return; 18222 } 18223 if (Array.isArray(disabled)) { 18224 disabled = $.merge([index], disabled).sort(); 18225 } else { 18226 disabled = [index]; 18227 } 18228 } 18229 this._setOptionDisabled(disabled); 18230 }, 18231 18232 load: function (index, event) { 18233 index = this._getIndex(index); 18234 var that = this, 18235 tab = this.tabs.eq(index), 18236 anchor = tab.find(".ui-tabs-anchor"), 18237 panel = this._getPanelForTab(tab), 18238 eventData = { 18239 tab: tab, 18240 panel: panel 18241 }, 18242 complete = function (jqXHR, status) { 18243 if (status === "abort") { 18244 that.panels.stop(false, true); 18245 } 18246 18247 that._removeClass(tab, "ui-tabs-loading"); 18248 panel.removeAttr("aria-busy"); 18249 18250 if (jqXHR === that.xhr) { 18251 delete that.xhr; 18252 } 18253 }; 18254 18255 // Not remote 18256 if (this._isLocal(anchor[0])) { 18257 return; 18258 } 18259 18260 this.xhr = $.ajax(this._ajaxSettings(anchor, event, eventData)); 18261 18262 if (this.xhr.statusText !== "canceled") { 18263 this._addClass(tab, "ui-tabs-loading"); 18264 panel.attr("aria-busy", "true"); 18265 18266 this.xhr 18267 .done(function (response, status, jqXHR) { 18268 panel.html(response); 18269 that._trigger("load", event, eventData); 18270 18271 complete(jqXHR, status); 18272 }) 18273 .fail(function (jqXHR, status) { 18274 complete(jqXHR, status); 18275 }); 18276 } 18277 }, 18278 18279 _ajaxSettings: function (anchor, event, eventData) { 18280 var that = this; 18281 return { 18282 url: anchor.attr("href"), 18283 beforeSend: function (jqXHR, settings) { 18284 return that._trigger("beforeLoad", event, 18285 $.extend({ jqXHR: jqXHR, ajaxSettings: settings }, eventData)); 18286 } 18287 }; 18288 }, 18289 18290 _getPanelForTab: function (tab) { 18291 var id = $(tab).attr("aria-controls"); 18292 return this.element.find("#" + CSS.escape(id)); 18293 } 18294 }); 18295 18296 // DEPRECATED 18297 // TODO: Switch return back to widget declaration at top of file when this is removed 18298 if ($.uiBackCompat === true) { 18299 18300 // Backcompat for ui-tab class (now ui-tabs-tab) 18301 $.widget("ui.tabs", $.ui.tabs, { 18302 _processTabs: function () { 18303 this._superApply(arguments); 18304 this._addClass(this.tabs, "ui-tab"); 18305 } 18306 }); 18307 } 18308 18309 var widgetsTabs = $.ui.tabs; 18310 18311 18312 /*! 18313 * jQuery UI Tooltip 1.14.1 18314 * https://jqueryui.com 18315 * 18316 * Copyright OpenJS Foundation and other contributors 18317 * Released under the MIT license. 18318 * https://jquery.org/license 18319 */ 18320 18321 //>>label: Tooltip 18322 //>>group: Widgets 18323 //>>description: Shows additional information for any element on hover or focus. 18324 //>>docs: https://api.jqueryui.com/tooltip/ 18325 //>>demos: https://jqueryui.com/tooltip/ 18326 //>>css.structure: ../../themes/base/core.css 18327 //>>css.structure: ../../themes/base/tooltip.css 18328 //>>css.theme: ../../themes/base/theme.css 18329 18330 18331 $.widget("ui.tooltip", { 18332 version: "1.14.1", 18333 options: { 18334 classes: { 18335 "ui-tooltip": "ui-corner-all ui-widget-shadow" 18336 }, 18337 content: function () { 18338 var title = $(this).attr("title"); 18339 18340 // Escape title, since we're going from an attribute to raw HTML 18341 return $("<a>").text(title).html(); 18342 }, 18343 hide: true, 18344 18345 // Disabled elements have inconsistent behavior across browsers (#8661) 18346 items: "[title]:not([disabled])", 18347 position: { 18348 my: "left top+15", 18349 at: "left bottom", 18350 collision: "flipfit flip" 18351 }, 18352 show: true, 18353 track: false, 18354 18355 // Callbacks 18356 close: null, 18357 open: null 18358 }, 18359 18360 _addDescribedBy: function (elem, id) { 18361 var describedby = (elem.attr("aria-describedby") || "").split(/\s+/); 18362 describedby.push(id); 18363 elem 18364 .data("ui-tooltip-id", id) 18365 .attr("aria-describedby", String.prototype.trim.call(describedby.join(" "))); 18366 }, 18367 18368 _removeDescribedBy: function (elem) { 18369 var id = elem.data("ui-tooltip-id"), 18370 describedby = (elem.attr("aria-describedby") || "").split(/\s+/), 18371 index = $.inArray(id, describedby); 18372 18373 if (index !== -1) { 18374 describedby.splice(index, 1); 18375 } 18376 18377 elem.removeData("ui-tooltip-id"); 18378 describedby = String.prototype.trim.call(describedby.join(" ")); 18379 if (describedby) { 18380 elem.attr("aria-describedby", describedby); 18381 } else { 18382 elem.removeAttr("aria-describedby"); 18383 } 18384 }, 18385 18386 _create: function () { 18387 this._on({ 18388 mouseover: "open", 18389 focusin: "open" 18390 }); 18391 18392 // IDs of generated tooltips, needed for destroy 18393 this.tooltips = {}; 18394 18395 // IDs of parent tooltips where we removed the title attribute 18396 this.parents = {}; 18397 18398 // Append the aria-live region so tooltips announce correctly 18399 this.liveRegion = $("<div>") 18400 .attr({ 18401 role: "log", 18402 "aria-live": "assertive", 18403 "aria-relevant": "additions" 18404 }) 18405 .appendTo(this.document[0].body); 18406 this._addClass(this.liveRegion, null, "ui-helper-hidden-accessible"); 18407 18408 this.disabledTitles = $([]); 18409 }, 18410 18411 _setOption: function (key, value) { 18412 var that = this; 18413 18414 this._super(key, value); 18415 18416 if (key === "content") { 18417 $.each(this.tooltips, function (id, tooltipData) { 18418 that._updateContent(tooltipData.element); 18419 }); 18420 } 18421 }, 18422 18423 _setOptionDisabled: function (value) { 18424 this[value ? "_disable" : "_enable"](); 18425 }, 18426 18427 _disable: function () { 18428 var that = this; 18429 18430 // Close open tooltips 18431 $.each(this.tooltips, function (id, tooltipData) { 18432 var event = $.Event("blur"); 18433 event.target = event.currentTarget = tooltipData.element[0]; 18434 that.close(event, true); 18435 }); 18436 18437 // Remove title attributes to prevent native tooltips 18438 this.disabledTitles = this.disabledTitles.add( 18439 this.element.find(this.options.items).addBack() 18440 .filter(function () { 18441 var element = $(this); 18442 if (element.is("[title]")) { 18443 return element 18444 .data("ui-tooltip-title", element.attr("title")) 18445 .removeAttr("title"); 18446 } 18447 }) 18448 ); 18449 }, 18450 18451 _enable: function () { 18452 18453 // restore title attributes 18454 this.disabledTitles.each(function () { 18455 var element = $(this); 18456 if (element.data("ui-tooltip-title")) { 18457 element.attr("title", element.data("ui-tooltip-title")); 18458 } 18459 }); 18460 this.disabledTitles = $([]); 18461 }, 18462 18463 open: function (event) { 18464 var that = this, 18465 target = $(event ? event.target : this.element) 18466 18467 // we need closest here due to mouseover bubbling, 18468 // but always pointing at the same event target 18469 .closest(this.options.items); 18470 18471 // No element to show a tooltip for or the tooltip is already open 18472 if (!target.length || target.data("ui-tooltip-id")) { 18473 return; 18474 } 18475 18476 if (target.attr("title")) { 18477 target.data("ui-tooltip-title", target.attr("title")); 18478 } 18479 18480 target.data("ui-tooltip-open", true); 18481 18482 // Kill parent tooltips, custom or native, for hover 18483 if (event && event.type === "mouseover") { 18484 target.parents().each(function () { 18485 var parent = $(this), 18486 blurEvent; 18487 if (parent.data("ui-tooltip-open")) { 18488 blurEvent = $.Event("blur"); 18489 blurEvent.target = blurEvent.currentTarget = this; 18490 that.close(blurEvent, true); 18491 } 18492 if (parent.attr("title")) { 18493 parent.uniqueId(); 18494 that.parents[this.id] = { 18495 element: this, 18496 title: parent.attr("title") 18497 }; 18498 parent.attr("title", ""); 18499 } 18500 }); 18501 } 18502 18503 this._registerCloseHandlers(event, target); 18504 this._updateContent(target, event); 18505 }, 18506 18507 _updateContent: function (target, event) { 18508 var content, 18509 contentOption = this.options.content, 18510 that = this, 18511 eventType = event ? event.type : null; 18512 18513 if (typeof contentOption === "string" || contentOption.nodeType || 18514 contentOption.jquery) { 18515 return this._open(event, target, contentOption); 18516 } 18517 18518 content = contentOption.call(target[0], function (response) { 18519 18520 // Ignore async response if tooltip was closed already 18521 if (!target.data("ui-tooltip-open")) { 18522 return; 18523 } 18524 18525 // JQuery creates a special event for focusin when it doesn't 18526 // exist natively. To improve performance, the native event 18527 // object is reused and the type is changed. Therefore, we can't 18528 // rely on the type being correct after the event finished 18529 // bubbling, so we set it back to the previous value. (#8740) 18530 if (event) { 18531 event.type = eventType; 18532 } 18533 that._open(event, target, response); 18534 }); 18535 if (content) { 18536 this._open(event, target, content); 18537 } 18538 }, 18539 18540 _open: function (event, target, content) { 18541 var tooltipData, tooltip, delayedShow, a11yContent, 18542 positionOption = $.extend({}, this.options.position); 18543 18544 if (!content) { 18545 return; 18546 } 18547 18548 // Content can be updated multiple times. If the tooltip already 18549 // exists, then just update the content and bail. 18550 tooltipData = this._find(target); 18551 if (tooltipData) { 18552 tooltipData.tooltip.find(".ui-tooltip-content").html(content); 18553 return; 18554 } 18555 18556 // If we have a title, clear it to prevent the native tooltip 18557 // we have to check first to avoid defining a title if none exists 18558 // (we don't want to cause an element to start matching [title]) 18559 // 18560 // We use removeAttr only for key events, to allow IE to export the correct 18561 // accessible attributes. For mouse events, set to empty string to avoid 18562 // native tooltip showing up (happens only when removing inside mouseover). 18563 if (target.is("[title]")) { 18564 if (event && event.type === "mouseover") { 18565 target.attr("title", ""); 18566 } else { 18567 target.removeAttr("title"); 18568 } 18569 } 18570 18571 tooltipData = this._tooltip(target); 18572 tooltip = tooltipData.tooltip; 18573 this._addDescribedBy(target, tooltip.attr("id")); 18574 tooltip.find(".ui-tooltip-content").html(content); 18575 18576 // Support: Voiceover on OS X, JAWS on IE <= 9 18577 // JAWS announces deletions even when aria-relevant="additions" 18578 // Voiceover will sometimes re-read the entire log region's contents from the beginning 18579 this.liveRegion.children().hide(); 18580 a11yContent = $("<div>").html(tooltip.find(".ui-tooltip-content").html()); 18581 a11yContent.removeAttr("name").find("[name]").removeAttr("name"); 18582 a11yContent.removeAttr("id").find("[id]").removeAttr("id"); 18583 a11yContent.appendTo(this.liveRegion); 18584 18585 function position(event) { 18586 positionOption.of = event; 18587 if (tooltip.is(":hidden")) { 18588 return; 18589 } 18590 tooltip.position(positionOption); 18591 } 18592 if (this.options.track && event && /^mouse/.test(event.type)) { 18593 this._on(this.document, { 18594 mousemove: position 18595 }); 18596 18597 // trigger once to override element-relative positioning 18598 position(event); 18599 } else { 18600 tooltip.position($.extend({ 18601 of: target 18602 }, this.options.position)); 18603 } 18604 18605 tooltip.hide(); 18606 18607 this._show(tooltip, this.options.show); 18608 18609 // Handle tracking tooltips that are shown with a delay (#8644). As soon 18610 // as the tooltip is visible, position the tooltip using the most recent 18611 // event. 18612 // Adds the check to add the timers only when both delay and track options are set (#14682) 18613 if (this.options.track && this.options.show && this.options.show.delay) { 18614 delayedShow = this.delayedShow = setInterval(function () { 18615 if (tooltip.is(":visible")) { 18616 position(positionOption.of); 18617 clearInterval(delayedShow); 18618 } 18619 }, 13); 18620 } 18621 18622 this._trigger("open", event, { tooltip: tooltip }); 18623 }, 18624 18625 _registerCloseHandlers: function (event, target) { 18626 var events = { 18627 keyup: function (event) { 18628 if (event.keyCode === $.ui.keyCode.ESCAPE) { 18629 var fakeEvent = $.Event(event); 18630 fakeEvent.currentTarget = target[0]; 18631 this.close(fakeEvent, true); 18632 } 18633 } 18634 }; 18635 18636 // Only bind remove handler for delegated targets. Non-delegated 18637 // tooltips will handle this in destroy. 18638 if (target[0] !== this.element[0]) { 18639 events.remove = function () { 18640 var targetElement = this._find(target); 18641 if (targetElement) { 18642 this._removeTooltip(targetElement.tooltip); 18643 } 18644 }; 18645 } 18646 18647 if (!event || event.type === "mouseover") { 18648 events.mouseleave = "close"; 18649 } 18650 if (!event || event.type === "focusin") { 18651 events.focusout = "close"; 18652 } 18653 this._on(true, target, events); 18654 }, 18655 18656 close: function (event) { 18657 var tooltip, 18658 that = this, 18659 target = $(event ? event.currentTarget : this.element), 18660 tooltipData = this._find(target); 18661 18662 // The tooltip may already be closed 18663 if (!tooltipData) { 18664 18665 // We set ui-tooltip-open immediately upon open (in open()), but only set the 18666 // additional data once there's actually content to show (in _open()). So even if the 18667 // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in 18668 // the period between open() and _open(). 18669 target.removeData("ui-tooltip-open"); 18670 return; 18671 } 18672 18673 tooltip = tooltipData.tooltip; 18674 18675 // Disabling closes the tooltip, so we need to track when we're closing 18676 // to avoid an infinite loop in case the tooltip becomes disabled on close 18677 if (tooltipData.closing) { 18678 return; 18679 } 18680 18681 // Clear the interval for delayed tracking tooltips 18682 clearInterval(this.delayedShow); 18683 18684 // Only set title if we had one before (see comment in _open()) 18685 // If the title attribute has changed since open(), don't restore 18686 if (target.data("ui-tooltip-title") && !target.attr("title")) { 18687 target.attr("title", target.data("ui-tooltip-title")); 18688 } 18689 18690 this._removeDescribedBy(target); 18691 18692 tooltipData.hiding = true; 18693 tooltip.stop(true); 18694 this._hide(tooltip, this.options.hide, function () { 18695 that._removeTooltip($(this)); 18696 }); 18697 18698 target.removeData("ui-tooltip-open"); 18699 this._off(target, "mouseleave focusout keyup"); 18700 18701 // Remove 'remove' binding only on delegated targets 18702 if (target[0] !== this.element[0]) { 18703 this._off(target, "remove"); 18704 } 18705 this._off(this.document, "mousemove"); 18706 18707 if (event && event.type === "mouseleave") { 18708 $.each(this.parents, function (id, parent) { 18709 $(parent.element).attr("title", parent.title); 18710 delete that.parents[id]; 18711 }); 18712 } 18713 18714 tooltipData.closing = true; 18715 this._trigger("close", event, { tooltip: tooltip }); 18716 if (!tooltipData.hiding) { 18717 tooltipData.closing = false; 18718 } 18719 }, 18720 18721 _tooltip: function (element) { 18722 var tooltip = $("<div>").attr("role", "tooltip"), 18723 content = $("<div>").appendTo(tooltip), 18724 id = tooltip.uniqueId().attr("id"); 18725 18726 this._addClass(content, "ui-tooltip-content"); 18727 this._addClass(tooltip, "ui-tooltip", "ui-widget ui-widget-content"); 18728 18729 tooltip.appendTo(this._appendTo(element)); 18730 18731 return this.tooltips[id] = { 18732 element: element, 18733 tooltip: tooltip 18734 }; 18735 }, 18736 18737 _find: function (target) { 18738 var id = target.data("ui-tooltip-id"); 18739 return id ? this.tooltips[id] : null; 18740 }, 18741 18742 _removeTooltip: function (tooltip) { 18743 18744 // Clear the interval for delayed tracking tooltips 18745 clearInterval(this.delayedShow); 18746 18747 tooltip.remove(); 18748 delete this.tooltips[tooltip.attr("id")]; 18749 }, 18750 18751 _appendTo: function (target) { 18752 var element = target.closest(".ui-front, dialog"); 18753 18754 if (!element.length) { 18755 element = this.document[0].body; 18756 } 18757 18758 return element; 18759 }, 18760 18761 _destroy: function () { 18762 var that = this; 18763 18764 // Close open tooltips 18765 $.each(this.tooltips, function (id, tooltipData) { 18766 18767 // Delegate to close method to handle common cleanup 18768 var event = $.Event("blur"), 18769 element = tooltipData.element; 18770 event.target = event.currentTarget = element[0]; 18771 that.close(event, true); 18772 18773 // Remove immediately; destroying an open tooltip doesn't use the 18774 // hide animation 18775 $("#" + id).remove(); 18776 18777 // Restore the title 18778 if (element.data("ui-tooltip-title")) { 18779 18780 // If the title attribute has changed since open(), don't restore 18781 if (!element.attr("title")) { 18782 element.attr("title", element.data("ui-tooltip-title")); 18783 } 18784 element.removeData("ui-tooltip-title"); 18785 } 18786 }); 18787 this.liveRegion.remove(); 18788 } 18789 }); 18790 18791 // DEPRECATED 18792 // TODO: Switch return back to widget declaration at top of file when this is removed 18793 if ($.uiBackCompat === true) { 18794 18795 // Backcompat for tooltipClass option 18796 $.widget("ui.tooltip", $.ui.tooltip, { 18797 options: { 18798 tooltipClass: null 18799 }, 18800 _tooltip: function () { 18801 var tooltipData = this._superApply(arguments); 18802 if (this.options.tooltipClass) { 18803 tooltipData.tooltip.addClass(this.options.tooltipClass); 18804 } 18805 return tooltipData; 18806 } 18807 }); 18808 } 18809 18810 var widgetsTooltip = $.ui.tooltip; 18811 18812 18813 18814 18815});
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.