1 /*! jQuery UI - v1.12.1+0b7246b6eeadfa9e2696e22f3230f6452f8129dc - 2020-02-20
4 * Copyright jQuery Foundation and other contributors; Licensed MIT */
6 /* global define, require */
7 /* eslint-disable no-param-reassign, new-cap, jsdoc/require-jsdoc */
11 if (typeof define === 'function' && define.amd) {
12 // AMD. Register as an anonymous module.
13 define(['jquery'], factory);
14 } else if (typeof exports === 'object') {
16 factory(require('jquery'));
19 factory(window.jQuery);
26 $.ui.version = '1.12.1';
29 * jQuery UI Widget 1.12.1
32 * Copyright jQuery Foundation and other contributors
33 * Released under the MIT license.
34 * http://jquery.org/license
39 //>>description: Provides a factory for creating stateful widgets with a common API.
40 //>>docs: http://api.jqueryui.com/jQuery.widget/
41 //>>demos: http://jqueryui.com/widget/
43 // Support: jQuery 1.9.x or older
44 // $.expr[ ":" ] is deprecated.
45 if (!$.expr.pseudos) {
46 $.expr.pseudos = $.expr[':'];
49 // Support: jQuery 1.11.x or older
50 // $.unique has been renamed to $.uniqueSort
52 $.uniqueSort = $.unique;
56 var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
57 var widgetSlice = Array.prototype.slice;
59 $.cleanData = (function (orig) {
60 return function (elems) {
62 // eslint-disable-next-line eqeqeq
63 for (i = 0; (elem = elems[i]) != null; i++) {
64 // Only trigger remove when necessary to save time
65 events = $._data(elem, 'events');
66 if (events && events.remove) {
67 $(elem).triggerHandler('remove');
74 $.widget = function (name, base, prototype) {
75 var existingConstructor, constructor, basePrototype;
77 // ProxiedPrototype allows the provided prototype to remain unmodified
78 // so that it can be used as a mixin for multiple widgets (#8876)
79 var proxiedPrototype = {};
81 var namespace = name.split('.')[0];
82 name = name.split('.')[1];
83 var fullName = namespace + '-' + name;
90 if ($.isArray(prototype)) {
91 prototype = $.extend.apply(null, [{}].concat(prototype));
94 // Create selector for plugin
95 $.expr.pseudos[fullName.toLowerCase()] = function (elem) {
96 return !!$.data(elem, fullName);
99 $[namespace] = $[namespace] || {};
100 existingConstructor = $[namespace][name];
101 constructor = $[namespace][name] = function (options, element) {
102 // Allow instantiation without "new" keyword
103 if (!this._createWidget) {
104 return new constructor(options, element);
107 // Allow instantiation without initializing for simple inheritance
108 // must use "new" keyword (the code above always passes args)
109 if (arguments.length) {
110 this._createWidget(options, element);
114 // Extend with the existing constructor to carry over any static properties
115 $.extend(constructor, existingConstructor, {
116 version: prototype.version,
118 // Copy the object used to create the prototype in case we need to
119 // redefine the widget later
120 _proto: $.extend({}, prototype),
122 // Track widgets that inherit from this widget in case this widget is
123 // redefined after a widget inherits from it
124 _childConstructors: []
127 basePrototype = new base();
129 // We need to make the options hash a property directly on the new instance
130 // otherwise we'll modify the options hash on the prototype that we're
132 basePrototype.options = $.widget.extend({}, basePrototype.options);
133 $.each(prototype, function (prop, value) {
134 if (!$.isFunction(value)) {
135 proxiedPrototype[prop] = value;
138 proxiedPrototype[prop] = (function () {
140 return base.prototype[prop].apply(this, arguments);
143 function _superApply(args) {
144 return base.prototype[prop].apply(this, args);
148 var __super = this._super;
149 var __superApply = this._superApply;
152 this._super = _super;
153 this._superApply = _superApply;
155 returnValue = value.apply(this, arguments);
157 this._super = __super;
158 this._superApply = __superApply;
164 constructor.prototype = $.widget.extend(
167 // TODO: remove support for widgetEventPrefix
168 // always use the name + a colon as the prefix, e.g., draggable:start
169 // don't prefix for widgets that aren't DOM-based
170 widgetEventPrefix: existingConstructor
171 ? basePrototype.widgetEventPrefix || name
176 constructor: constructor,
177 namespace: namespace,
179 widgetFullName: fullName
183 // If this widget is being redefined then we need to find all widgets that
184 // are inheriting from it and redefine all of them so that they inherit from
185 // the new version of this widget. We're essentially trying to replace one
186 // level in the prototype chain.
187 if (existingConstructor) {
188 $.each(existingConstructor._childConstructors, function (i, child) {
189 var childPrototype = child.prototype;
191 // Redefine the child widget using the same prototype that was
192 // originally used, but inherit from the new version of the base
194 childPrototype.namespace + '.' + childPrototype.widgetName,
200 // Remove the list of existing child constructors from the old constructor
201 // so the old child constructors can be garbage collected
202 delete existingConstructor._childConstructors;
204 base._childConstructors.push(constructor);
207 $.widget.bridge(name, constructor);
212 $.widget.extend = function (target) {
213 var input = widgetSlice.call(arguments, 1);
215 var inputLength = input.length;
219 for (; inputIndex < inputLength; inputIndex++) {
220 for (key in input[inputIndex]) {
221 value = input[inputIndex][key];
223 widgetHasOwnProperty.call(input[inputIndex], key) &&
227 if ($.isPlainObject(value)) {
228 target[key] = $.isPlainObject(target[key])
229 ? $.widget.extend({}, target[key], value)
230 : // Don't extend strings, arrays, etc. with objects
231 $.widget.extend({}, value);
233 // Copy everything else by reference
243 $.widget.bridge = function (name, object) {
244 var fullName = object.prototype.widgetFullName || name;
245 $.fn[name] = function (options) {
246 var isMethodCall = typeof options === 'string';
247 var args = widgetSlice.call(arguments, 1);
248 var returnValue = this;
251 // If this is an empty collection, we need to have the instance method
252 // return undefined instead of the jQuery instance
253 if (!this.length && options === 'instance') {
254 returnValue = undefined;
256 this.each(function () {
258 var instance = $.data(this, fullName);
260 if (options === 'instance') {
261 returnValue = instance;
267 'cannot call methods on ' +
269 ' prior to initialization; ' +
270 "attempted to call method '" +
276 if (!$.isFunction(instance[options]) || options.charAt(0) === '_') {
286 methodValue = instance[options].apply(instance, args);
288 if (methodValue !== instance && methodValue !== undefined) {
290 methodValue && methodValue.jquery
291 ? returnValue.pushStack(methodValue.get())
298 // Allow multiple hashes to be passed on init
300 options = $.widget.extend.apply(null, [options].concat(args));
303 this.each(function () {
304 var instance = $.data(this, fullName);
306 instance.option(options || {});
307 if (instance._init) {
311 $.data(this, fullName, new object(options, this));
320 $.Widget = function (/* options, element */) {};
321 $.Widget._childConstructors = [];
323 $.Widget.prototype = {
324 widgetName: 'widget',
325 widgetEventPrefix: '',
326 defaultElement: '<div>',
336 _createWidget: function (options, element) {
337 element = $(element || this.defaultElement || this)[0];
338 this.element = $(element);
339 this.uuid = widgetUuid++;
340 this.eventNamespace = '.' + this.widgetName + this.uuid;
343 this.hoverable = $();
344 this.focusable = $();
345 this.classesElementLookup = {};
347 if (element !== this) {
348 $.data(element, this.widgetFullName, this);
349 this._on(true, this.element, {
350 remove: function (event) {
351 if (event.target === element) {
358 ? // Element within the document
359 element.ownerDocument
360 : // Element is window or document
361 element.document || element
364 this.document[0].defaultView || this.document[0].parentWindow
368 this.options = $.widget.extend(
371 this._getCreateOptions(),
377 if (this.options.disabled) {
378 this._setOptionDisabled(this.options.disabled);
381 this._trigger('create', null, this._getCreateEventData());
385 _getCreateOptions: function () {
389 _getCreateEventData: $.noop,
395 destroy: function () {
399 $.each(this.classesElementLookup, function (key, value) {
400 that._removeClass(value, key);
403 // We can probably remove the unbind calls in 2.0
404 // all event bindings should go through this._on()
405 this.element.off(this.eventNamespace).removeData(this.widgetFullName);
406 this.widget().off(this.eventNamespace).removeAttr('aria-disabled');
408 // Clean up events and states
409 this.bindings.off(this.eventNamespace);
414 widget: function () {
418 option: function (key, value) {
424 if (arguments.length === 0) {
425 // Don't return a reference to the internal hash
426 return $.widget.extend({}, this.options);
429 if (typeof key === 'string') {
430 // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
432 parts = key.split('.');
435 curOption = options[key] = $.widget.extend({}, this.options[key]);
436 for (i = 0; i < parts.length - 1; i++) {
437 curOption[parts[i]] = curOption[parts[i]] || {};
438 curOption = curOption[parts[i]];
441 if (arguments.length === 1) {
442 return curOption[key] === undefined ? null : curOption[key];
444 curOption[key] = value;
446 if (arguments.length === 1) {
447 return this.options[key] === undefined ? null : this.options[key];
449 options[key] = value;
453 this._setOptions(options);
458 _setOptions: function (options) {
461 for (key in options) {
462 this._setOption(key, options[key]);
468 _setOption: function (key, value) {
469 if (key === 'classes') {
470 this._setOptionClasses(value);
473 this.options[key] = value;
475 if (key === 'disabled') {
476 this._setOptionDisabled(value);
482 _setOptionClasses: function (value) {
483 var classKey, elements, currentElements;
485 for (classKey in value) {
486 currentElements = this.classesElementLookup[classKey];
488 value[classKey] === this.options.classes[classKey] ||
490 !currentElements.length
495 // We are doing this to create a new jQuery object because the _removeClass() call
496 // on the next line is going to destroy the reference to the current elements being
497 // tracked. We need to save a copy of this collection so that we can add the new classes
499 elements = $(currentElements.get());
500 this._removeClass(currentElements, classKey);
502 // We don't use _addClass() here, because that uses this.options.classes
503 // for generating the string of classes. We want to use the value passed in from
504 // _setOption(), this is the new value of the classes option which was passed to
505 // _setOption(). We pass this value directly to _classes().
517 _setOptionDisabled: function (value) {
520 this.widgetFullName + '-disabled',
525 // If the widget is becoming disabled, then nothing is interactive
527 this._removeClass(this.hoverable, null, 'ui-state-hover');
528 this._removeClass(this.focusable, null, 'ui-state-focus');
532 enable: function () {
533 return this._setOptions({ disabled: false });
536 disable: function () {
537 return this._setOptions({ disabled: true });
540 _classes: function (options) {
546 element: this.element,
547 classes: this.options.classes || {}
552 function bindRemoveEvent() {
553 options.element.each(function (_, element) {
554 var isTracked = $.map(that.classesElementLookup, function (elements) {
556 }).some(function (elements) {
557 return elements.is(element);
561 that._on($(element), {
562 remove: '_untrackClassesElement'
568 function processClassString(classes, checkOption) {
570 for (i = 0; i < classes.length; i++) {
571 current = that.classesElementLookup[classes[i]] || $();
575 $.uniqueSort(current.get().concat(options.element.get()))
578 current = $(current.not(options.element).get());
580 that.classesElementLookup[classes[i]] = current;
581 full.push(classes[i]);
582 if (checkOption && options.classes[classes[i]]) {
583 full.push(options.classes[classes[i]]);
589 processClassString(options.keys.match(/\S+/g) || [], true);
592 processClassString(options.extra.match(/\S+/g) || []);
595 return full.join(' ');
598 _untrackClassesElement: function (event) {
600 $.each(that.classesElementLookup, function (key, value) {
601 if ($.inArray(event.target, value) !== -1) {
602 that.classesElementLookup[key] = $(value.not(event.target).get());
606 this._off($(event.target));
609 _removeClass: function (element, keys, extra) {
610 return this._toggleClass(element, keys, extra, false);
613 _addClass: function (element, keys, extra) {
614 return this._toggleClass(element, keys, extra, true);
617 _toggleClass: function (element, keys, extra, add) {
618 add = typeof add === 'boolean' ? add : extra;
619 var shift = typeof element === 'string' || element === null,
621 extra: shift ? keys : extra,
622 keys: shift ? element : keys,
623 element: shift ? this.element : element,
626 options.element.toggleClass(this._classes(options), add);
630 _on: function (suppressDisabledCheck, element, handlers) {
634 // No suppressDisabledCheck flag, shuffle arguments
635 if (typeof suppressDisabledCheck !== 'boolean') {
637 element = suppressDisabledCheck;
638 suppressDisabledCheck = false;
641 // No element argument, shuffle and use this.element
644 element = this.element;
645 delegateElement = this.widget();
647 element = delegateElement = $(element);
648 this.bindings = this.bindings.add(element);
651 $.each(handlers, function (event, handler) {
652 function handlerProxy() {
653 // Allow widgets to customize the disabled handling
654 // - disabled as an array instead of boolean
655 // - disabled class as method for disabling individual parts
657 !suppressDisabledCheck &&
658 (instance.options.disabled === true ||
659 $(this).hasClass('ui-state-disabled'))
664 typeof handler === 'string' ? instance[handler] : handler
665 ).apply(instance, arguments);
668 // Copy the guid so direct unbinding works
669 if (typeof handler !== 'string') {
670 handlerProxy.guid = handler.guid =
671 handler.guid || handlerProxy.guid || $.guid++;
674 var match = event.match(/^([\w:-]*)\s*(.*)$/);
675 var eventName = match[1] + instance.eventNamespace;
676 var selector = match[2];
679 delegateElement.on(eventName, selector, handlerProxy);
681 element.on(eventName, handlerProxy);
686 _off: function (element, eventName) {
688 (eventName || '').split(' ').join(this.eventNamespace + ' ') +
690 element.off(eventName);
692 // Clear the stack to avoid memory leaks (#10056)
693 this.bindings = $(this.bindings.not(element).get());
694 this.focusable = $(this.focusable.not(element).get());
695 this.hoverable = $(this.hoverable.not(element).get());
698 _delay: function (handler, delay) {
700 function handlerProxy() {
702 typeof handler === 'string' ? instance[handler] : handler
703 ).apply(instance, arguments);
705 return setTimeout(handlerProxy, delay || 0);
708 _hoverable: function (element) {
709 this.hoverable = this.hoverable.add(element);
711 mouseenter: function (event) {
712 this._addClass($(event.currentTarget), null, 'ui-state-hover');
714 mouseleave: function (event) {
715 this._removeClass($(event.currentTarget), null, 'ui-state-hover');
720 _focusable: function (element) {
721 this.focusable = this.focusable.add(element);
723 focusin: function (event) {
724 this._addClass($(event.currentTarget), null, 'ui-state-focus');
726 focusout: function (event) {
727 this._removeClass($(event.currentTarget), null, 'ui-state-focus');
732 _trigger: function (type, event, data) {
734 var callback = this.options[type];
737 event = $.Event(event);
739 type === this.widgetEventPrefix ? type : this.widgetEventPrefix + type
742 // The original event may come from any element
743 // so we need to reset the target on the new event
744 event.target = this.element[0];
746 // Copy original event properties over to the new event
747 orig = event.originalEvent;
750 if (!(prop in event)) {
751 event[prop] = orig[prop];
756 this.element.trigger(event, data);
758 ($.isFunction(callback) &&
759 callback.apply(this.element[0], [event].concat(data)) === false) ||
760 event.isDefaultPrevented()
765 $.each({ show: 'fadeIn', hide: 'fadeOut' }, function (method, defaultEffect) {
766 $.Widget.prototype['_' + method] = function (element, options, callback) {
767 if (typeof options === 'string') {
768 options = { effect: options };
772 var effectName = !options
774 : options === true || typeof options === 'number'
776 : options.effect || defaultEffect;
778 options = options || {};
779 if (typeof options === 'number') {
780 options = { duration: options };
783 hasOptions = !$.isEmptyObject(options);
784 options.complete = callback;
787 element.delay(options.delay);
790 if (hasOptions && $.effects && $.effects.effect[effectName]) {
791 element[method](options);
792 } else if (effectName !== method && element[effectName]) {
793 element[effectName](options.duration, options.easing, callback);
795 element.queue(function (next) {
798 callback.call(element[0]);