· 5 years ago · May 24, 2020, 06:32 AM
1/*! jQuery UI - v1.12.1 - 2016-09-14
2* http://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-1-7.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 jQuery Foundation and other contributors; Licensed MIT */
5
6(function( factory ) {
7 if ( typeof define === "function" && define.amd ) {
8
9 // AMD. Register as an anonymous module.
10 define([ "jquery" ], factory );
11 } else {
12
13 // Browser globals
14 factory( $jQuery );
15 }
16}(function( $ ) {
17
18$.ui = $.ui || {};
19
20var version = $.ui.version = "1.12.1";
21
22
23/*!
24 * jQuery UI Widget 1.12.1
25 * http://jqueryui.com
26 *
27 * Copyright jQuery Foundation and other contributors
28 * Released under the MIT license.
29 * http://jquery.org/license
30 */
31
32//>>label: Widget
33//>>group: Core
34//>>description: Provides a factory for creating stateful widgets with a common API.
35//>>docs: http://api.jqueryui.com/jQuery.widget/
36//>>demos: http://jqueryui.com/widget/
37
38
39
40var widgetUuid = 0;
41var widgetSlice = Array.prototype.slice;
42
43$.cleanData = ( function( orig ) {
44 return function( elems ) {
45 var events, elem, i;
46 for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
47 try {
48
49 // Only trigger remove when necessary to save time
50 events = $._data( elem, "events" );
51 if ( events && events.remove ) {
52 $( elem ).triggerHandler( "remove" );
53 }
54
55 // Http://bugs.jquery.com/ticket/8235
56 } catch ( e ) {}
57 }
58 orig( elems );
59 };
60} )( $.cleanData );
61
62$.widget = function( name, base, prototype ) {
63 var existingConstructor, constructor, basePrototype;
64
65 // ProxiedPrototype allows the provided prototype to remain unmodified
66 // so that it can be used as a mixin for multiple widgets (#8876)
67 var proxiedPrototype = {};
68
69 var namespace = name.split( "." )[ 0 ];
70 name = name.split( "." )[ 1 ];
71 var fullName = namespace + "-" + name;
72
73 if ( !prototype ) {
74 prototype = base;
75 base = $.Widget;
76 }
77
78 if ( $.isArray( prototype ) ) {
79 prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
80 }
81
82 // Create selector for plugin
83 $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
84 return !!$.data( elem, fullName );
85 };
86
87 $[ namespace ] = $[ namespace ] || {};
88 existingConstructor = $[ namespace ][ name ];
89 constructor = $[ namespace ][ name ] = function( options, element ) {
90
91 // Allow instantiation without "new" keyword
92 if ( !this._createWidget ) {
93 return new constructor( options, element );
94 }
95
96 // Allow instantiation without initializing for simple inheritance
97 // must use "new" keyword (the code above always passes args)
98 if ( arguments.length ) {
99 this._createWidget( options, element );
100 }
101 };
102
103 // Extend with the existing constructor to carry over any static properties
104 $.extend( constructor, existingConstructor, {
105 version: prototype.version,
106
107 // Copy the object used to create the prototype in case we need to
108 // redefine the widget later
109 _proto: $.extend( {}, prototype ),
110
111 // Track widgets that inherit from this widget in case this widget is
112 // redefined after a widget inherits from it
113 _childConstructors: []
114 } );
115
116 basePrototype = new base();
117
118 // We need to make the options hash a property directly on the new instance
119 // otherwise we'll modify the options hash on the prototype that we're
120 // inheriting from
121 basePrototype.options = $.widget.extend( {}, basePrototype.options );
122 $.each( prototype, function( prop, value ) {
123 if ( !$.isFunction( value ) ) {
124 proxiedPrototype[ prop ] = value;
125 return;
126 }
127 proxiedPrototype[ prop ] = ( function() {
128 function _super() {
129 return base.prototype[ prop ].apply( this, arguments );
130 }
131
132 function _superApply( args ) {
133 return base.prototype[ prop ].apply( this, args );
134 }
135
136 return function() {
137 var __super = this._super;
138 var __superApply = this._superApply;
139 var returnValue;
140
141 this._super = _super;
142 this._superApply = _superApply;
143
144 returnValue = value.apply( this, arguments );
145
146 this._super = __super;
147 this._superApply = __superApply;
148
149 return returnValue;
150 };
151 } )();
152 } );
153 constructor.prototype = $.widget.extend( basePrototype, {
154
155 // TODO: remove support for widgetEventPrefix
156 // always use the name + a colon as the prefix, e.g., draggable:start
157 // don't prefix for widgets that aren't DOM-based
158 widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
159 }, proxiedPrototype, {
160 constructor: constructor,
161 namespace: namespace,
162 widgetName: name,
163 widgetFullName: fullName
164 } );
165
166 // If this widget is being redefined then we need to find all widgets that
167 // are inheriting from it and redefine all of them so that they inherit from
168 // the new version of this widget. We're essentially trying to replace one
169 // level in the prototype chain.
170 if ( existingConstructor ) {
171 $.each( existingConstructor._childConstructors, function( i, child ) {
172 var childPrototype = child.prototype;
173
174 // Redefine the child widget using the same prototype that was
175 // originally used, but inherit from the new version of the base
176 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
177 child._proto );
178 } );
179
180 // Remove the list of existing child constructors from the old constructor
181 // so the old child constructors can be garbage collected
182 delete existingConstructor._childConstructors;
183 } else {
184 base._childConstructors.push( constructor );
185 }
186
187 $.widget.bridge( name, constructor );
188
189 return constructor;
190};
191
192$.widget.extend = function( target ) {
193 var input = widgetSlice.call( arguments, 1 );
194 var inputIndex = 0;
195 var inputLength = input.length;
196 var key;
197 var value;
198
199 for ( ; inputIndex < inputLength; inputIndex++ ) {
200 for ( key in input[ inputIndex ] ) {
201 value = input[ inputIndex ][ key ];
202 if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
203
204 // Clone objects
205 if ( $.isPlainObject( value ) ) {
206 target[ key ] = $.isPlainObject( target[ key ] ) ?
207 $.widget.extend( {}, target[ key ], value ) :
208
209 // Don't extend strings, arrays, etc. with objects
210 $.widget.extend( {}, value );
211
212 // Copy everything else by reference
213 } else {
214 target[ key ] = value;
215 }
216 }
217 }
218 }
219 return target;
220};
221
222$.widget.bridge = function( name, object ) {
223 var fullName = object.prototype.widgetFullName || name;
224 $.fn[ name ] = function( options ) {
225 var isMethodCall = typeof options === "string";
226 var args = widgetSlice.call( arguments, 1 );
227 var returnValue = this;
228
229 if ( isMethodCall ) {
230
231 // If this is an empty collection, we need to have the instance method
232 // return undefined instead of the jQuery instance
233 if ( !this.length && options === "instance" ) {
234 returnValue = undefined;
235 } else {
236 this.each( function() {
237 var methodValue;
238 var instance = $.data( this, fullName );
239
240 if ( options === "instance" ) {
241 returnValue = instance;
242 return false;
243 }
244
245 if ( !instance ) {
246 return $.error( "cannot call methods on " + name +
247 " prior to initialization; " +
248 "attempted to call method '" + options + "'" );
249 }
250
251 if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) {
252 return $.error( "no such method '" + options + "' for " + name +
253 " widget instance" );
254 }
255
256 methodValue = instance[ options ].apply( instance, args );
257
258 if ( methodValue !== instance && methodValue !== undefined ) {
259 returnValue = methodValue && methodValue.jquery ?
260 returnValue.pushStack( methodValue.get() ) :
261 methodValue;
262 return false;
263 }
264 } );
265 }
266 } else {
267
268 // Allow multiple hashes to be passed on init
269 if ( args.length ) {
270 options = $.widget.extend.apply( null, [ options ].concat( args ) );
271 }
272
273 this.each( function() {
274 var instance = $.data( this, fullName );
275 if ( instance ) {
276 instance.option( options || {} );
277 if ( instance._init ) {
278 instance._init();
279 }
280 } else {
281 $.data( this, fullName, new object( options, this ) );
282 }
283 } );
284 }
285
286 return returnValue;
287 };
288};
289
290$.Widget = function( /* options, element */ ) {};
291$.Widget._childConstructors = [];
292
293$.Widget.prototype = {
294 widgetName: "widget",
295 widgetEventPrefix: "",
296 defaultElement: "<div>",
297
298 options: {
299 classes: {},
300 disabled: false,
301
302 // Callbacks
303 create: null
304 },
305
306 _createWidget: function( options, element ) {
307 element = $( element || this.defaultElement || this )[ 0 ];
308 this.element = $( element );
309 this.uuid = widgetUuid++;
310 this.eventNamespace = "." + this.widgetName + this.uuid;
311
312 this.bindings = $();
313 this.hoverable = $();
314 this.focusable = $();
315 this.classesElementLookup = {};
316
317 if ( element !== this ) {
318 $.data( element, this.widgetFullName, this );
319 this._on( true, this.element, {
320 remove: function( event ) {
321 if ( event.target === element ) {
322 this.destroy();
323 }
324 }
325 } );
326 this.document = $( element.style ?
327
328 // Element within the document
329 element.ownerDocument :
330
331 // Element is window or document
332 element.document || element );
333 this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
334 }
335
336 this.options = $.widget.extend( {},
337 this.options,
338 this._getCreateOptions(),
339 options );
340
341 this._create();
342
343 if ( this.options.disabled ) {
344 this._setOptionDisabled( this.options.disabled );
345 }
346
347 this._trigger( "create", null, this._getCreateEventData() );
348 this._init();
349 },
350
351 _getCreateOptions: function() {
352 return {};
353 },
354
355 _getCreateEventData: $.noop,
356
357 _create: $.noop,
358
359 _init: $.noop,
360
361 destroy: function() {
362 var that = this;
363
364 this._destroy();
365 $.each( this.classesElementLookup, function( key, value ) {
366 that._removeClass( value, key );
367 } );
368
369 // We can probably remove the unbind calls in 2.0
370 // all event bindings should go through this._on()
371 this.element
372 .off( this.eventNamespace )
373 .removeData( this.widgetFullName );
374 this.widget()
375 .off( this.eventNamespace )
376 .removeAttr( "aria-disabled" );
377
378 // Clean up events and states
379 this.bindings.off( this.eventNamespace );
380 },
381
382 _destroy: $.noop,
383
384 widget: function() {
385 return this.element;
386 },
387
388 option: function( key, value ) {
389 var options = key;
390 var parts;
391 var curOption;
392 var i;
393
394 if ( arguments.length === 0 ) {
395
396 // Don't return a reference to the internal hash
397 return $.widget.extend( {}, this.options );
398 }
399
400 if ( typeof key === "string" ) {
401
402 // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
403 options = {};
404 parts = key.split( "." );
405 key = parts.shift();
406 if ( parts.length ) {
407 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
408 for ( i = 0; i < parts.length - 1; i++ ) {
409 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
410 curOption = curOption[ parts[ i ] ];
411 }
412 key = parts.pop();
413 if ( arguments.length === 1 ) {
414 return curOption[ key ] === undefined ? null : curOption[ key ];
415 }
416 curOption[ key ] = value;
417 } else {
418 if ( arguments.length === 1 ) {
419 return this.options[ key ] === undefined ? null : this.options[ key ];
420 }
421 options[ key ] = value;
422 }
423 }
424
425 this._setOptions( options );
426
427 return this;
428 },
429
430 _setOptions: function( options ) {
431 var key;
432
433 for ( key in options ) {
434 this._setOption( key, options[ key ] );
435 }
436
437 return this;
438 },
439
440 _setOption: function( key, value ) {
441 if ( key === "classes" ) {
442 this._setOptionClasses( value );
443 }
444
445 this.options[ key ] = value;
446
447 if ( key === "disabled" ) {
448 this._setOptionDisabled( value );
449 }
450
451 return this;
452 },
453
454 _setOptionClasses: function( value ) {
455 var classKey, elements, currentElements;
456
457 for ( classKey in value ) {
458 currentElements = this.classesElementLookup[ classKey ];
459 if ( value[ classKey ] === this.options.classes[ classKey ] ||
460 !currentElements ||
461 !currentElements.length ) {
462 continue;
463 }
464
465 // We are doing this to create a new jQuery object because the _removeClass() call
466 // on the next line is going to destroy the reference to the current elements being
467 // tracked. We need to save a copy of this collection so that we can add the new classes
468 // below.
469 elements = $( currentElements.get() );
470 this._removeClass( currentElements, classKey );
471
472 // We don't use _addClass() here, because that uses this.options.classes
473 // for generating the string of classes. We want to use the value passed in from
474 // _setOption(), this is the new value of the classes option which was passed to
475 // _setOption(). We pass this value directly to _classes().
476 elements.addClass( this._classes( {
477 element: elements,
478 keys: classKey,
479 classes: value,
480 add: true
481 } ) );
482 }
483 },
484
485 _setOptionDisabled: function( value ) {
486 this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
487
488 // If the widget is becoming disabled, then nothing is interactive
489 if ( value ) {
490 this._removeClass( this.hoverable, null, "ui-state-hover" );
491 this._removeClass( this.focusable, null, "ui-state-focus" );
492 }
493 },
494
495 enable: function() {
496 return this._setOptions( { disabled: false } );
497 },
498
499 disable: function() {
500 return this._setOptions( { disabled: true } );
501 },
502
503 _classes: function( options ) {
504 var full = [];
505 var that = this;
506
507 options = $.extend( {
508 element: this.element,
509 classes: this.options.classes || {}
510 }, options );
511
512 function processClassString( classes, checkOption ) {
513 var current, i;
514 for ( i = 0; i < classes.length; i++ ) {
515 current = that.classesElementLookup[ classes[ i ] ] || $();
516 if ( options.add ) {
517 current = $( $.unique( current.get().concat( options.element.get() ) ) );
518 } else {
519 current = $( current.not( options.element ).get() );
520 }
521 that.classesElementLookup[ classes[ i ] ] = current;
522 full.push( classes[ i ] );
523 if ( checkOption && options.classes[ classes[ i ] ] ) {
524 full.push( options.classes[ classes[ i ] ] );
525 }
526 }
527 }
528
529 this._on( options.element, {
530 "remove": "_untrackClassesElement"
531 } );
532
533 if ( options.keys ) {
534 processClassString( options.keys.match( /\S+/g ) || [], true );
535 }
536 if ( options.extra ) {
537 processClassString( options.extra.match( /\S+/g ) || [] );
538 }
539
540 return full.join( " " );
541 },
542
543 _untrackClassesElement: function( event ) {
544 var that = this;
545 $.each( that.classesElementLookup, function( key, value ) {
546 if ( $.inArray( event.target, value ) !== -1 ) {
547 that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
548 }
549 } );
550 },
551
552 _removeClass: function( element, keys, extra ) {
553 return this._toggleClass( element, keys, extra, false );
554 },
555
556 _addClass: function( element, keys, extra ) {
557 return this._toggleClass( element, keys, extra, true );
558 },
559
560 _toggleClass: function( element, keys, extra, add ) {
561 add = ( typeof add === "boolean" ) ? add : extra;
562 var shift = ( typeof element === "string" || element === null ),
563 options = {
564 extra: shift ? keys : extra,
565 keys: shift ? element : keys,
566 element: shift ? this.element : element,
567 add: add
568 };
569 options.element.toggleClass( this._classes( options ), add );
570 return this;
571 },
572
573 _on: function( suppressDisabledCheck, element, handlers ) {
574 var delegateElement;
575 var instance = this;
576
577 // No suppressDisabledCheck flag, shuffle arguments
578 if ( typeof suppressDisabledCheck !== "boolean" ) {
579 handlers = element;
580 element = suppressDisabledCheck;
581 suppressDisabledCheck = false;
582 }
583
584 // No element argument, shuffle and use this.element
585 if ( !handlers ) {
586 handlers = element;
587 element = this.element;
588 delegateElement = this.widget();
589 } else {
590 element = delegateElement = $( element );
591 this.bindings = this.bindings.add( element );
592 }
593
594 $.each( handlers, function( event, handler ) {
595 function handlerProxy() {
596
597 // Allow widgets to customize the disabled handling
598 // - disabled as an array instead of boolean
599 // - disabled class as method for disabling individual parts
600 if ( !suppressDisabledCheck &&
601 ( instance.options.disabled === true ||
602 $( this ).hasClass( "ui-state-disabled" ) ) ) {
603 return;
604 }
605 return ( typeof handler === "string" ? instance[ handler ] : handler )
606 .apply( instance, arguments );
607 }
608
609 // Copy the guid so direct unbinding works
610 if ( typeof handler !== "string" ) {
611 handlerProxy.guid = handler.guid =
612 handler.guid || handlerProxy.guid || $.guid++;
613 }
614
615 var match = event.match( /^([\w:-]*)\s*(.*)$/ );
616 var eventName = match[ 1 ] + instance.eventNamespace;
617 var selector = match[ 2 ];
618
619 if ( selector ) {
620 delegateElement.on( eventName, selector, handlerProxy );
621 } else {
622 element.on( eventName, handlerProxy );
623 }
624 } );
625 },
626
627 _off: function( element, eventName ) {
628 eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
629 this.eventNamespace;
630 element.off( eventName ).off( eventName );
631
632 // Clear the stack to avoid memory leaks (#10056)
633 this.bindings = $( this.bindings.not( element ).get() );
634 this.focusable = $( this.focusable.not( element ).get() );
635 this.hoverable = $( this.hoverable.not( element ).get() );
636 },
637
638 _delay: function( handler, delay ) {
639 function handlerProxy() {
640 return ( typeof handler === "string" ? instance[ handler ] : handler )
641 .apply( instance, arguments );
642 }
643 var instance = this;
644 return setTimeout( handlerProxy, delay || 0 );
645 },
646
647 _hoverable: function( element ) {
648 this.hoverable = this.hoverable.add( element );
649 this._on( element, {
650 mouseenter: function( event ) {
651 this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
652 },
653 mouseleave: function( event ) {
654 this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
655 }
656 } );
657 },
658
659 _focusable: function( element ) {
660 this.focusable = this.focusable.add( element );
661 this._on( element, {
662 focusin: function( event ) {
663 this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
664 },
665 focusout: function( event ) {
666 this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
667 }
668 } );
669 },
670
671 _trigger: function( type, event, data ) {
672 var prop, orig;
673 var callback = this.options[ type ];
674
675 data = data || {};
676 event = $.Event( event );
677 event.type = ( type === this.widgetEventPrefix ?
678 type :
679 this.widgetEventPrefix + type ).toLowerCase();
680
681 // The original event may come from any element
682 // so we need to reset the target on the new event
683 event.target = this.element[ 0 ];
684
685 // Copy original event properties over to the new event
686 orig = event.originalEvent;
687 if ( orig ) {
688 for ( prop in orig ) {
689 if ( !( prop in event ) ) {
690 event[ prop ] = orig[ prop ];
691 }
692 }
693 }
694
695 this.element.trigger( event, data );
696 return !( $.isFunction( callback ) &&
697 callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
698 event.isDefaultPrevented() );
699 }
700};
701
702$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
703 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
704 if ( typeof options === "string" ) {
705 options = { effect: options };
706 }
707
708 var hasOptions;
709 var effectName = !options ?
710 method :
711 options === true || typeof options === "number" ?
712 defaultEffect :
713 options.effect || defaultEffect;
714
715 options = options || {};
716 if ( typeof options === "number" ) {
717 options = { duration: options };
718 }
719
720 hasOptions = !$.isEmptyObject( options );
721 options.complete = callback;
722
723 if ( options.delay ) {
724 element.delay( options.delay );
725 }
726
727 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
728 element[ method ]( options );
729 } else if ( effectName !== method && element[ effectName ] ) {
730 element[ effectName ]( options.duration, options.easing, callback );
731 } else {
732 element.queue( function( next ) {
733 $( this )[ method ]();
734 if ( callback ) {
735 callback.call( element[ 0 ] );
736 }
737 next();
738 } );
739 }
740 };
741} );
742
743var widget = $.widget;
744
745
746/*!
747 * jQuery UI Position 1.12.1
748 * http://jqueryui.com
749 *
750 * Copyright jQuery Foundation and other contributors
751 * Released under the MIT license.
752 * http://jquery.org/license
753 *
754 * http://api.jqueryui.com/position/
755 */
756
757//>>label: Position
758//>>group: Core
759//>>description: Positions elements relative to other elements.
760//>>docs: http://api.jqueryui.com/position/
761//>>demos: http://jqueryui.com/position/
762
763
764( function() {
765var cachedScrollbarWidth,
766 max = Math.max,
767 abs = Math.abs,
768 rhorizontal = /left|center|right/,
769 rvertical = /top|center|bottom/,
770 roffset = /[\+\-]\d+(\.[\d]+)?%?/,
771 rposition = /^\w+/,
772 rpercent = /%$/,
773 _position = $.fn.position;
774
775function getOffsets( offsets, width, height ) {
776 return [
777 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
778 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
779 ];
780}
781
782function parseCss( element, property ) {
783 return parseInt( $.css( element, property ), 10 ) || 0;
784}
785
786function getDimensions( elem ) {
787 var raw = elem[ 0 ];
788 if ( raw.nodeType === 9 ) {
789 return {
790 width: elem.width(),
791 height: elem.height(),
792 offset: { top: 0, left: 0 }
793 };
794 }
795 if ( $.isWindow( raw ) ) {
796 return {
797 width: elem.width(),
798 height: elem.height(),
799 offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
800 };
801 }
802 if ( raw.preventDefault ) {
803 return {
804 width: 0,
805 height: 0,
806 offset: { top: raw.pageY, left: raw.pageX }
807 };
808 }
809 return {
810 width: elem.outerWidth(),
811 height: elem.outerHeight(),
812 offset: elem.offset()
813 };
814}
815
816$.position = {
817 scrollbarWidth: function() {
818 if ( cachedScrollbarWidth !== undefined ) {
819 return cachedScrollbarWidth;
820 }
821 var w1, w2,
822 div = $( "<div " +
823 "style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'>" +
824 "<div style='height:100px;width:auto;'></div></div>" ),
825 innerDiv = div.children()[ 0 ];
826
827 $( "body" ).append( div );
828 w1 = innerDiv.offsetWidth;
829 div.css( "overflow", "scroll" );
830
831 w2 = innerDiv.offsetWidth;
832
833 if ( w1 === w2 ) {
834 w2 = div[ 0 ].clientWidth;
835 }
836
837 div.remove();
838
839 return ( cachedScrollbarWidth = w1 - w2 );
840 },
841 getScrollInfo: function( within ) {
842 var overflowX = within.isWindow || within.isDocument ? "" :
843 within.element.css( "overflow-x" ),
844 overflowY = within.isWindow || within.isDocument ? "" :
845 within.element.css( "overflow-y" ),
846 hasOverflowX = overflowX === "scroll" ||
847 ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
848 hasOverflowY = overflowY === "scroll" ||
849 ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
850 return {
851 width: hasOverflowY ? $.position.scrollbarWidth() : 0,
852 height: hasOverflowX ? $.position.scrollbarWidth() : 0
853 };
854 },
855 getWithinInfo: function( element ) {
856 var withinElement = $( element || window ),
857 isWindow = $.isWindow( withinElement[ 0 ] ),
858 isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
859 hasOffset = !isWindow && !isDocument;
860 return {
861 element: withinElement,
862 isWindow: isWindow,
863 isDocument: isDocument,
864 offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
865 scrollLeft: withinElement.scrollLeft(),
866 scrollTop: withinElement.scrollTop(),
867 width: withinElement.outerWidth(),
868 height: withinElement.outerHeight()
869 };
870 }
871};
872
873$.fn.position = function( options ) {
874 if ( !options || !options.of ) {
875 return _position.apply( this, arguments );
876 }
877
878 // Make a copy, we don't want to modify arguments
879 options = $.extend( {}, options );
880
881 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
882 target = $( options.of ),
883 within = $.position.getWithinInfo( options.within ),
884 scrollInfo = $.position.getScrollInfo( within ),
885 collision = ( options.collision || "flip" ).split( " " ),
886 offsets = {};
887
888 dimensions = getDimensions( target );
889 if ( target[ 0 ].preventDefault ) {
890
891 // Force left top to allow flipping
892 options.at = "left top";
893 }
894 targetWidth = dimensions.width;
895 targetHeight = dimensions.height;
896 targetOffset = dimensions.offset;
897
898 // Clone to reuse original targetOffset later
899 basePosition = $.extend( {}, targetOffset );
900
901 // Force my and at to have valid horizontal and vertical positions
902 // if a value is missing or invalid, it will be converted to center
903 $.each( [ "my", "at" ], function() {
904 var pos = ( options[ this ] || "" ).split( " " ),
905 horizontalOffset,
906 verticalOffset;
907
908 if ( pos.length === 1 ) {
909 pos = rhorizontal.test( pos[ 0 ] ) ?
910 pos.concat( [ "center" ] ) :
911 rvertical.test( pos[ 0 ] ) ?
912 [ "center" ].concat( pos ) :
913 [ "center", "center" ];
914 }
915 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
916 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
917
918 // Calculate offsets
919 horizontalOffset = roffset.exec( pos[ 0 ] );
920 verticalOffset = roffset.exec( pos[ 1 ] );
921 offsets[ this ] = [
922 horizontalOffset ? horizontalOffset[ 0 ] : 0,
923 verticalOffset ? verticalOffset[ 0 ] : 0
924 ];
925
926 // Reduce to just the positions without the offsets
927 options[ this ] = [
928 rposition.exec( pos[ 0 ] )[ 0 ],
929 rposition.exec( pos[ 1 ] )[ 0 ]
930 ];
931 } );
932
933 // Normalize collision option
934 if ( collision.length === 1 ) {
935 collision[ 1 ] = collision[ 0 ];
936 }
937
938 if ( options.at[ 0 ] === "right" ) {
939 basePosition.left += targetWidth;
940 } else if ( options.at[ 0 ] === "center" ) {
941 basePosition.left += targetWidth / 2;
942 }
943
944 if ( options.at[ 1 ] === "bottom" ) {
945 basePosition.top += targetHeight;
946 } else if ( options.at[ 1 ] === "center" ) {
947 basePosition.top += targetHeight / 2;
948 }
949
950 atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
951 basePosition.left += atOffset[ 0 ];
952 basePosition.top += atOffset[ 1 ];
953
954 return this.each( function() {
955 var collisionPosition, using,
956 elem = $( this ),
957 elemWidth = elem.outerWidth(),
958 elemHeight = elem.outerHeight(),
959 marginLeft = parseCss( this, "marginLeft" ),
960 marginTop = parseCss( this, "marginTop" ),
961 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
962 scrollInfo.width,
963 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
964 scrollInfo.height,
965 position = $.extend( {}, basePosition ),
966 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
967
968 if ( options.my[ 0 ] === "right" ) {
969 position.left -= elemWidth;
970 } else if ( options.my[ 0 ] === "center" ) {
971 position.left -= elemWidth / 2;
972 }
973
974 if ( options.my[ 1 ] === "bottom" ) {
975 position.top -= elemHeight;
976 } else if ( options.my[ 1 ] === "center" ) {
977 position.top -= elemHeight / 2;
978 }
979
980 position.left += myOffset[ 0 ];
981 position.top += myOffset[ 1 ];
982
983 collisionPosition = {
984 marginLeft: marginLeft,
985 marginTop: marginTop
986 };
987
988 $.each( [ "left", "top" ], function( i, dir ) {
989 if ( $.ui.position[ collision[ i ] ] ) {
990 $.ui.position[ collision[ i ] ][ dir ]( position, {
991 targetWidth: targetWidth,
992 targetHeight: targetHeight,
993 elemWidth: elemWidth,
994 elemHeight: elemHeight,
995 collisionPosition: collisionPosition,
996 collisionWidth: collisionWidth,
997 collisionHeight: collisionHeight,
998 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
999 my: options.my,
1000 at: options.at,
1001 within: within,
1002 elem: elem
1003 } );
1004 }
1005 } );
1006
1007 if ( options.using ) {
1008
1009 // Adds feedback as second argument to using callback, if present
1010 using = function( props ) {
1011 var left = targetOffset.left - position.left,
1012 right = left + targetWidth - elemWidth,
1013 top = targetOffset.top - position.top,
1014 bottom = top + targetHeight - elemHeight,
1015 feedback = {
1016 target: {
1017 element: target,
1018 left: targetOffset.left,
1019 top: targetOffset.top,
1020 width: targetWidth,
1021 height: targetHeight
1022 },
1023 element: {
1024 element: elem,
1025 left: position.left,
1026 top: position.top,
1027 width: elemWidth,
1028 height: elemHeight
1029 },
1030 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1031 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1032 };
1033 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1034 feedback.horizontal = "center";
1035 }
1036 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1037 feedback.vertical = "middle";
1038 }
1039 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1040 feedback.important = "horizontal";
1041 } else {
1042 feedback.important = "vertical";
1043 }
1044 options.using.call( this, props, feedback );
1045 };
1046 }
1047
1048 elem.offset( $.extend( position, { using: using } ) );
1049 } );
1050};
1051
1052$.ui.position = {
1053 fit: {
1054 left: function( position, data ) {
1055 var within = data.within,
1056 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1057 outerWidth = within.width,
1058 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1059 overLeft = withinOffset - collisionPosLeft,
1060 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1061 newOverRight;
1062
1063 // Element is wider than within
1064 if ( data.collisionWidth > outerWidth ) {
1065
1066 // Element is initially over the left side of within
1067 if ( overLeft > 0 && overRight <= 0 ) {
1068 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
1069 withinOffset;
1070 position.left += overLeft - newOverRight;
1071
1072 // Element is initially over right side of within
1073 } else if ( overRight > 0 && overLeft <= 0 ) {
1074 position.left = withinOffset;
1075
1076 // Element is initially over both left and right sides of within
1077 } else {
1078 if ( overLeft > overRight ) {
1079 position.left = withinOffset + outerWidth - data.collisionWidth;
1080 } else {
1081 position.left = withinOffset;
1082 }
1083 }
1084
1085 // Too far left -> align with left edge
1086 } else if ( overLeft > 0 ) {
1087 position.left += overLeft;
1088
1089 // Too far right -> align with right edge
1090 } else if ( overRight > 0 ) {
1091 position.left -= overRight;
1092
1093 // Adjust based on position and margin
1094 } else {
1095 position.left = max( position.left - collisionPosLeft, position.left );
1096 }
1097 },
1098 top: function( position, data ) {
1099 var within = data.within,
1100 withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1101 outerHeight = data.within.height,
1102 collisionPosTop = position.top - data.collisionPosition.marginTop,
1103 overTop = withinOffset - collisionPosTop,
1104 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1105 newOverBottom;
1106
1107 // Element is taller than within
1108 if ( data.collisionHeight > outerHeight ) {
1109
1110 // Element is initially over the top of within
1111 if ( overTop > 0 && overBottom <= 0 ) {
1112 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
1113 withinOffset;
1114 position.top += overTop - newOverBottom;
1115
1116 // Element is initially over bottom of within
1117 } else if ( overBottom > 0 && overTop <= 0 ) {
1118 position.top = withinOffset;
1119
1120 // Element is initially over both top and bottom of within
1121 } else {
1122 if ( overTop > overBottom ) {
1123 position.top = withinOffset + outerHeight - data.collisionHeight;
1124 } else {
1125 position.top = withinOffset;
1126 }
1127 }
1128
1129 // Too far up -> align with top
1130 } else if ( overTop > 0 ) {
1131 position.top += overTop;
1132
1133 // Too far down -> align with bottom edge
1134 } else if ( overBottom > 0 ) {
1135 position.top -= overBottom;
1136
1137 // Adjust based on position and margin
1138 } else {
1139 position.top = max( position.top - collisionPosTop, position.top );
1140 }
1141 }
1142 },
1143 flip: {
1144 left: function( position, data ) {
1145 var within = data.within,
1146 withinOffset = within.offset.left + within.scrollLeft,
1147 outerWidth = within.width,
1148 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1149 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1150 overLeft = collisionPosLeft - offsetLeft,
1151 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1152 myOffset = data.my[ 0 ] === "left" ?
1153 -data.elemWidth :
1154 data.my[ 0 ] === "right" ?
1155 data.elemWidth :
1156 0,
1157 atOffset = data.at[ 0 ] === "left" ?
1158 data.targetWidth :
1159 data.at[ 0 ] === "right" ?
1160 -data.targetWidth :
1161 0,
1162 offset = -2 * data.offset[ 0 ],
1163 newOverRight,
1164 newOverLeft;
1165
1166 if ( overLeft < 0 ) {
1167 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
1168 outerWidth - withinOffset;
1169 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1170 position.left += myOffset + atOffset + offset;
1171 }
1172 } else if ( overRight > 0 ) {
1173 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
1174 atOffset + offset - offsetLeft;
1175 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1176 position.left += myOffset + atOffset + offset;
1177 }
1178 }
1179 },
1180 top: function( position, data ) {
1181 var within = data.within,
1182 withinOffset = within.offset.top + within.scrollTop,
1183 outerHeight = within.height,
1184 offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1185 collisionPosTop = position.top - data.collisionPosition.marginTop,
1186 overTop = collisionPosTop - offsetTop,
1187 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1188 top = data.my[ 1 ] === "top",
1189 myOffset = top ?
1190 -data.elemHeight :
1191 data.my[ 1 ] === "bottom" ?
1192 data.elemHeight :
1193 0,
1194 atOffset = data.at[ 1 ] === "top" ?
1195 data.targetHeight :
1196 data.at[ 1 ] === "bottom" ?
1197 -data.targetHeight :
1198 0,
1199 offset = -2 * data.offset[ 1 ],
1200 newOverTop,
1201 newOverBottom;
1202 if ( overTop < 0 ) {
1203 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
1204 outerHeight - withinOffset;
1205 if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1206 position.top += myOffset + atOffset + offset;
1207 }
1208 } else if ( overBottom > 0 ) {
1209 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
1210 offset - offsetTop;
1211 if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1212 position.top += myOffset + atOffset + offset;
1213 }
1214 }
1215 }
1216 },
1217 flipfit: {
1218 left: function() {
1219 $.ui.position.flip.left.apply( this, arguments );
1220 $.ui.position.fit.left.apply( this, arguments );
1221 },
1222 top: function() {
1223 $.ui.position.flip.top.apply( this, arguments );
1224 $.ui.position.fit.top.apply( this, arguments );
1225 }
1226 }
1227};
1228
1229} )();
1230
1231var position = $.ui.position;
1232
1233
1234/*!
1235 * jQuery UI :data 1.12.1
1236 * http://jqueryui.com
1237 *
1238 * Copyright jQuery Foundation and other contributors
1239 * Released under the MIT license.
1240 * http://jquery.org/license
1241 */
1242
1243//>>label: :data Selector
1244//>>group: Core
1245//>>description: Selects elements which have data stored under the specified key.
1246//>>docs: http://api.jqueryui.com/data-selector/
1247
1248
1249var data = $.extend( $.expr[ ":" ], {
1250 data: $.expr.createPseudo ?
1251 $.expr.createPseudo( function( dataName ) {
1252 return function( elem ) {
1253 return !!$.data( elem, dataName );
1254 };
1255 } ) :
1256
1257 // Support: jQuery <1.8
1258 function( elem, i, match ) {
1259 return !!$.data( elem, match[ 3 ] );
1260 }
1261} );
1262
1263/*!
1264 * jQuery UI Disable Selection 1.12.1
1265 * http://jqueryui.com
1266 *
1267 * Copyright jQuery Foundation and other contributors
1268 * Released under the MIT license.
1269 * http://jquery.org/license
1270 */
1271
1272//>>label: disableSelection
1273//>>group: Core
1274//>>description: Disable selection of text content within the set of matched elements.
1275//>>docs: http://api.jqueryui.com/disableSelection/
1276
1277// This file is deprecated
1278
1279
1280var disableSelection = $.fn.extend( {
1281 disableSelection: ( function() {
1282 var eventType = "onselectstart" in document.createElement( "div" ) ?
1283 "selectstart" :
1284 "mousedown";
1285
1286 return function() {
1287 return this.on( eventType + ".ui-disableSelection", function( event ) {
1288 event.preventDefault();
1289 } );
1290 };
1291 } )(),
1292
1293 enableSelection: function() {
1294 return this.off( ".ui-disableSelection" );
1295 }
1296} );
1297
1298
1299/*!
1300 * jQuery UI Effects 1.12.1
1301 * http://jqueryui.com
1302 *
1303 * Copyright jQuery Foundation and other contributors
1304 * Released under the MIT license.
1305 * http://jquery.org/license
1306 */
1307
1308//>>label: Effects Core
1309//>>group: Effects
1310// jscs:disable maximumLineLength
1311//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.
1312// jscs:enable maximumLineLength
1313//>>docs: http://api.jqueryui.com/category/effects-core/
1314//>>demos: http://jqueryui.com/effect/
1315
1316
1317
1318var dataSpace = "ui-effects-",
1319 dataSpaceStyle = "ui-effects-style",
1320 dataSpaceAnimated = "ui-effects-animated",
1321
1322 // Create a local jQuery because jQuery Color relies on it and the
1323 // global may not exist with AMD and a custom build (#10199)
1324 jQuery = $;
1325
1326$.effects = {
1327 effect: {}
1328};
1329
1330/*!
1331 * jQuery Color Animations v2.1.2
1332 * https://github.com/jquery/jquery-color
1333 *
1334 * Copyright 2014 jQuery Foundation and other contributors
1335 * Released under the MIT license.
1336 * http://jquery.org/license
1337 *
1338 * Date: Wed Jan 16 08:47:09 2013 -0600
1339 */
1340( function( jQuery, undefined ) {
1341
1342 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " +
1343 "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
1344
1345 // Plusequals test for += 100 -= 100
1346 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
1347
1348 // A set of RE's that can match strings and generate color tuples.
1349 stringParsers = [ {
1350 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1351 parse: function( execResult ) {
1352 return [
1353 execResult[ 1 ],
1354 execResult[ 2 ],
1355 execResult[ 3 ],
1356 execResult[ 4 ]
1357 ];
1358 }
1359 }, {
1360 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1361 parse: function( execResult ) {
1362 return [
1363 execResult[ 1 ] * 2.55,
1364 execResult[ 2 ] * 2.55,
1365 execResult[ 3 ] * 2.55,
1366 execResult[ 4 ]
1367 ];
1368 }
1369 }, {
1370
1371 // This regex ignores A-F because it's compared against an already lowercased string
1372 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
1373 parse: function( execResult ) {
1374 return [
1375 parseInt( execResult[ 1 ], 16 ),
1376 parseInt( execResult[ 2 ], 16 ),
1377 parseInt( execResult[ 3 ], 16 )
1378 ];
1379 }
1380 }, {
1381
1382 // This regex ignores A-F because it's compared against an already lowercased string
1383 re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
1384 parse: function( execResult ) {
1385 return [
1386 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
1387 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
1388 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
1389 ];
1390 }
1391 }, {
1392 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1393 space: "hsla",
1394 parse: function( execResult ) {
1395 return [
1396 execResult[ 1 ],
1397 execResult[ 2 ] / 100,
1398 execResult[ 3 ] / 100,
1399 execResult[ 4 ]
1400 ];
1401 }
1402 } ],
1403
1404 // JQuery.Color( )
1405 color = jQuery.Color = function( color, green, blue, alpha ) {
1406 return new jQuery.Color.fn.parse( color, green, blue, alpha );
1407 },
1408 spaces = {
1409 rgba: {
1410 props: {
1411 red: {
1412 idx: 0,
1413 type: "byte"
1414 },
1415 green: {
1416 idx: 1,
1417 type: "byte"
1418 },
1419 blue: {
1420 idx: 2,
1421 type: "byte"
1422 }
1423 }
1424 },
1425
1426 hsla: {
1427 props: {
1428 hue: {
1429 idx: 0,
1430 type: "degrees"
1431 },
1432 saturation: {
1433 idx: 1,
1434 type: "percent"
1435 },
1436 lightness: {
1437 idx: 2,
1438 type: "percent"
1439 }
1440 }
1441 }
1442 },
1443 propTypes = {
1444 "byte": {
1445 floor: true,
1446 max: 255
1447 },
1448 "percent": {
1449 max: 1
1450 },
1451 "degrees": {
1452 mod: 360,
1453 floor: true
1454 }
1455 },
1456 support = color.support = {},
1457
1458 // Element for support tests
1459 supportElem = jQuery( "<p>" )[ 0 ],
1460
1461 // Colors = jQuery.Color.names
1462 colors,
1463
1464 // Local aliases of functions called often
1465 each = jQuery.each;
1466
1467// Determine rgba support immediately
1468supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
1469support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
1470
1471// Define cache name and alpha properties
1472// for rgba and hsla spaces
1473each( spaces, function( spaceName, space ) {
1474 space.cache = "_" + spaceName;
1475 space.props.alpha = {
1476 idx: 3,
1477 type: "percent",
1478 def: 1
1479 };
1480} );
1481
1482function clamp( value, prop, allowEmpty ) {
1483 var type = propTypes[ prop.type ] || {};
1484
1485 if ( value == null ) {
1486 return ( allowEmpty || !prop.def ) ? null : prop.def;
1487 }
1488
1489 // ~~ is an short way of doing floor for positive numbers
1490 value = type.floor ? ~~value : parseFloat( value );
1491
1492 // IE will pass in empty strings as value for alpha,
1493 // which will hit this case
1494 if ( isNaN( value ) ) {
1495 return prop.def;
1496 }
1497
1498 if ( type.mod ) {
1499
1500 // We add mod before modding to make sure that negatives values
1501 // get converted properly: -10 -> 350
1502 return ( value + type.mod ) % type.mod;
1503 }
1504
1505 // For now all property types without mod have min and max
1506 return 0 > value ? 0 : type.max < value ? type.max : value;
1507}
1508
1509function stringParse( string ) {
1510 var inst = color(),
1511 rgba = inst._rgba = [];
1512
1513 string = string.toLowerCase();
1514
1515 each( stringParsers, function( i, parser ) {
1516 var parsed,
1517 match = parser.re.exec( string ),
1518 values = match && parser.parse( match ),
1519 spaceName = parser.space || "rgba";
1520
1521 if ( values ) {
1522 parsed = inst[ spaceName ]( values );
1523
1524 // If this was an rgba parse the assignment might happen twice
1525 // oh well....
1526 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
1527 rgba = inst._rgba = parsed._rgba;
1528
1529 // Exit each( stringParsers ) here because we matched
1530 return false;
1531 }
1532 } );
1533
1534 // Found a stringParser that handled it
1535 if ( rgba.length ) {
1536
1537 // If this came from a parsed string, force "transparent" when alpha is 0
1538 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
1539 if ( rgba.join() === "0,0,0,0" ) {
1540 jQuery.extend( rgba, colors.transparent );
1541 }
1542 return inst;
1543 }
1544
1545 // Named colors
1546 return colors[ string ];
1547}
1548
1549color.fn = jQuery.extend( color.prototype, {
1550 parse: function( red, green, blue, alpha ) {
1551 if ( red === undefined ) {
1552 this._rgba = [ null, null, null, null ];
1553 return this;
1554 }
1555 if ( red.jquery || red.nodeType ) {
1556 red = jQuery( red ).css( green );
1557 green = undefined;
1558 }
1559
1560 var inst = this,
1561 type = jQuery.type( red ),
1562 rgba = this._rgba = [];
1563
1564 // More than 1 argument specified - assume ( red, green, blue, alpha )
1565 if ( green !== undefined ) {
1566 red = [ red, green, blue, alpha ];
1567 type = "array";
1568 }
1569
1570 if ( type === "string" ) {
1571 return this.parse( stringParse( red ) || colors._default );
1572 }
1573
1574 if ( type === "array" ) {
1575 each( spaces.rgba.props, function( key, prop ) {
1576 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
1577 } );
1578 return this;
1579 }
1580
1581 if ( type === "object" ) {
1582 if ( red instanceof color ) {
1583 each( spaces, function( spaceName, space ) {
1584 if ( red[ space.cache ] ) {
1585 inst[ space.cache ] = red[ space.cache ].slice();
1586 }
1587 } );
1588 } else {
1589 each( spaces, function( spaceName, space ) {
1590 var cache = space.cache;
1591 each( space.props, function( key, prop ) {
1592
1593 // If the cache doesn't exist, and we know how to convert
1594 if ( !inst[ cache ] && space.to ) {
1595
1596 // If the value was null, we don't need to copy it
1597 // if the key was alpha, we don't need to copy it either
1598 if ( key === "alpha" || red[ key ] == null ) {
1599 return;
1600 }
1601 inst[ cache ] = space.to( inst._rgba );
1602 }
1603
1604 // This is the only case where we allow nulls for ALL properties.
1605 // call clamp with alwaysAllowEmpty
1606 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
1607 } );
1608
1609 // Everything defined but alpha?
1610 if ( inst[ cache ] &&
1611 jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
1612
1613 // Use the default of 1
1614 inst[ cache ][ 3 ] = 1;
1615 if ( space.from ) {
1616 inst._rgba = space.from( inst[ cache ] );
1617 }
1618 }
1619 } );
1620 }
1621 return this;
1622 }
1623 },
1624 is: function( compare ) {
1625 var is = color( compare ),
1626 same = true,
1627 inst = this;
1628
1629 each( spaces, function( _, space ) {
1630 var localCache,
1631 isCache = is[ space.cache ];
1632 if ( isCache ) {
1633 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
1634 each( space.props, function( _, prop ) {
1635 if ( isCache[ prop.idx ] != null ) {
1636 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
1637 return same;
1638 }
1639 } );
1640 }
1641 return same;
1642 } );
1643 return same;
1644 },
1645 _space: function() {
1646 var used = [],
1647 inst = this;
1648 each( spaces, function( spaceName, space ) {
1649 if ( inst[ space.cache ] ) {
1650 used.push( spaceName );
1651 }
1652 } );
1653 return used.pop();
1654 },
1655 transition: function( other, distance ) {
1656 var end = color( other ),
1657 spaceName = end._space(),
1658 space = spaces[ spaceName ],
1659 startColor = this.alpha() === 0 ? color( "transparent" ) : this,
1660 start = startColor[ space.cache ] || space.to( startColor._rgba ),
1661 result = start.slice();
1662
1663 end = end[ space.cache ];
1664 each( space.props, function( key, prop ) {
1665 var index = prop.idx,
1666 startValue = start[ index ],
1667 endValue = end[ index ],
1668 type = propTypes[ prop.type ] || {};
1669
1670 // If null, don't override start value
1671 if ( endValue === null ) {
1672 return;
1673 }
1674
1675 // If null - use end
1676 if ( startValue === null ) {
1677 result[ index ] = endValue;
1678 } else {
1679 if ( type.mod ) {
1680 if ( endValue - startValue > type.mod / 2 ) {
1681 startValue += type.mod;
1682 } else if ( startValue - endValue > type.mod / 2 ) {
1683 startValue -= type.mod;
1684 }
1685 }
1686 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
1687 }
1688 } );
1689 return this[ spaceName ]( result );
1690 },
1691 blend: function( opaque ) {
1692
1693 // If we are already opaque - return ourself
1694 if ( this._rgba[ 3 ] === 1 ) {
1695 return this;
1696 }
1697
1698 var rgb = this._rgba.slice(),
1699 a = rgb.pop(),
1700 blend = color( opaque )._rgba;
1701
1702 return color( jQuery.map( rgb, function( v, i ) {
1703 return ( 1 - a ) * blend[ i ] + a * v;
1704 } ) );
1705 },
1706 toRgbaString: function() {
1707 var prefix = "rgba(",
1708 rgba = jQuery.map( this._rgba, function( v, i ) {
1709 return v == null ? ( i > 2 ? 1 : 0 ) : v;
1710 } );
1711
1712 if ( rgba[ 3 ] === 1 ) {
1713 rgba.pop();
1714 prefix = "rgb(";
1715 }
1716
1717 return prefix + rgba.join() + ")";
1718 },
1719 toHslaString: function() {
1720 var prefix = "hsla(",
1721 hsla = jQuery.map( this.hsla(), function( v, i ) {
1722 if ( v == null ) {
1723 v = i > 2 ? 1 : 0;
1724 }
1725
1726 // Catch 1 and 2
1727 if ( i && i < 3 ) {
1728 v = Math.round( v * 100 ) + "%";
1729 }
1730 return v;
1731 } );
1732
1733 if ( hsla[ 3 ] === 1 ) {
1734 hsla.pop();
1735 prefix = "hsl(";
1736 }
1737 return prefix + hsla.join() + ")";
1738 },
1739 toHexString: function( includeAlpha ) {
1740 var rgba = this._rgba.slice(),
1741 alpha = rgba.pop();
1742
1743 if ( includeAlpha ) {
1744 rgba.push( ~~( alpha * 255 ) );
1745 }
1746
1747 return "#" + jQuery.map( rgba, function( v ) {
1748
1749 // Default to 0 when nulls exist
1750 v = ( v || 0 ).toString( 16 );
1751 return v.length === 1 ? "0" + v : v;
1752 } ).join( "" );
1753 },
1754 toString: function() {
1755 return this._rgba[ 3 ] === 0 ? "transparent