]> git.immae.eu Git - github/shaarli/Shaarli.git/blame - inc/jquery-ui-1.11.2.js
fix broken URL for user.css
[github/shaarli/Shaarli.git] / inc / jquery-ui-1.11.2.js
CommitLineData
8e0ad1d9 1/*! jQuery UI - v1.11.2 - 2014-10-16
2* http://jqueryui.com
3* Includes: core.js, widget.js, mouse.js, position.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, draggable.js, droppable.js, effect.js, effect-blind.js, effect-bounce.js, effect-clip.js, effect-drop.js, effect-explode.js, effect-fade.js, effect-fold.js, effect-highlight.js, effect-puff.js, effect-pulsate.js, effect-scale.js, effect-shake.js, effect-size.js, effect-slide.js, effect-transfer.js, menu.js, progressbar.js, resizable.js, selectable.js, selectmenu.js, slider.js, sortable.js, spinner.js, tabs.js, tooltip.js
4* Copyright 2014 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 * jQuery UI Core 1.11.2
19 * http://jqueryui.com
20 *
21 * Copyright 2014 jQuery Foundation and other contributors
22 * Released under the MIT license.
23 * http://jquery.org/license
24 *
25 * http://api.jqueryui.com/category/ui-core/
26 */
27
28
29// $.ui might exist from components with no dependencies, e.g., $.ui.position
30$.ui = $.ui || {};
31
32$.extend( $.ui, {
33 version: "1.11.2",
34
35 keyCode: {
36 BACKSPACE: 8,
37 COMMA: 188,
38 DELETE: 46,
39 DOWN: 40,
40 END: 35,
41 ENTER: 13,
42 ESCAPE: 27,
43 HOME: 36,
44 LEFT: 37,
45 PAGE_DOWN: 34,
46 PAGE_UP: 33,
47 PERIOD: 190,
48 RIGHT: 39,
49 SPACE: 32,
50 TAB: 9,
51 UP: 38
52 }
53});
54
55// plugins
56$.fn.extend({
57 scrollParent: function( includeHidden ) {
58 var position = this.css( "position" ),
59 excludeStaticParent = position === "absolute",
60 overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
61 scrollParent = this.parents().filter( function() {
62 var parent = $( this );
63 if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
64 return false;
65 }
66 return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + parent.css( "overflow-x" ) );
67 }).eq( 0 );
68
69 return position === "fixed" || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent;
70 },
71
72 uniqueId: (function() {
73 var uuid = 0;
74
75 return function() {
76 return this.each(function() {
77 if ( !this.id ) {
78 this.id = "ui-id-" + ( ++uuid );
79 }
80 });
81 };
82 })(),
83
84 removeUniqueId: function() {
85 return this.each(function() {
86 if ( /^ui-id-\d+$/.test( this.id ) ) {
87 $( this ).removeAttr( "id" );
88 }
89 });
90 }
91});
92
93// selectors
94function focusable( element, isTabIndexNotNaN ) {
95 var map, mapName, img,
96 nodeName = element.nodeName.toLowerCase();
97 if ( "area" === nodeName ) {
98 map = element.parentNode;
99 mapName = map.name;
100 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
101 return false;
102 }
103 img = $( "img[usemap='#" + mapName + "']" )[ 0 ];
104 return !!img && visible( img );
105 }
106 return ( /input|select|textarea|button|object/.test( nodeName ) ?
107 !element.disabled :
108 "a" === nodeName ?
109 element.href || isTabIndexNotNaN :
110 isTabIndexNotNaN) &&
111 // the element and all of its ancestors must be visible
112 visible( element );
113}
114
115function visible( element ) {
116 return $.expr.filters.visible( element ) &&
117 !$( element ).parents().addBack().filter(function() {
118 return $.css( this, "visibility" ) === "hidden";
119 }).length;
120}
121
122$.extend( $.expr[ ":" ], {
123 data: $.expr.createPseudo ?
124 $.expr.createPseudo(function( dataName ) {
125 return function( elem ) {
126 return !!$.data( elem, dataName );
127 };
128 }) :
129 // support: jQuery <1.8
130 function( elem, i, match ) {
131 return !!$.data( elem, match[ 3 ] );
132 },
133
134 focusable: function( element ) {
135 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
136 },
137
138 tabbable: function( element ) {
139 var tabIndex = $.attr( element, "tabindex" ),
140 isTabIndexNaN = isNaN( tabIndex );
141 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
142 }
143});
144
145// support: jQuery <1.8
146if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
147 $.each( [ "Width", "Height" ], function( i, name ) {
148 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
149 type = name.toLowerCase(),
150 orig = {
151 innerWidth: $.fn.innerWidth,
152 innerHeight: $.fn.innerHeight,
153 outerWidth: $.fn.outerWidth,
154 outerHeight: $.fn.outerHeight
155 };
156
157 function reduce( elem, size, border, margin ) {
158 $.each( side, function() {
159 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
160 if ( border ) {
161 size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
162 }
163 if ( margin ) {
164 size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
165 }
166 });
167 return size;
168 }
169
170 $.fn[ "inner" + name ] = function( size ) {
171 if ( size === undefined ) {
172 return orig[ "inner" + name ].call( this );
173 }
174
175 return this.each(function() {
176 $( this ).css( type, reduce( this, size ) + "px" );
177 });
178 };
179
180 $.fn[ "outer" + name] = function( size, margin ) {
181 if ( typeof size !== "number" ) {
182 return orig[ "outer" + name ].call( this, size );
183 }
184
185 return this.each(function() {
186 $( this).css( type, reduce( this, size, true, margin ) + "px" );
187 });
188 };
189 });
190}
191
192// support: jQuery <1.8
193if ( !$.fn.addBack ) {
194 $.fn.addBack = function( selector ) {
195 return this.add( selector == null ?
196 this.prevObject : this.prevObject.filter( selector )
197 );
198 };
199}
200
201// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
202if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
203 $.fn.removeData = (function( removeData ) {
204 return function( key ) {
205 if ( arguments.length ) {
206 return removeData.call( this, $.camelCase( key ) );
207 } else {
208 return removeData.call( this );
209 }
210 };
211 })( $.fn.removeData );
212}
213
214// deprecated
215$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
216
217$.fn.extend({
218 focus: (function( orig ) {
219 return function( delay, fn ) {
220 return typeof delay === "number" ?
221 this.each(function() {
222 var elem = this;
223 setTimeout(function() {
224 $( elem ).focus();
225 if ( fn ) {
226 fn.call( elem );
227 }
228 }, delay );
229 }) :
230 orig.apply( this, arguments );
231 };
232 })( $.fn.focus ),
233
234 disableSelection: (function() {
235 var eventType = "onselectstart" in document.createElement( "div" ) ?
236 "selectstart" :
237 "mousedown";
238
239 return function() {
240 return this.bind( eventType + ".ui-disableSelection", function( event ) {
241 event.preventDefault();
242 });
243 };
244 })(),
245
246 enableSelection: function() {
247 return this.unbind( ".ui-disableSelection" );
248 },
249
250 zIndex: function( zIndex ) {
251 if ( zIndex !== undefined ) {
252 return this.css( "zIndex", zIndex );
253 }
254
255 if ( this.length ) {
256 var elem = $( this[ 0 ] ), position, value;
257 while ( elem.length && elem[ 0 ] !== document ) {
258 // Ignore z-index if position is set to a value where z-index is ignored by the browser
259 // This makes behavior of this function consistent across browsers
260 // WebKit always returns auto if the element is positioned
261 position = elem.css( "position" );
262 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
263 // IE returns 0 when zIndex is not specified
264 // other browsers return a string
265 // we ignore the case of nested elements with an explicit value of 0
266 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
267 value = parseInt( elem.css( "zIndex" ), 10 );
268 if ( !isNaN( value ) && value !== 0 ) {
269 return value;
270 }
271 }
272 elem = elem.parent();
273 }
274 }
275
276 return 0;
277 }
278});
279
280// $.ui.plugin is deprecated. Use $.widget() extensions instead.
281$.ui.plugin = {
282 add: function( module, option, set ) {
283 var i,
284 proto = $.ui[ module ].prototype;
285 for ( i in set ) {
286 proto.plugins[ i ] = proto.plugins[ i ] || [];
287 proto.plugins[ i ].push( [ option, set[ i ] ] );
288 }
289 },
290 call: function( instance, name, args, allowDisconnected ) {
291 var i,
292 set = instance.plugins[ name ];
293
294 if ( !set ) {
295 return;
296 }
297
298 if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
299 return;
300 }
301
302 for ( i = 0; i < set.length; i++ ) {
303 if ( instance.options[ set[ i ][ 0 ] ] ) {
304 set[ i ][ 1 ].apply( instance.element, args );
305 }
306 }
307 }
308};
309
310
311/*!
312 * jQuery UI Widget 1.11.2
313 * http://jqueryui.com
314 *
315 * Copyright 2014 jQuery Foundation and other contributors
316 * Released under the MIT license.
317 * http://jquery.org/license
318 *
319 * http://api.jqueryui.com/jQuery.widget/
320 */
321
322
323var widget_uuid = 0,
324 widget_slice = Array.prototype.slice;
325
326$.cleanData = (function( orig ) {
327 return function( elems ) {
328 var events, elem, i;
329 for ( i = 0; (elem = elems[i]) != null; i++ ) {
330 try {
331
332 // Only trigger remove when necessary to save time
333 events = $._data( elem, "events" );
334 if ( events && events.remove ) {
335 $( elem ).triggerHandler( "remove" );
336 }
337
338 // http://bugs.jquery.com/ticket/8235
339 } catch ( e ) {}
340 }
341 orig( elems );
342 };
343})( $.cleanData );
344
345$.widget = function( name, base, prototype ) {
346 var fullName, existingConstructor, constructor, basePrototype,
347 // proxiedPrototype allows the provided prototype to remain unmodified
348 // so that it can be used as a mixin for multiple widgets (#8876)
349 proxiedPrototype = {},
350 namespace = name.split( "." )[ 0 ];
351
352 name = name.split( "." )[ 1 ];
353 fullName = namespace + "-" + name;
354
355 if ( !prototype ) {
356 prototype = base;
357 base = $.Widget;
358 }
359
360 // create selector for plugin
361 $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
362 return !!$.data( elem, fullName );
363 };
364
365 $[ namespace ] = $[ namespace ] || {};
366 existingConstructor = $[ namespace ][ name ];
367 constructor = $[ namespace ][ name ] = function( options, element ) {
368 // allow instantiation without "new" keyword
369 if ( !this._createWidget ) {
370 return new constructor( options, element );
371 }
372
373 // allow instantiation without initializing for simple inheritance
374 // must use "new" keyword (the code above always passes args)
375 if ( arguments.length ) {
376 this._createWidget( options, element );
377 }
378 };
379 // extend with the existing constructor to carry over any static properties
380 $.extend( constructor, existingConstructor, {
381 version: prototype.version,
382 // copy the object used to create the prototype in case we need to
383 // redefine the widget later
384 _proto: $.extend( {}, prototype ),
385 // track widgets that inherit from this widget in case this widget is
386 // redefined after a widget inherits from it
387 _childConstructors: []
388 });
389
390 basePrototype = new base();
391 // we need to make the options hash a property directly on the new instance
392 // otherwise we'll modify the options hash on the prototype that we're
393 // inheriting from
394 basePrototype.options = $.widget.extend( {}, basePrototype.options );
395 $.each( prototype, function( prop, value ) {
396 if ( !$.isFunction( value ) ) {
397 proxiedPrototype[ prop ] = value;
398 return;
399 }
400 proxiedPrototype[ prop ] = (function() {
401 var _super = function() {
402 return base.prototype[ prop ].apply( this, arguments );
403 },
404 _superApply = function( args ) {
405 return base.prototype[ prop ].apply( this, args );
406 };
407 return function() {
408 var __super = this._super,
409 __superApply = this._superApply,
410 returnValue;
411
412 this._super = _super;
413 this._superApply = _superApply;
414
415 returnValue = value.apply( this, arguments );
416
417 this._super = __super;
418 this._superApply = __superApply;
419
420 return returnValue;
421 };
422 })();
423 });
424 constructor.prototype = $.widget.extend( basePrototype, {
425 // TODO: remove support for widgetEventPrefix
426 // always use the name + a colon as the prefix, e.g., draggable:start
427 // don't prefix for widgets that aren't DOM-based
428 widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
429 }, proxiedPrototype, {
430 constructor: constructor,
431 namespace: namespace,
432 widgetName: name,
433 widgetFullName: fullName
434 });
435
436 // If this widget is being redefined then we need to find all widgets that
437 // are inheriting from it and redefine all of them so that they inherit from
438 // the new version of this widget. We're essentially trying to replace one
439 // level in the prototype chain.
440 if ( existingConstructor ) {
441 $.each( existingConstructor._childConstructors, function( i, child ) {
442 var childPrototype = child.prototype;
443
444 // redefine the child widget using the same prototype that was
445 // originally used, but inherit from the new version of the base
446 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
447 });
448 // remove the list of existing child constructors from the old constructor
449 // so the old child constructors can be garbage collected
450 delete existingConstructor._childConstructors;
451 } else {
452 base._childConstructors.push( constructor );
453 }
454
455 $.widget.bridge( name, constructor );
456
457 return constructor;
458};
459
460$.widget.extend = function( target ) {
461 var input = widget_slice.call( arguments, 1 ),
462 inputIndex = 0,
463 inputLength = input.length,
464 key,
465 value;
466 for ( ; inputIndex < inputLength; inputIndex++ ) {
467 for ( key in input[ inputIndex ] ) {
468 value = input[ inputIndex ][ key ];
469 if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
470 // Clone objects
471 if ( $.isPlainObject( value ) ) {
472 target[ key ] = $.isPlainObject( target[ key ] ) ?
473 $.widget.extend( {}, target[ key ], value ) :
474 // Don't extend strings, arrays, etc. with objects
475 $.widget.extend( {}, value );
476 // Copy everything else by reference
477 } else {
478 target[ key ] = value;
479 }
480 }
481 }
482 }
483 return target;
484};
485
486$.widget.bridge = function( name, object ) {
487 var fullName = object.prototype.widgetFullName || name;
488 $.fn[ name ] = function( options ) {
489 var isMethodCall = typeof options === "string",
490 args = widget_slice.call( arguments, 1 ),
491 returnValue = this;
492
493 // allow multiple hashes to be passed on init
494 options = !isMethodCall && args.length ?
495 $.widget.extend.apply( null, [ options ].concat(args) ) :
496 options;
497
498 if ( isMethodCall ) {
499 this.each(function() {
500 var methodValue,
501 instance = $.data( this, fullName );
502 if ( options === "instance" ) {
503 returnValue = instance;
504 return false;
505 }
506 if ( !instance ) {
507 return $.error( "cannot call methods on " + name + " prior to initialization; " +
508 "attempted to call method '" + options + "'" );
509 }
510 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
511 return $.error( "no such method '" + options + "' for " + name + " widget instance" );
512 }
513 methodValue = instance[ options ].apply( instance, args );
514 if ( methodValue !== instance && methodValue !== undefined ) {
515 returnValue = methodValue && methodValue.jquery ?
516 returnValue.pushStack( methodValue.get() ) :
517 methodValue;
518 return false;
519 }
520 });
521 } else {
522 this.each(function() {
523 var instance = $.data( this, fullName );
524 if ( instance ) {
525 instance.option( options || {} );
526 if ( instance._init ) {
527 instance._init();
528 }
529 } else {
530 $.data( this, fullName, new object( options, this ) );
531 }
532 });
533 }
534
535 return returnValue;
536 };
537};
538
539$.Widget = function( /* options, element */ ) {};
540$.Widget._childConstructors = [];
541
542$.Widget.prototype = {
543 widgetName: "widget",
544 widgetEventPrefix: "",
545 defaultElement: "<div>",
546 options: {
547 disabled: false,
548
549 // callbacks
550 create: null
551 },
552 _createWidget: function( options, element ) {
553 element = $( element || this.defaultElement || this )[ 0 ];
554 this.element = $( element );
555 this.uuid = widget_uuid++;
556 this.eventNamespace = "." + this.widgetName + this.uuid;
557
558 this.bindings = $();
559 this.hoverable = $();
560 this.focusable = $();
561
562 if ( element !== this ) {
563 $.data( element, this.widgetFullName, this );
564 this._on( true, this.element, {
565 remove: function( event ) {
566 if ( event.target === element ) {
567 this.destroy();
568 }
569 }
570 });
571 this.document = $( element.style ?
572 // element within the document
573 element.ownerDocument :
574 // element is window or document
575 element.document || element );
576 this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
577 }
578
579 this.options = $.widget.extend( {},
580 this.options,
581 this._getCreateOptions(),
582 options );
583
584 this._create();
585 this._trigger( "create", null, this._getCreateEventData() );
586 this._init();
587 },
588 _getCreateOptions: $.noop,
589 _getCreateEventData: $.noop,
590 _create: $.noop,
591 _init: $.noop,
592
593 destroy: function() {
594 this._destroy();
595 // we can probably remove the unbind calls in 2.0
596 // all event bindings should go through this._on()
597 this.element
598 .unbind( this.eventNamespace )
599 .removeData( this.widgetFullName )
600 // support: jquery <1.6.3
601 // http://bugs.jquery.com/ticket/9413
602 .removeData( $.camelCase( this.widgetFullName ) );
603 this.widget()
604 .unbind( this.eventNamespace )
605 .removeAttr( "aria-disabled" )
606 .removeClass(
607 this.widgetFullName + "-disabled " +
608 "ui-state-disabled" );
609
610 // clean up events and states
611 this.bindings.unbind( this.eventNamespace );
612 this.hoverable.removeClass( "ui-state-hover" );
613 this.focusable.removeClass( "ui-state-focus" );
614 },
615 _destroy: $.noop,
616
617 widget: function() {
618 return this.element;
619 },
620
621 option: function( key, value ) {
622 var options = key,
623 parts,
624 curOption,
625 i;
626
627 if ( arguments.length === 0 ) {
628 // don't return a reference to the internal hash
629 return $.widget.extend( {}, this.options );
630 }
631
632 if ( typeof key === "string" ) {
633 // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
634 options = {};
635 parts = key.split( "." );
636 key = parts.shift();
637 if ( parts.length ) {
638 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
639 for ( i = 0; i < parts.length - 1; i++ ) {
640 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
641 curOption = curOption[ parts[ i ] ];
642 }
643 key = parts.pop();
644 if ( arguments.length === 1 ) {
645 return curOption[ key ] === undefined ? null : curOption[ key ];
646 }
647 curOption[ key ] = value;
648 } else {
649 if ( arguments.length === 1 ) {
650 return this.options[ key ] === undefined ? null : this.options[ key ];
651 }
652 options[ key ] = value;
653 }
654 }
655
656 this._setOptions( options );
657
658 return this;
659 },
660 _setOptions: function( options ) {
661 var key;
662
663 for ( key in options ) {
664 this._setOption( key, options[ key ] );
665 }
666
667 return this;
668 },
669 _setOption: function( key, value ) {
670 this.options[ key ] = value;
671
672 if ( key === "disabled" ) {
673 this.widget()
674 .toggleClass( this.widgetFullName + "-disabled", !!value );
675
676 // If the widget is becoming disabled, then nothing is interactive
677 if ( value ) {
678 this.hoverable.removeClass( "ui-state-hover" );
679 this.focusable.removeClass( "ui-state-focus" );
680 }
681 }
682
683 return this;
684 },
685
686 enable: function() {
687 return this._setOptions({ disabled: false });
688 },
689 disable: function() {
690 return this._setOptions({ disabled: true });
691 },
692
693 _on: function( suppressDisabledCheck, element, handlers ) {
694 var delegateElement,
695 instance = this;
696
697 // no suppressDisabledCheck flag, shuffle arguments
698 if ( typeof suppressDisabledCheck !== "boolean" ) {
699 handlers = element;
700 element = suppressDisabledCheck;
701 suppressDisabledCheck = false;
702 }
703
704 // no element argument, shuffle and use this.element
705 if ( !handlers ) {
706 handlers = element;
707 element = this.element;
708 delegateElement = this.widget();
709 } else {
710 element = delegateElement = $( element );
711 this.bindings = this.bindings.add( element );
712 }
713
714 $.each( handlers, function( event, handler ) {
715 function handlerProxy() {
716 // allow widgets to customize the disabled handling
717 // - disabled as an array instead of boolean
718 // - disabled class as method for disabling individual parts
719 if ( !suppressDisabledCheck &&
720 ( instance.options.disabled === true ||
721 $( this ).hasClass( "ui-state-disabled" ) ) ) {
722 return;
723 }
724 return ( typeof handler === "string" ? instance[ handler ] : handler )
725 .apply( instance, arguments );
726 }
727
728 // copy the guid so direct unbinding works
729 if ( typeof handler !== "string" ) {
730 handlerProxy.guid = handler.guid =
731 handler.guid || handlerProxy.guid || $.guid++;
732 }
733
734 var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
735 eventName = match[1] + instance.eventNamespace,
736 selector = match[2];
737 if ( selector ) {
738 delegateElement.delegate( selector, eventName, handlerProxy );
739 } else {
740 element.bind( eventName, handlerProxy );
741 }
742 });
743 },
744
745 _off: function( element, eventName ) {
746 eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) +
747 this.eventNamespace;
748 element.unbind( eventName ).undelegate( eventName );
749
750 // Clear the stack to avoid memory leaks (#10056)
751 this.bindings = $( this.bindings.not( element ).get() );
752 this.focusable = $( this.focusable.not( element ).get() );
753 this.hoverable = $( this.hoverable.not( element ).get() );
754 },
755
756 _delay: function( handler, delay ) {
757 function handlerProxy() {
758 return ( typeof handler === "string" ? instance[ handler ] : handler )
759 .apply( instance, arguments );
760 }
761 var instance = this;
762 return setTimeout( handlerProxy, delay || 0 );
763 },
764
765 _hoverable: function( element ) {
766 this.hoverable = this.hoverable.add( element );
767 this._on( element, {
768 mouseenter: function( event ) {
769 $( event.currentTarget ).addClass( "ui-state-hover" );
770 },
771 mouseleave: function( event ) {
772 $( event.currentTarget ).removeClass( "ui-state-hover" );
773 }
774 });
775 },
776
777 _focusable: function( element ) {
778 this.focusable = this.focusable.add( element );
779 this._on( element, {
780 focusin: function( event ) {
781 $( event.currentTarget ).addClass( "ui-state-focus" );
782 },
783 focusout: function( event ) {
784 $( event.currentTarget ).removeClass( "ui-state-focus" );
785 }
786 });
787 },
788
789 _trigger: function( type, event, data ) {
790 var prop, orig,
791 callback = this.options[ type ];
792
793 data = data || {};
794 event = $.Event( event );
795 event.type = ( type === this.widgetEventPrefix ?
796 type :
797 this.widgetEventPrefix + type ).toLowerCase();
798 // the original event may come from any element
799 // so we need to reset the target on the new event
800 event.target = this.element[ 0 ];
801
802 // copy original event properties over to the new event
803 orig = event.originalEvent;
804 if ( orig ) {
805 for ( prop in orig ) {
806 if ( !( prop in event ) ) {
807 event[ prop ] = orig[ prop ];
808 }
809 }
810 }
811
812 this.element.trigger( event, data );
813 return !( $.isFunction( callback ) &&
814 callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
815 event.isDefaultPrevented() );
816 }
817};
818
819$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
820 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
821 if ( typeof options === "string" ) {
822 options = { effect: options };
823 }
824 var hasOptions,
825 effectName = !options ?
826 method :
827 options === true || typeof options === "number" ?
828 defaultEffect :
829 options.effect || defaultEffect;
830 options = options || {};
831 if ( typeof options === "number" ) {
832 options = { duration: options };
833 }
834 hasOptions = !$.isEmptyObject( options );
835 options.complete = callback;
836 if ( options.delay ) {
837 element.delay( options.delay );
838 }
839 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
840 element[ method ]( options );
841 } else if ( effectName !== method && element[ effectName ] ) {
842 element[ effectName ]( options.duration, options.easing, callback );
843 } else {
844 element.queue(function( next ) {
845 $( this )[ method ]();
846 if ( callback ) {
847 callback.call( element[ 0 ] );
848 }
849 next();
850 });
851 }
852 };
853});
854
855var widget = $.widget;
856
857
858/*!
859 * jQuery UI Mouse 1.11.2
860 * http://jqueryui.com
861 *
862 * Copyright 2014 jQuery Foundation and other contributors
863 * Released under the MIT license.
864 * http://jquery.org/license
865 *
866 * http://api.jqueryui.com/mouse/
867 */
868
869
870var mouseHandled = false;
871$( document ).mouseup( function() {
872 mouseHandled = false;
873});
874
875var mouse = $.widget("ui.mouse", {
876 version: "1.11.2",
877 options: {
878 cancel: "input,textarea,button,select,option",
879 distance: 1,
880 delay: 0
881 },
882 _mouseInit: function() {
883 var that = this;
884
885 this.element
886 .bind("mousedown." + this.widgetName, function(event) {
887 return that._mouseDown(event);
888 })
889 .bind("click." + this.widgetName, function(event) {
890 if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
891 $.removeData(event.target, that.widgetName + ".preventClickEvent");
892 event.stopImmediatePropagation();
893 return false;
894 }
895 });
896
897 this.started = false;
898 },
899
900 // TODO: make sure destroying one instance of mouse doesn't mess with
901 // other instances of mouse
902 _mouseDestroy: function() {
903 this.element.unbind("." + this.widgetName);
904 if ( this._mouseMoveDelegate ) {
905 this.document
906 .unbind("mousemove." + this.widgetName, this._mouseMoveDelegate)
907 .unbind("mouseup." + this.widgetName, this._mouseUpDelegate);
908 }
909 },
910
911 _mouseDown: function(event) {
912 // don't let more than one widget handle mouseStart
913 if ( mouseHandled ) {
914 return;
915 }
916
917 this._mouseMoved = false;
918
919 // we may have missed mouseup (out of window)
920 (this._mouseStarted && this._mouseUp(event));
921
922 this._mouseDownEvent = event;
923
924 var that = this,
925 btnIsLeft = (event.which === 1),
926 // event.target.nodeName works around a bug in IE 8 with
927 // disabled inputs (#7620)
928 elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
929 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
930 return true;
931 }
932
933 this.mouseDelayMet = !this.options.delay;
934 if (!this.mouseDelayMet) {
935 this._mouseDelayTimer = setTimeout(function() {
936 that.mouseDelayMet = true;
937 }, this.options.delay);
938 }
939
940 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
941 this._mouseStarted = (this._mouseStart(event) !== false);
942 if (!this._mouseStarted) {
943 event.preventDefault();
944 return true;
945 }
946 }
947
948 // Click event may never have fired (Gecko & Opera)
949 if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
950 $.removeData(event.target, this.widgetName + ".preventClickEvent");
951 }
952
953 // these delegates are required to keep context
954 this._mouseMoveDelegate = function(event) {
955 return that._mouseMove(event);
956 };
957 this._mouseUpDelegate = function(event) {
958 return that._mouseUp(event);
959 };
960
961 this.document
962 .bind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
963 .bind( "mouseup." + this.widgetName, this._mouseUpDelegate );
964
965 event.preventDefault();
966
967 mouseHandled = true;
968 return true;
969 },
970
971 _mouseMove: function(event) {
972 // Only check for mouseups outside the document if you've moved inside the document
973 // at least once. This prevents the firing of mouseup in the case of IE<9, which will
974 // fire a mousemove event if content is placed under the cursor. See #7778
975 // Support: IE <9
976 if ( this._mouseMoved ) {
977 // IE mouseup check - mouseup happened when mouse was out of window
978 if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
979 return this._mouseUp(event);
980
981 // Iframe mouseup check - mouseup occurred in another document
982 } else if ( !event.which ) {
983 return this._mouseUp( event );
984 }
985 }
986
987 if ( event.which || event.button ) {
988 this._mouseMoved = true;
989 }
990
991 if (this._mouseStarted) {
992 this._mouseDrag(event);
993 return event.preventDefault();
994 }
995
996 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
997 this._mouseStarted =
998 (this._mouseStart(this._mouseDownEvent, event) !== false);
999 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
1000 }
1001
1002 return !this._mouseStarted;
1003 },
1004
1005 _mouseUp: function(event) {
1006 this.document
1007 .unbind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
1008 .unbind( "mouseup." + this.widgetName, this._mouseUpDelegate );
1009
1010 if (this._mouseStarted) {
1011 this._mouseStarted = false;
1012
1013 if (event.target === this._mouseDownEvent.target) {
1014 $.data(event.target, this.widgetName + ".preventClickEvent", true);
1015 }
1016
1017 this._mouseStop(event);
1018 }
1019
1020 mouseHandled = false;
1021 return false;
1022 },
1023
1024 _mouseDistanceMet: function(event) {
1025 return (Math.max(
1026 Math.abs(this._mouseDownEvent.pageX - event.pageX),
1027 Math.abs(this._mouseDownEvent.pageY - event.pageY)
1028 ) >= this.options.distance
1029 );
1030 },
1031
1032 _mouseDelayMet: function(/* event */) {
1033 return this.mouseDelayMet;
1034 },
1035
1036 // These are placeholder methods, to be overriden by extending plugin
1037 _mouseStart: function(/* event */) {},
1038 _mouseDrag: function(/* event */) {},
1039 _mouseStop: function(/* event */) {},
1040 _mouseCapture: function(/* event */) { return true; }
1041});
1042
1043
1044/*!
1045 * jQuery UI Position 1.11.2
1046 * http://jqueryui.com
1047 *
1048 * Copyright 2014 jQuery Foundation and other contributors
1049 * Released under the MIT license.
1050 * http://jquery.org/license
1051 *
1052 * http://api.jqueryui.com/position/
1053 */
1054
1055(function() {
1056
1057$.ui = $.ui || {};
1058
1059var cachedScrollbarWidth, supportsOffsetFractions,
1060 max = Math.max,
1061 abs = Math.abs,
1062 round = Math.round,
1063 rhorizontal = /left|center|right/,
1064 rvertical = /top|center|bottom/,
1065 roffset = /[\+\-]\d+(\.[\d]+)?%?/,
1066 rposition = /^\w+/,
1067 rpercent = /%$/,
1068 _position = $.fn.position;
1069
1070function getOffsets( offsets, width, height ) {
1071 return [
1072 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
1073 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
1074 ];
1075}
1076
1077function parseCss( element, property ) {
1078 return parseInt( $.css( element, property ), 10 ) || 0;
1079}
1080
1081function getDimensions( elem ) {
1082 var raw = elem[0];
1083 if ( raw.nodeType === 9 ) {
1084 return {
1085 width: elem.width(),
1086 height: elem.height(),
1087 offset: { top: 0, left: 0 }
1088 };
1089 }
1090 if ( $.isWindow( raw ) ) {
1091 return {
1092 width: elem.width(),
1093 height: elem.height(),
1094 offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
1095 };
1096 }
1097 if ( raw.preventDefault ) {
1098 return {
1099 width: 0,
1100 height: 0,
1101 offset: { top: raw.pageY, left: raw.pageX }
1102 };
1103 }
1104 return {
1105 width: elem.outerWidth(),
1106 height: elem.outerHeight(),
1107 offset: elem.offset()
1108 };
1109}
1110
1111$.position = {
1112 scrollbarWidth: function() {
1113 if ( cachedScrollbarWidth !== undefined ) {
1114 return cachedScrollbarWidth;
1115 }
1116 var w1, w2,
1117 div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
1118 innerDiv = div.children()[0];
1119
1120 $( "body" ).append( div );
1121 w1 = innerDiv.offsetWidth;
1122 div.css( "overflow", "scroll" );
1123
1124 w2 = innerDiv.offsetWidth;
1125
1126 if ( w1 === w2 ) {
1127 w2 = div[0].clientWidth;
1128 }
1129
1130 div.remove();
1131
1132 return (cachedScrollbarWidth = w1 - w2);
1133 },
1134 getScrollInfo: function( within ) {
1135 var overflowX = within.isWindow || within.isDocument ? "" :
1136 within.element.css( "overflow-x" ),
1137 overflowY = within.isWindow || within.isDocument ? "" :
1138 within.element.css( "overflow-y" ),
1139 hasOverflowX = overflowX === "scroll" ||
1140 ( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
1141 hasOverflowY = overflowY === "scroll" ||
1142 ( overflowY === "auto" && within.height < within.element[0].scrollHeight );
1143 return {
1144 width: hasOverflowY ? $.position.scrollbarWidth() : 0,
1145 height: hasOverflowX ? $.position.scrollbarWidth() : 0
1146 };
1147 },
1148 getWithinInfo: function( element ) {
1149 var withinElement = $( element || window ),
1150 isWindow = $.isWindow( withinElement[0] ),
1151 isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9;
1152 return {
1153 element: withinElement,
1154 isWindow: isWindow,
1155 isDocument: isDocument,
1156 offset: withinElement.offset() || { left: 0, top: 0 },
1157 scrollLeft: withinElement.scrollLeft(),
1158 scrollTop: withinElement.scrollTop(),
1159
1160 // support: jQuery 1.6.x
1161 // jQuery 1.6 doesn't support .outerWidth/Height() on documents or windows
1162 width: isWindow || isDocument ? withinElement.width() : withinElement.outerWidth(),
1163 height: isWindow || isDocument ? withinElement.height() : withinElement.outerHeight()
1164 };
1165 }
1166};
1167
1168$.fn.position = function( options ) {
1169 if ( !options || !options.of ) {
1170 return _position.apply( this, arguments );
1171 }
1172
1173 // make a copy, we don't want to modify arguments
1174 options = $.extend( {}, options );
1175
1176 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
1177 target = $( options.of ),
1178 within = $.position.getWithinInfo( options.within ),
1179 scrollInfo = $.position.getScrollInfo( within ),
1180 collision = ( options.collision || "flip" ).split( " " ),
1181 offsets = {};
1182
1183 dimensions = getDimensions( target );
1184 if ( target[0].preventDefault ) {
1185 // force left top to allow flipping
1186 options.at = "left top";
1187 }
1188 targetWidth = dimensions.width;
1189 targetHeight = dimensions.height;
1190 targetOffset = dimensions.offset;
1191 // clone to reuse original targetOffset later
1192 basePosition = $.extend( {}, targetOffset );
1193
1194 // force my and at to have valid horizontal and vertical positions
1195 // if a value is missing or invalid, it will be converted to center
1196 $.each( [ "my", "at" ], function() {
1197 var pos = ( options[ this ] || "" ).split( " " ),
1198 horizontalOffset,
1199 verticalOffset;
1200
1201 if ( pos.length === 1) {
1202 pos = rhorizontal.test( pos[ 0 ] ) ?
1203 pos.concat( [ "center" ] ) :
1204 rvertical.test( pos[ 0 ] ) ?
1205 [ "center" ].concat( pos ) :
1206 [ "center", "center" ];
1207 }
1208 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
1209 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
1210
1211 // calculate offsets
1212 horizontalOffset = roffset.exec( pos[ 0 ] );
1213 verticalOffset = roffset.exec( pos[ 1 ] );
1214 offsets[ this ] = [
1215 horizontalOffset ? horizontalOffset[ 0 ] : 0,
1216 verticalOffset ? verticalOffset[ 0 ] : 0
1217 ];
1218
1219 // reduce to just the positions without the offsets
1220 options[ this ] = [
1221 rposition.exec( pos[ 0 ] )[ 0 ],
1222 rposition.exec( pos[ 1 ] )[ 0 ]
1223 ];
1224 });
1225
1226 // normalize collision option
1227 if ( collision.length === 1 ) {
1228 collision[ 1 ] = collision[ 0 ];
1229 }
1230
1231 if ( options.at[ 0 ] === "right" ) {
1232 basePosition.left += targetWidth;
1233 } else if ( options.at[ 0 ] === "center" ) {
1234 basePosition.left += targetWidth / 2;
1235 }
1236
1237 if ( options.at[ 1 ] === "bottom" ) {
1238 basePosition.top += targetHeight;
1239 } else if ( options.at[ 1 ] === "center" ) {
1240 basePosition.top += targetHeight / 2;
1241 }
1242
1243 atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
1244 basePosition.left += atOffset[ 0 ];
1245 basePosition.top += atOffset[ 1 ];
1246
1247 return this.each(function() {
1248 var collisionPosition, using,
1249 elem = $( this ),
1250 elemWidth = elem.outerWidth(),
1251 elemHeight = elem.outerHeight(),
1252 marginLeft = parseCss( this, "marginLeft" ),
1253 marginTop = parseCss( this, "marginTop" ),
1254 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
1255 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
1256 position = $.extend( {}, basePosition ),
1257 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
1258
1259 if ( options.my[ 0 ] === "right" ) {
1260 position.left -= elemWidth;
1261 } else if ( options.my[ 0 ] === "center" ) {
1262 position.left -= elemWidth / 2;
1263 }
1264
1265 if ( options.my[ 1 ] === "bottom" ) {
1266 position.top -= elemHeight;
1267 } else if ( options.my[ 1 ] === "center" ) {
1268 position.top -= elemHeight / 2;
1269 }
1270
1271 position.left += myOffset[ 0 ];
1272 position.top += myOffset[ 1 ];
1273
1274 // if the browser doesn't support fractions, then round for consistent results
1275 if ( !supportsOffsetFractions ) {
1276 position.left = round( position.left );
1277 position.top = round( position.top );
1278 }
1279
1280 collisionPosition = {
1281 marginLeft: marginLeft,
1282 marginTop: marginTop
1283 };
1284
1285 $.each( [ "left", "top" ], function( i, dir ) {
1286 if ( $.ui.position[ collision[ i ] ] ) {
1287 $.ui.position[ collision[ i ] ][ dir ]( position, {
1288 targetWidth: targetWidth,
1289 targetHeight: targetHeight,
1290 elemWidth: elemWidth,
1291 elemHeight: elemHeight,
1292 collisionPosition: collisionPosition,
1293 collisionWidth: collisionWidth,
1294 collisionHeight: collisionHeight,
1295 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1296 my: options.my,
1297 at: options.at,
1298 within: within,
1299 elem: elem
1300 });
1301 }
1302 });
1303
1304 if ( options.using ) {
1305 // adds feedback as second argument to using callback, if present
1306 using = function( props ) {
1307 var left = targetOffset.left - position.left,
1308 right = left + targetWidth - elemWidth,
1309 top = targetOffset.top - position.top,
1310 bottom = top + targetHeight - elemHeight,
1311 feedback = {
1312 target: {
1313 element: target,
1314 left: targetOffset.left,
1315 top: targetOffset.top,
1316 width: targetWidth,
1317 height: targetHeight
1318 },
1319 element: {
1320 element: elem,
1321 left: position.left,
1322 top: position.top,
1323 width: elemWidth,
1324 height: elemHeight
1325 },
1326 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1327 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1328 };
1329 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1330 feedback.horizontal = "center";
1331 }
1332 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1333 feedback.vertical = "middle";
1334 }
1335 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1336 feedback.important = "horizontal";
1337 } else {
1338 feedback.important = "vertical";
1339 }
1340 options.using.call( this, props, feedback );
1341 };
1342 }
1343
1344 elem.offset( $.extend( position, { using: using } ) );
1345 });
1346};
1347
1348$.ui.position = {
1349 fit: {
1350 left: function( position, data ) {
1351 var within = data.within,
1352 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1353 outerWidth = within.width,
1354 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1355 overLeft = withinOffset - collisionPosLeft,
1356 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1357 newOverRight;
1358
1359 // element is wider than within
1360 if ( data.collisionWidth > outerWidth ) {
1361 // element is initially over the left side of within
1362 if ( overLeft > 0 && overRight <= 0 ) {
1363 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
1364 position.left += overLeft - newOverRight;
1365 // element is initially over right side of within
1366 } else if ( overRight > 0 && overLeft <= 0 ) {
1367 position.left = withinOffset;
1368 // element is initially over both left and right sides of within
1369 } else {
1370 if ( overLeft > overRight ) {
1371 position.left = withinOffset + outerWidth - data.collisionWidth;
1372 } else {
1373 position.left = withinOffset;
1374 }
1375 }
1376 // too far left -> align with left edge
1377 } else if ( overLeft > 0 ) {
1378 position.left += overLeft;
1379 // too far right -> align with right edge
1380 } else if ( overRight > 0 ) {
1381 position.left -= overRight;
1382 // adjust based on position and margin
1383 } else {
1384 position.left = max( position.left - collisionPosLeft, position.left );
1385 }
1386 },
1387 top: function( position, data ) {
1388 var within = data.within,
1389 withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1390 outerHeight = data.within.height,
1391 collisionPosTop = position.top - data.collisionPosition.marginTop,
1392 overTop = withinOffset - collisionPosTop,
1393 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1394 newOverBottom;
1395
1396 // element is taller than within
1397 if ( data.collisionHeight > outerHeight ) {
1398 // element is initially over the top of within
1399 if ( overTop > 0 && overBottom <= 0 ) {
1400 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
1401 position.top += overTop - newOverBottom;
1402 // element is initially over bottom of within
1403 } else if ( overBottom > 0 && overTop <= 0 ) {
1404 position.top = withinOffset;
1405 // element is initially over both top and bottom of within
1406 } else {
1407 if ( overTop > overBottom ) {
1408 position.top = withinOffset + outerHeight - data.collisionHeight;
1409 } else {
1410 position.top = withinOffset;
1411 }
1412 }
1413 // too far up -> align with top
1414 } else if ( overTop > 0 ) {
1415 position.top += overTop;
1416 // too far down -> align with bottom edge
1417 } else if ( overBottom > 0 ) {
1418 position.top -= overBottom;
1419 // adjust based on position and margin
1420 } else {
1421 position.top = max( position.top - collisionPosTop, position.top );
1422 }
1423 }
1424 },
1425 flip: {
1426 left: function( position, data ) {
1427 var within = data.within,
1428 withinOffset = within.offset.left + within.scrollLeft,
1429 outerWidth = within.width,
1430 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1431 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1432 overLeft = collisionPosLeft - offsetLeft,
1433 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1434 myOffset = data.my[ 0 ] === "left" ?
1435 -data.elemWidth :
1436 data.my[ 0 ] === "right" ?
1437 data.elemWidth :
1438 0,
1439 atOffset = data.at[ 0 ] === "left" ?
1440 data.targetWidth :
1441 data.at[ 0 ] === "right" ?
1442 -data.targetWidth :
1443 0,
1444 offset = -2 * data.offset[ 0 ],
1445 newOverRight,
1446 newOverLeft;
1447
1448 if ( overLeft < 0 ) {
1449 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
1450 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1451 position.left += myOffset + atOffset + offset;
1452 }
1453 } else if ( overRight > 0 ) {
1454 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
1455 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1456 position.left += myOffset + atOffset + offset;
1457 }
1458 }
1459 },
1460 top: function( position, data ) {
1461 var within = data.within,
1462 withinOffset = within.offset.top + within.scrollTop,
1463 outerHeight = within.height,
1464 offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1465 collisionPosTop = position.top - data.collisionPosition.marginTop,
1466 overTop = collisionPosTop - offsetTop,
1467 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1468 top = data.my[ 1 ] === "top",
1469 myOffset = top ?
1470 -data.elemHeight :
1471 data.my[ 1 ] === "bottom" ?
1472 data.elemHeight :
1473 0,
1474 atOffset = data.at[ 1 ] === "top" ?
1475 data.targetHeight :
1476 data.at[ 1 ] === "bottom" ?
1477 -data.targetHeight :
1478 0,
1479 offset = -2 * data.offset[ 1 ],
1480 newOverTop,
1481 newOverBottom;
1482 if ( overTop < 0 ) {
1483 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
1484 if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
1485 position.top += myOffset + atOffset + offset;
1486 }
1487 } else if ( overBottom > 0 ) {
1488 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
1489 if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
1490 position.top += myOffset + atOffset + offset;
1491 }
1492 }
1493 }
1494 },
1495 flipfit: {
1496 left: function() {
1497 $.ui.position.flip.left.apply( this, arguments );
1498 $.ui.position.fit.left.apply( this, arguments );
1499 },
1500 top: function() {
1501 $.ui.position.flip.top.apply( this, arguments );
1502 $.ui.position.fit.top.apply( this, arguments );
1503 }
1504 }
1505};
1506
1507// fraction support test
1508(function() {
1509 var testElement, testElementParent, testElementStyle, offsetLeft, i,
1510 body = document.getElementsByTagName( "body" )[ 0 ],
1511 div = document.createElement( "div" );
1512
1513 //Create a "fake body" for testing based on method used in jQuery.support
1514 testElement = document.createElement( body ? "div" : "body" );
1515 testElementStyle = {
1516 visibility: "hidden",
1517 width: 0,
1518 height: 0,
1519 border: 0,
1520 margin: 0,
1521 background: "none"
1522 };
1523 if ( body ) {
1524 $.extend( testElementStyle, {
1525 position: "absolute",
1526 left: "-1000px",
1527 top: "-1000px"
1528 });
1529 }
1530 for ( i in testElementStyle ) {
1531 testElement.style[ i ] = testElementStyle[ i ];
1532 }
1533 testElement.appendChild( div );
1534 testElementParent = body || document.documentElement;
1535 testElementParent.insertBefore( testElement, testElementParent.firstChild );
1536
1537 div.style.cssText = "position: absolute; left: 10.7432222px;";
1538
1539 offsetLeft = $( div ).offset().left;
1540 supportsOffsetFractions = offsetLeft > 10 && offsetLeft < 11;
1541
1542 testElement.innerHTML = "";
1543 testElementParent.removeChild( testElement );
1544})();
1545
1546})();
1547
1548var position = $.ui.position;
1549
1550
1551/*!
1552 * jQuery UI Accordion 1.11.2
1553 * http://jqueryui.com
1554 *
1555 * Copyright 2014 jQuery Foundation and other contributors
1556 * Released under the MIT license.
1557 * http://jquery.org/license
1558 *
1559 * http://api.jqueryui.com/accordion/
1560 */
1561
1562
1563var accordion = $.widget( "ui.accordion", {
1564 version: "1.11.2",
1565 options: {
1566 active: 0,
1567 animate: {},
1568 collapsible: false,
1569 event: "click",
1570 header: "> li > :first-child,> :not(li):even",
1571 heightStyle: "auto",
1572 icons: {
1573 activeHeader: "ui-icon-triangle-1-s",
1574 header: "ui-icon-triangle-1-e"
1575 },
1576
1577 // callbacks
1578 activate: null,
1579 beforeActivate: null
1580 },
1581
1582 hideProps: {
1583 borderTopWidth: "hide",
1584 borderBottomWidth: "hide",
1585 paddingTop: "hide",
1586 paddingBottom: "hide",
1587 height: "hide"
1588 },
1589
1590 showProps: {
1591 borderTopWidth: "show",
1592 borderBottomWidth: "show",
1593 paddingTop: "show",
1594 paddingBottom: "show",
1595 height: "show"
1596 },
1597
1598 _create: function() {
1599 var options = this.options;
1600 this.prevShow = this.prevHide = $();
1601 this.element.addClass( "ui-accordion ui-widget ui-helper-reset" )
1602 // ARIA
1603 .attr( "role", "tablist" );
1604
1605 // don't allow collapsible: false and active: false / null
1606 if ( !options.collapsible && (options.active === false || options.active == null) ) {
1607 options.active = 0;
1608 }
1609
1610 this._processPanels();
1611 // handle negative values
1612 if ( options.active < 0 ) {
1613 options.active += this.headers.length;
1614 }
1615 this._refresh();
1616 },
1617
1618 _getCreateEventData: function() {
1619 return {
1620 header: this.active,
1621 panel: !this.active.length ? $() : this.active.next()
1622 };
1623 },
1624
1625 _createIcons: function() {
1626 var icons = this.options.icons;
1627 if ( icons ) {
1628 $( "<span>" )
1629 .addClass( "ui-accordion-header-icon ui-icon " + icons.header )
1630 .prependTo( this.headers );
1631 this.active.children( ".ui-accordion-header-icon" )
1632 .removeClass( icons.header )
1633 .addClass( icons.activeHeader );
1634 this.headers.addClass( "ui-accordion-icons" );
1635 }
1636 },
1637
1638 _destroyIcons: function() {
1639 this.headers
1640 .removeClass( "ui-accordion-icons" )
1641 .children( ".ui-accordion-header-icon" )
1642 .remove();
1643 },
1644
1645 _destroy: function() {
1646 var contents;
1647
1648 // clean up main element
1649 this.element
1650 .removeClass( "ui-accordion ui-widget ui-helper-reset" )
1651 .removeAttr( "role" );
1652
1653 // clean up headers
1654 this.headers
1655 .removeClass( "ui-accordion-header ui-accordion-header-active ui-state-default " +
1656 "ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
1657 .removeAttr( "role" )
1658 .removeAttr( "aria-expanded" )
1659 .removeAttr( "aria-selected" )
1660 .removeAttr( "aria-controls" )
1661 .removeAttr( "tabIndex" )
1662 .removeUniqueId();
1663
1664 this._destroyIcons();
1665
1666 // clean up content panels
1667 contents = this.headers.next()
1668 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom " +
1669 "ui-accordion-content ui-accordion-content-active ui-state-disabled" )
1670 .css( "display", "" )
1671 .removeAttr( "role" )
1672 .removeAttr( "aria-hidden" )
1673 .removeAttr( "aria-labelledby" )
1674 .removeUniqueId();
1675
1676 if ( this.options.heightStyle !== "content" ) {
1677 contents.css( "height", "" );
1678 }
1679 },
1680
1681 _setOption: function( key, value ) {
1682 if ( key === "active" ) {
1683 // _activate() will handle invalid values and update this.options
1684 this._activate( value );
1685 return;
1686 }
1687
1688 if ( key === "event" ) {
1689 if ( this.options.event ) {
1690 this._off( this.headers, this.options.event );
1691 }
1692 this._setupEvents( value );
1693 }
1694
1695 this._super( key, value );
1696
1697 // setting collapsible: false while collapsed; open first panel
1698 if ( key === "collapsible" && !value && this.options.active === false ) {
1699 this._activate( 0 );
1700 }
1701
1702 if ( key === "icons" ) {
1703 this._destroyIcons();
1704 if ( value ) {
1705 this._createIcons();
1706 }
1707 }
1708
1709 // #5332 - opacity doesn't cascade to positioned elements in IE
1710 // so we need to add the disabled class to the headers and panels
1711 if ( key === "disabled" ) {
1712 this.element
1713 .toggleClass( "ui-state-disabled", !!value )
1714 .attr( "aria-disabled", value );
1715 this.headers.add( this.headers.next() )
1716 .toggleClass( "ui-state-disabled", !!value );
1717 }
1718 },
1719
1720 _keydown: function( event ) {
1721 if ( event.altKey || event.ctrlKey ) {
1722 return;
1723 }
1724
1725 var keyCode = $.ui.keyCode,
1726 length = this.headers.length,
1727 currentIndex = this.headers.index( event.target ),
1728 toFocus = false;
1729
1730 switch ( event.keyCode ) {
1731 case keyCode.RIGHT:
1732 case keyCode.DOWN:
1733 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
1734 break;
1735 case keyCode.LEFT:
1736 case keyCode.UP:
1737 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
1738 break;
1739 case keyCode.SPACE:
1740 case keyCode.ENTER:
1741 this._eventHandler( event );
1742 break;
1743 case keyCode.HOME:
1744 toFocus = this.headers[ 0 ];
1745 break;
1746 case keyCode.END:
1747 toFocus = this.headers[ length - 1 ];
1748 break;
1749 }
1750
1751 if ( toFocus ) {
1752 $( event.target ).attr( "tabIndex", -1 );
1753 $( toFocus ).attr( "tabIndex", 0 );
1754 toFocus.focus();
1755 event.preventDefault();
1756 }
1757 },
1758
1759 _panelKeyDown: function( event ) {
1760 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
1761 $( event.currentTarget ).prev().focus();
1762 }
1763 },
1764
1765 refresh: function() {
1766 var options = this.options;
1767 this._processPanels();
1768
1769 // was collapsed or no panel
1770 if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {
1771 options.active = false;
1772 this.active = $();
1773 // active false only when collapsible is true
1774 } else if ( options.active === false ) {
1775 this._activate( 0 );
1776 // was active, but active panel is gone
1777 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
1778 // all remaining panel are disabled
1779 if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {
1780 options.active = false;
1781 this.active = $();
1782 // activate previous panel
1783 } else {
1784 this._activate( Math.max( 0, options.active - 1 ) );
1785 }
1786 // was active, active panel still exists
1787 } else {
1788 // make sure active index is correct
1789 options.active = this.headers.index( this.active );
1790 }
1791
1792 this._destroyIcons();
1793
1794 this._refresh();
1795 },
1796
1797 _processPanels: function() {
1798 var prevHeaders = this.headers,
1799 prevPanels = this.panels;
1800
1801 this.headers = this.element.find( this.options.header )
1802 .addClass( "ui-accordion-header ui-state-default ui-corner-all" );
1803
1804 this.panels = this.headers.next()
1805 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
1806 .filter( ":not(.ui-accordion-content-active)" )
1807 .hide();
1808
1809 // Avoid memory leaks (#10056)
1810 if ( prevPanels ) {
1811 this._off( prevHeaders.not( this.headers ) );
1812 this._off( prevPanels.not( this.panels ) );
1813 }
1814 },
1815
1816 _refresh: function() {
1817 var maxHeight,
1818 options = this.options,
1819 heightStyle = options.heightStyle,
1820 parent = this.element.parent();
1821
1822 this.active = this._findActive( options.active )
1823 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" )
1824 .removeClass( "ui-corner-all" );
1825 this.active.next()
1826 .addClass( "ui-accordion-content-active" )
1827 .show();
1828
1829 this.headers
1830 .attr( "role", "tab" )
1831 .each(function() {
1832 var header = $( this ),
1833 headerId = header.uniqueId().attr( "id" ),
1834 panel = header.next(),
1835 panelId = panel.uniqueId().attr( "id" );
1836 header.attr( "aria-controls", panelId );
1837 panel.attr( "aria-labelledby", headerId );
1838 })
1839 .next()
1840 .attr( "role", "tabpanel" );
1841
1842 this.headers
1843 .not( this.active )
1844 .attr({
1845 "aria-selected": "false",
1846 "aria-expanded": "false",
1847 tabIndex: -1
1848 })
1849 .next()
1850 .attr({
1851 "aria-hidden": "true"
1852 })
1853 .hide();
1854
1855 // make sure at least one header is in the tab order
1856 if ( !this.active.length ) {
1857 this.headers.eq( 0 ).attr( "tabIndex", 0 );
1858 } else {
1859 this.active.attr({
1860 "aria-selected": "true",
1861 "aria-expanded": "true",
1862 tabIndex: 0
1863 })
1864 .next()
1865 .attr({
1866 "aria-hidden": "false"
1867 });
1868 }
1869
1870 this._createIcons();
1871
1872 this._setupEvents( options.event );
1873
1874 if ( heightStyle === "fill" ) {
1875 maxHeight = parent.height();
1876 this.element.siblings( ":visible" ).each(function() {
1877 var elem = $( this ),
1878 position = elem.css( "position" );
1879
1880 if ( position === "absolute" || position === "fixed" ) {
1881 return;
1882 }
1883 maxHeight -= elem.outerHeight( true );
1884 });
1885
1886 this.headers.each(function() {
1887 maxHeight -= $( this ).outerHeight( true );
1888 });
1889
1890 this.headers.next()
1891 .each(function() {
1892 $( this ).height( Math.max( 0, maxHeight -
1893 $( this ).innerHeight() + $( this ).height() ) );
1894 })
1895 .css( "overflow", "auto" );
1896 } else if ( heightStyle === "auto" ) {
1897 maxHeight = 0;
1898 this.headers.next()
1899 .each(function() {
1900 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
1901 })
1902 .height( maxHeight );
1903 }
1904 },
1905
1906 _activate: function( index ) {
1907 var active = this._findActive( index )[ 0 ];
1908
1909 // trying to activate the already active panel
1910 if ( active === this.active[ 0 ] ) {
1911 return;
1912 }
1913
1914 // trying to collapse, simulate a click on the currently active header
1915 active = active || this.active[ 0 ];
1916
1917 this._eventHandler({
1918 target: active,
1919 currentTarget: active,
1920 preventDefault: $.noop
1921 });
1922 },
1923
1924 _findActive: function( selector ) {
1925 return typeof selector === "number" ? this.headers.eq( selector ) : $();
1926 },
1927
1928 _setupEvents: function( event ) {
1929 var events = {
1930 keydown: "_keydown"
1931 };
1932 if ( event ) {
1933 $.each( event.split( " " ), function( index, eventName ) {
1934 events[ eventName ] = "_eventHandler";
1935 });
1936 }
1937
1938 this._off( this.headers.add( this.headers.next() ) );
1939 this._on( this.headers, events );
1940 this._on( this.headers.next(), { keydown: "_panelKeyDown" });
1941 this._hoverable( this.headers );
1942 this._focusable( this.headers );
1943 },
1944
1945 _eventHandler: function( event ) {
1946 var options = this.options,
1947 active = this.active,
1948 clicked = $( event.currentTarget ),
1949 clickedIsActive = clicked[ 0 ] === active[ 0 ],
1950 collapsing = clickedIsActive && options.collapsible,
1951 toShow = collapsing ? $() : clicked.next(),
1952 toHide = active.next(),
1953 eventData = {
1954 oldHeader: active,
1955 oldPanel: toHide,
1956 newHeader: collapsing ? $() : clicked,
1957 newPanel: toShow
1958 };
1959
1960 event.preventDefault();
1961
1962 if (
1963 // click on active header, but not collapsible
1964 ( clickedIsActive && !options.collapsible ) ||
1965 // allow canceling activation
1966 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
1967 return;
1968 }
1969
1970 options.active = collapsing ? false : this.headers.index( clicked );
1971
1972 // when the call to ._toggle() comes after the class changes
1973 // it causes a very odd bug in IE 8 (see #6720)
1974 this.active = clickedIsActive ? $() : clicked;
1975 this._toggle( eventData );
1976
1977 // switch classes
1978 // corner classes on the previously active header stay after the animation
1979 active.removeClass( "ui-accordion-header-active ui-state-active" );
1980 if ( options.icons ) {
1981 active.children( ".ui-accordion-header-icon" )
1982 .removeClass( options.icons.activeHeader )
1983 .addClass( options.icons.header );
1984 }
1985
1986 if ( !clickedIsActive ) {
1987 clicked
1988 .removeClass( "ui-corner-all" )
1989 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
1990 if ( options.icons ) {
1991 clicked.children( ".ui-accordion-header-icon" )
1992 .removeClass( options.icons.header )
1993 .addClass( options.icons.activeHeader );
1994 }
1995
1996 clicked
1997 .next()
1998 .addClass( "ui-accordion-content-active" );
1999 }
2000 },
2001
2002 _toggle: function( data ) {
2003 var toShow = data.newPanel,
2004 toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
2005
2006 // handle activating a panel during the animation for another activation
2007 this.prevShow.add( this.prevHide ).stop( true, true );
2008 this.prevShow = toShow;
2009 this.prevHide = toHide;
2010
2011 if ( this.options.animate ) {
2012 this._animate( toShow, toHide, data );
2013 } else {
2014 toHide.hide();
2015 toShow.show();
2016 this._toggleComplete( data );
2017 }
2018
2019 toHide.attr({
2020 "aria-hidden": "true"
2021 });
2022 toHide.prev().attr( "aria-selected", "false" );
2023 // if we're switching panels, remove the old header from the tab order
2024 // if we're opening from collapsed state, remove the previous header from the tab order
2025 // if we're collapsing, then keep the collapsing header in the tab order
2026 if ( toShow.length && toHide.length ) {
2027 toHide.prev().attr({
2028 "tabIndex": -1,
2029 "aria-expanded": "false"
2030 });
2031 } else if ( toShow.length ) {
2032 this.headers.filter(function() {
2033 return $( this ).attr( "tabIndex" ) === 0;
2034 })
2035 .attr( "tabIndex", -1 );
2036 }
2037
2038 toShow
2039 .attr( "aria-hidden", "false" )
2040 .prev()
2041 .attr({
2042 "aria-selected": "true",
2043 tabIndex: 0,
2044 "aria-expanded": "true"
2045 });
2046 },
2047
2048 _animate: function( toShow, toHide, data ) {
2049 var total, easing, duration,
2050 that = this,
2051 adjust = 0,
2052 down = toShow.length &&
2053 ( !toHide.length || ( toShow.index() < toHide.index() ) ),
2054 animate = this.options.animate || {},
2055 options = down && animate.down || animate,
2056 complete = function() {
2057 that._toggleComplete( data );
2058 };
2059
2060 if ( typeof options === "number" ) {
2061 duration = options;
2062 }
2063 if ( typeof options === "string" ) {
2064 easing = options;
2065 }
2066 // fall back from options to animation in case of partial down settings
2067 easing = easing || options.easing || animate.easing;
2068 duration = duration || options.duration || animate.duration;
2069
2070 if ( !toHide.length ) {
2071 return toShow.animate( this.showProps, duration, easing, complete );
2072 }
2073 if ( !toShow.length ) {
2074 return toHide.animate( this.hideProps, duration, easing, complete );
2075 }
2076
2077 total = toShow.show().outerHeight();
2078 toHide.animate( this.hideProps, {
2079 duration: duration,
2080 easing: easing,
2081 step: function( now, fx ) {
2082 fx.now = Math.round( now );
2083 }
2084 });
2085 toShow
2086 .hide()
2087 .animate( this.showProps, {
2088 duration: duration,
2089 easing: easing,
2090 complete: complete,
2091 step: function( now, fx ) {
2092 fx.now = Math.round( now );
2093 if ( fx.prop !== "height" ) {
2094 adjust += fx.now;
2095 } else if ( that.options.heightStyle !== "content" ) {
2096 fx.now = Math.round( total - toHide.outerHeight() - adjust );
2097 adjust = 0;
2098 }
2099 }
2100 });
2101 },
2102
2103 _toggleComplete: function( data ) {
2104 var toHide = data.oldPanel;
2105
2106 toHide
2107 .removeClass( "ui-accordion-content-active" )
2108 .prev()
2109 .removeClass( "ui-corner-top" )
2110 .addClass( "ui-corner-all" );
2111
2112 // Work around for rendering bug in IE (#5421)
2113 if ( toHide.length ) {
2114 toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
2115 }
2116 this._trigger( "activate", null, data );
2117 }
2118});
2119
2120
2121/*!
2122 * jQuery UI Menu 1.11.2
2123 * http://jqueryui.com
2124 *
2125 * Copyright 2014 jQuery Foundation and other contributors
2126 * Released under the MIT license.
2127 * http://jquery.org/license
2128 *
2129 * http://api.jqueryui.com/menu/
2130 */
2131
2132
2133var menu = $.widget( "ui.menu", {
2134 version: "1.11.2",
2135 defaultElement: "<ul>",
2136 delay: 300,
2137 options: {
2138 icons: {
2139 submenu: "ui-icon-carat-1-e"
2140 },
2141 items: "> *",
2142 menus: "ul",
2143 position: {
2144 my: "left-1 top",
2145 at: "right top"
2146 },
2147 role: "menu",
2148
2149 // callbacks
2150 blur: null,
2151 focus: null,
2152 select: null
2153 },
2154
2155 _create: function() {
2156 this.activeMenu = this.element;
2157
2158 // Flag used to prevent firing of the click handler
2159 // as the event bubbles up through nested menus
2160 this.mouseHandled = false;
2161 this.element
2162 .uniqueId()
2163 .addClass( "ui-menu ui-widget ui-widget-content" )
2164 .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
2165 .attr({
2166 role: this.options.role,
2167 tabIndex: 0
2168 });
2169
2170 if ( this.options.disabled ) {
2171 this.element
2172 .addClass( "ui-state-disabled" )
2173 .attr( "aria-disabled", "true" );
2174 }
2175
2176 this._on({
2177 // Prevent focus from sticking to links inside menu after clicking
2178 // them (focus should always stay on UL during navigation).
2179 "mousedown .ui-menu-item": function( event ) {
2180 event.preventDefault();
2181 },
2182 "click .ui-menu-item": function( event ) {
2183 var target = $( event.target );
2184 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
2185 this.select( event );
2186
2187 // Only set the mouseHandled flag if the event will bubble, see #9469.
2188 if ( !event.isPropagationStopped() ) {
2189 this.mouseHandled = true;
2190 }
2191
2192 // Open submenu on click
2193 if ( target.has( ".ui-menu" ).length ) {
2194 this.expand( event );
2195 } else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) {
2196
2197 // Redirect focus to the menu
2198 this.element.trigger( "focus", [ true ] );
2199
2200 // If the active item is on the top level, let it stay active.
2201 // Otherwise, blur the active item since it is no longer visible.
2202 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
2203 clearTimeout( this.timer );
2204 }
2205 }
2206 }
2207 },
2208 "mouseenter .ui-menu-item": function( event ) {
2209 // Ignore mouse events while typeahead is active, see #10458.
2210 // Prevents focusing the wrong item when typeahead causes a scroll while the mouse
2211 // is over an item in the menu
2212 if ( this.previousFilter ) {
2213 return;
2214 }
2215 var target = $( event.currentTarget );
2216 // Remove ui-state-active class from siblings of the newly focused menu item
2217 // to avoid a jump caused by adjacent elements both having a class with a border
2218 target.siblings( ".ui-state-active" ).removeClass( "ui-state-active" );
2219 this.focus( event, target );
2220 },
2221 mouseleave: "collapseAll",
2222 "mouseleave .ui-menu": "collapseAll",
2223 focus: function( event, keepActiveItem ) {
2224 // If there's already an active item, keep it active
2225 // If not, activate the first item
2226 var item = this.active || this.element.find( this.options.items ).eq( 0 );
2227
2228 if ( !keepActiveItem ) {
2229 this.focus( event, item );
2230 }
2231 },
2232 blur: function( event ) {
2233 this._delay(function() {
2234 if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
2235 this.collapseAll( event );
2236 }
2237 });
2238 },
2239 keydown: "_keydown"
2240 });
2241
2242 this.refresh();
2243
2244 // Clicks outside of a menu collapse any open menus
2245 this._on( this.document, {
2246 click: function( event ) {
2247 if ( this._closeOnDocumentClick( event ) ) {
2248 this.collapseAll( event );
2249 }
2250
2251 // Reset the mouseHandled flag
2252 this.mouseHandled = false;
2253 }
2254 });
2255 },
2256
2257 _destroy: function() {
2258 // Destroy (sub)menus
2259 this.element
2260 .removeAttr( "aria-activedescendant" )
2261 .find( ".ui-menu" ).addBack()
2262 .removeClass( "ui-menu ui-widget ui-widget-content ui-menu-icons ui-front" )
2263 .removeAttr( "role" )
2264 .removeAttr( "tabIndex" )
2265 .removeAttr( "aria-labelledby" )
2266 .removeAttr( "aria-expanded" )
2267 .removeAttr( "aria-hidden" )
2268 .removeAttr( "aria-disabled" )
2269 .removeUniqueId()
2270 .show();
2271
2272 // Destroy menu items
2273 this.element.find( ".ui-menu-item" )
2274 .removeClass( "ui-menu-item" )
2275 .removeAttr( "role" )
2276 .removeAttr( "aria-disabled" )
2277 .removeUniqueId()
2278 .removeClass( "ui-state-hover" )
2279 .removeAttr( "tabIndex" )
2280 .removeAttr( "role" )
2281 .removeAttr( "aria-haspopup" )
2282 .children().each( function() {
2283 var elem = $( this );
2284 if ( elem.data( "ui-menu-submenu-carat" ) ) {
2285 elem.remove();
2286 }
2287 });
2288
2289 // Destroy menu dividers
2290 this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
2291 },
2292
2293 _keydown: function( event ) {
2294 var match, prev, character, skip,
2295 preventDefault = true;
2296
2297 switch ( event.keyCode ) {
2298 case $.ui.keyCode.PAGE_UP:
2299 this.previousPage( event );
2300 break;
2301 case $.ui.keyCode.PAGE_DOWN:
2302 this.nextPage( event );
2303 break;
2304 case $.ui.keyCode.HOME:
2305 this._move( "first", "first", event );
2306 break;
2307 case $.ui.keyCode.END:
2308 this._move( "last", "last", event );
2309 break;
2310 case $.ui.keyCode.UP:
2311 this.previous( event );
2312 break;
2313 case $.ui.keyCode.DOWN:
2314 this.next( event );
2315 break;
2316 case $.ui.keyCode.LEFT:
2317 this.collapse( event );
2318 break;
2319 case $.ui.keyCode.RIGHT:
2320 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
2321 this.expand( event );
2322 }
2323 break;
2324 case $.ui.keyCode.ENTER:
2325 case $.ui.keyCode.SPACE:
2326 this._activate( event );
2327 break;
2328 case $.ui.keyCode.ESCAPE:
2329 this.collapse( event );
2330 break;
2331 default:
2332 preventDefault = false;
2333 prev = this.previousFilter || "";
2334 character = String.fromCharCode( event.keyCode );
2335 skip = false;
2336
2337 clearTimeout( this.filterTimer );
2338
2339 if ( character === prev ) {
2340 skip = true;
2341 } else {
2342 character = prev + character;
2343 }
2344
2345 match = this._filterMenuItems( character );
2346 match = skip && match.index( this.active.next() ) !== -1 ?
2347 this.active.nextAll( ".ui-menu-item" ) :
2348 match;
2349
2350 // If no matches on the current filter, reset to the last character pressed
2351 // to move down the menu to the first item that starts with that character
2352 if ( !match.length ) {
2353 character = String.fromCharCode( event.keyCode );
2354 match = this._filterMenuItems( character );
2355 }
2356
2357 if ( match.length ) {
2358 this.focus( event, match );
2359 this.previousFilter = character;
2360 this.filterTimer = this._delay(function() {
2361 delete this.previousFilter;
2362 }, 1000 );
2363 } else {
2364 delete this.previousFilter;
2365 }
2366 }
2367
2368 if ( preventDefault ) {
2369 event.preventDefault();
2370 }
2371 },
2372
2373 _activate: function( event ) {
2374 if ( !this.active.is( ".ui-state-disabled" ) ) {
2375 if ( this.active.is( "[aria-haspopup='true']" ) ) {
2376 this.expand( event );
2377 } else {
2378 this.select( event );
2379 }
2380 }
2381 },
2382
2383 refresh: function() {
2384 var menus, items,
2385 that = this,
2386 icon = this.options.icons.submenu,
2387 submenus = this.element.find( this.options.menus );
2388
2389 this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length );
2390
2391 // Initialize nested menus
2392 submenus.filter( ":not(.ui-menu)" )
2393 .addClass( "ui-menu ui-widget ui-widget-content ui-front" )
2394 .hide()
2395 .attr({
2396 role: this.options.role,
2397 "aria-hidden": "true",
2398 "aria-expanded": "false"
2399 })
2400 .each(function() {
2401 var menu = $( this ),
2402 item = menu.parent(),
2403 submenuCarat = $( "<span>" )
2404 .addClass( "ui-menu-icon ui-icon " + icon )
2405 .data( "ui-menu-submenu-carat", true );
2406
2407 item
2408 .attr( "aria-haspopup", "true" )
2409 .prepend( submenuCarat );
2410 menu.attr( "aria-labelledby", item.attr( "id" ) );
2411 });
2412
2413 menus = submenus.add( this.element );
2414 items = menus.find( this.options.items );
2415
2416 // Initialize menu-items containing spaces and/or dashes only as dividers
2417 items.not( ".ui-menu-item" ).each(function() {
2418 var item = $( this );
2419 if ( that._isDivider( item ) ) {
2420 item.addClass( "ui-widget-content ui-menu-divider" );
2421 }
2422 });
2423
2424 // Don't refresh list items that are already adapted
2425 items.not( ".ui-menu-item, .ui-menu-divider" )
2426 .addClass( "ui-menu-item" )
2427 .uniqueId()
2428 .attr({
2429 tabIndex: -1,
2430 role: this._itemRole()
2431 });
2432
2433 // Add aria-disabled attribute to any disabled menu item
2434 items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
2435
2436 // If the active item has been removed, blur the menu
2437 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
2438 this.blur();
2439 }
2440 },
2441
2442 _itemRole: function() {
2443 return {
2444 menu: "menuitem",
2445 listbox: "option"
2446 }[ this.options.role ];
2447 },
2448
2449 _setOption: function( key, value ) {
2450 if ( key === "icons" ) {
2451 this.element.find( ".ui-menu-icon" )
2452 .removeClass( this.options.icons.submenu )
2453 .addClass( value.submenu );
2454 }
2455 if ( key === "disabled" ) {
2456 this.element
2457 .toggleClass( "ui-state-disabled", !!value )
2458 .attr( "aria-disabled", value );
2459 }
2460 this._super( key, value );
2461 },
2462
2463 focus: function( event, item ) {
2464 var nested, focused;
2465 this.blur( event, event && event.type === "focus" );
2466
2467 this._scrollIntoView( item );
2468
2469 this.active = item.first();
2470 focused = this.active.addClass( "ui-state-focus" ).removeClass( "ui-state-active" );
2471 // Only update aria-activedescendant if there's a role
2472 // otherwise we assume focus is managed elsewhere
2473 if ( this.options.role ) {
2474 this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
2475 }
2476
2477 // Highlight active parent menu item, if any
2478 this.active
2479 .parent()
2480 .closest( ".ui-menu-item" )
2481 .addClass( "ui-state-active" );
2482
2483 if ( event && event.type === "keydown" ) {
2484 this._close();
2485 } else {
2486 this.timer = this._delay(function() {
2487 this._close();
2488 }, this.delay );
2489 }
2490
2491 nested = item.children( ".ui-menu" );
2492 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
2493 this._startOpening(nested);
2494 }
2495 this.activeMenu = item.parent();
2496
2497 this._trigger( "focus", event, { item: item } );
2498 },
2499
2500 _scrollIntoView: function( item ) {
2501 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
2502 if ( this._hasScroll() ) {
2503 borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
2504 paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
2505 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
2506 scroll = this.activeMenu.scrollTop();
2507 elementHeight = this.activeMenu.height();
2508 itemHeight = item.outerHeight();
2509
2510 if ( offset < 0 ) {
2511 this.activeMenu.scrollTop( scroll + offset );
2512 } else if ( offset + itemHeight > elementHeight ) {
2513 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
2514 }
2515 }
2516 },
2517
2518 blur: function( event, fromFocus ) {
2519 if ( !fromFocus ) {
2520 clearTimeout( this.timer );
2521 }
2522
2523 if ( !this.active ) {
2524 return;
2525 }
2526
2527 this.active.removeClass( "ui-state-focus" );
2528 this.active = null;
2529
2530 this._trigger( "blur", event, { item: this.active } );
2531 },
2532
2533 _startOpening: function( submenu ) {
2534 clearTimeout( this.timer );
2535
2536 // Don't open if already open fixes a Firefox bug that caused a .5 pixel
2537 // shift in the submenu position when mousing over the carat icon
2538 if ( submenu.attr( "aria-hidden" ) !== "true" ) {
2539 return;
2540 }
2541
2542 this.timer = this._delay(function() {
2543 this._close();
2544 this._open( submenu );
2545 }, this.delay );
2546 },
2547
2548 _open: function( submenu ) {
2549 var position = $.extend({
2550 of: this.active
2551 }, this.options.position );
2552
2553 clearTimeout( this.timer );
2554 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
2555 .hide()
2556 .attr( "aria-hidden", "true" );
2557
2558 submenu
2559 .show()
2560 .removeAttr( "aria-hidden" )
2561 .attr( "aria-expanded", "true" )
2562 .position( position );
2563 },
2564
2565 collapseAll: function( event, all ) {
2566 clearTimeout( this.timer );
2567 this.timer = this._delay(function() {
2568 // If we were passed an event, look for the submenu that contains the event
2569 var currentMenu = all ? this.element :
2570 $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
2571
2572 // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
2573 if ( !currentMenu.length ) {
2574 currentMenu = this.element;
2575 }
2576
2577 this._close( currentMenu );
2578
2579 this.blur( event );
2580 this.activeMenu = currentMenu;
2581 }, this.delay );
2582 },
2583
2584 // With no arguments, closes the currently active menu - if nothing is active
2585 // it closes all menus. If passed an argument, it will search for menus BELOW
2586 _close: function( startMenu ) {
2587 if ( !startMenu ) {
2588 startMenu = this.active ? this.active.parent() : this.element;
2589 }
2590
2591 startMenu
2592 .find( ".ui-menu" )
2593 .hide()
2594 .attr( "aria-hidden", "true" )
2595 .attr( "aria-expanded", "false" )
2596 .end()
2597 .find( ".ui-state-active" ).not( ".ui-state-focus" )
2598 .removeClass( "ui-state-active" );
2599 },
2600
2601 _closeOnDocumentClick: function( event ) {
2602 return !$( event.target ).closest( ".ui-menu" ).length;
2603 },
2604
2605 _isDivider: function( item ) {
2606
2607 // Match hyphen, em dash, en dash
2608 return !/[^\-\u2014\u2013\s]/.test( item.text() );
2609 },
2610
2611 collapse: function( event ) {
2612 var newItem = this.active &&
2613 this.active.parent().closest( ".ui-menu-item", this.element );
2614 if ( newItem && newItem.length ) {
2615 this._close();
2616 this.focus( event, newItem );
2617 }
2618 },
2619
2620 expand: function( event ) {
2621 var newItem = this.active &&
2622 this.active
2623 .children( ".ui-menu " )
2624 .find( this.options.items )
2625 .first();
2626
2627 if ( newItem && newItem.length ) {
2628 this._open( newItem.parent() );
2629
2630 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
2631 this._delay(function() {
2632 this.focus( event, newItem );
2633 });
2634 }
2635 },
2636
2637 next: function( event ) {
2638 this._move( "next", "first", event );
2639 },
2640
2641 previous: function( event ) {
2642 this._move( "prev", "last", event );
2643 },
2644
2645 isFirstItem: function() {
2646 return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
2647 },
2648
2649 isLastItem: function() {
2650 return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
2651 },
2652
2653 _move: function( direction, filter, event ) {
2654 var next;
2655 if ( this.active ) {
2656 if ( direction === "first" || direction === "last" ) {
2657 next = this.active
2658 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
2659 .eq( -1 );
2660 } else {
2661 next = this.active
2662 [ direction + "All" ]( ".ui-menu-item" )
2663 .eq( 0 );
2664 }
2665 }
2666 if ( !next || !next.length || !this.active ) {
2667 next = this.activeMenu.find( this.options.items )[ filter ]();
2668 }
2669
2670 this.focus( event, next );
2671 },
2672
2673 nextPage: function( event ) {
2674 var item, base, height;
2675
2676 if ( !this.active ) {
2677 this.next( event );
2678 return;
2679 }
2680 if ( this.isLastItem() ) {
2681 return;
2682 }
2683 if ( this._hasScroll() ) {
2684 base = this.active.offset().top;
2685 height = this.element.height();
2686 this.active.nextAll( ".ui-menu-item" ).each(function() {
2687 item = $( this );
2688 return item.offset().top - base - height < 0;
2689 });
2690
2691 this.focus( event, item );
2692 } else {
2693 this.focus( event, this.activeMenu.find( this.options.items )
2694 [ !this.active ? "first" : "last" ]() );
2695 }
2696 },
2697
2698 previousPage: function( event ) {
2699 var item, base, height;
2700 if ( !this.active ) {
2701 this.next( event );
2702 return;
2703 }
2704 if ( this.isFirstItem() ) {
2705 return;
2706 }
2707 if ( this._hasScroll() ) {
2708 base = this.active.offset().top;
2709 height = this.element.height();
2710 this.active.prevAll( ".ui-menu-item" ).each(function() {
2711 item = $( this );
2712 return item.offset().top - base + height > 0;
2713 });
2714
2715 this.focus( event, item );
2716 } else {
2717 this.focus( event, this.activeMenu.find( this.options.items ).first() );
2718 }
2719 },
2720
2721 _hasScroll: function() {
2722 return this.element.outerHeight() < this.element.prop( "scrollHeight" );
2723 },
2724
2725 select: function( event ) {
2726 // TODO: It should never be possible to not have an active item at this
2727 // point, but the tests don't trigger mouseenter before click.
2728 this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
2729 var ui = { item: this.active };
2730 if ( !this.active.has( ".ui-menu" ).length ) {
2731 this.collapseAll( event, true );
2732 }
2733 this._trigger( "select", event, ui );
2734 },
2735
2736 _filterMenuItems: function(character) {
2737 var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
2738 regex = new RegExp( "^" + escapedCharacter, "i" );
2739
2740 return this.activeMenu
2741 .find( this.options.items )
2742
2743 // Only match on items, not dividers or other content (#10571)
2744 .filter( ".ui-menu-item" )
2745 .filter(function() {
2746 return regex.test( $.trim( $( this ).text() ) );
2747 });
2748 }
2749});
2750
2751
2752/*!
2753 * jQuery UI Autocomplete 1.11.2
2754 * http://jqueryui.com
2755 *
2756 * Copyright 2014 jQuery Foundation and other contributors
2757 * Released under the MIT license.
2758 * http://jquery.org/license
2759 *
2760 * http://api.jqueryui.com/autocomplete/
2761 */
2762
2763
2764$.widget( "ui.autocomplete", {
2765 version: "1.11.2",
2766 defaultElement: "<input>",
2767 options: {
2768 appendTo: null,
2769 autoFocus: false,
2770 delay: 300,
2771 minLength: 1,
2772 position: {
2773 my: "left top",
2774 at: "left bottom",
2775 collision: "none"
2776 },
2777 source: null,
2778
2779 // callbacks
2780 change: null,
2781 close: null,
2782 focus: null,
2783 open: null,
2784 response: null,
2785 search: null,
2786 select: null
2787 },
2788
2789 requestIndex: 0,
2790 pending: 0,
2791
2792 _create: function() {
2793 // Some browsers only repeat keydown events, not keypress events,
2794 // so we use the suppressKeyPress flag to determine if we've already
2795 // handled the keydown event. #7269
2796 // Unfortunately the code for & in keypress is the same as the up arrow,
2797 // so we use the suppressKeyPressRepeat flag to avoid handling keypress
2798 // events when we know the keydown event was used to modify the
2799 // search term. #7799
2800 var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
2801 nodeName = this.element[ 0 ].nodeName.toLowerCase(),
2802 isTextarea = nodeName === "textarea",
2803 isInput = nodeName === "input";
2804
2805 this.isMultiLine =
2806 // Textareas are always multi-line
2807 isTextarea ? true :
2808 // Inputs are always single-line, even if inside a contentEditable element
2809 // IE also treats inputs as contentEditable
2810 isInput ? false :
2811 // All other element types are determined by whether or not they're contentEditable
2812 this.element.prop( "isContentEditable" );
2813
2814 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
2815 this.isNewMenu = true;
2816
2817 this.element
2818 .addClass( "ui-autocomplete-input" )
2819 .attr( "autocomplete", "off" );
2820
2821 this._on( this.element, {
2822 keydown: function( event ) {
2823 if ( this.element.prop( "readOnly" ) ) {
2824 suppressKeyPress = true;
2825 suppressInput = true;
2826 suppressKeyPressRepeat = true;
2827 return;
2828 }
2829
2830 suppressKeyPress = false;
2831 suppressInput = false;
2832 suppressKeyPressRepeat = false;
2833 var keyCode = $.ui.keyCode;
2834 switch ( event.keyCode ) {
2835 case keyCode.PAGE_UP:
2836 suppressKeyPress = true;
2837 this._move( "previousPage", event );
2838 break;
2839 case keyCode.PAGE_DOWN:
2840 suppressKeyPress = true;
2841 this._move( "nextPage", event );
2842 break;
2843 case keyCode.UP:
2844 suppressKeyPress = true;
2845 this._keyEvent( "previous", event );
2846 break;
2847 case keyCode.DOWN:
2848 suppressKeyPress = true;
2849 this._keyEvent( "next", event );
2850 break;
2851 case keyCode.ENTER:
2852 // when menu is open and has focus
2853 if ( this.menu.active ) {
2854 // #6055 - Opera still allows the keypress to occur
2855 // which causes forms to submit
2856 suppressKeyPress = true;
2857 event.preventDefault();
2858 this.menu.select( event );
2859 }
2860 break;
2861 case keyCode.TAB:
2862 if ( this.menu.active ) {
2863 this.menu.select( event );
2864 }
2865 break;
2866 case keyCode.ESCAPE:
2867 if ( this.menu.element.is( ":visible" ) ) {
2868 if ( !this.isMultiLine ) {
2869 this._value( this.term );
2870 }
2871 this.close( event );
2872 // Different browsers have different default behavior for escape
2873 // Single press can mean undo or clear
2874 // Double press in IE means clear the whole form
2875 event.preventDefault();
2876 }
2877 break;
2878 default:
2879 suppressKeyPressRepeat = true;
2880 // search timeout should be triggered before the input value is changed
2881 this._searchTimeout( event );
2882 break;
2883 }
2884 },
2885 keypress: function( event ) {
2886 if ( suppressKeyPress ) {
2887 suppressKeyPress = false;
2888 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
2889 event.preventDefault();
2890 }
2891 return;
2892 }
2893 if ( suppressKeyPressRepeat ) {
2894 return;
2895 }
2896
2897 // replicate some key handlers to allow them to repeat in Firefox and Opera
2898 var keyCode = $.ui.keyCode;
2899 switch ( event.keyCode ) {
2900 case keyCode.PAGE_UP:
2901 this._move( "previousPage", event );
2902 break;
2903 case keyCode.PAGE_DOWN:
2904 this._move( "nextPage", event );
2905 break;
2906 case keyCode.UP:
2907 this._keyEvent( "previous", event );
2908 break;
2909 case keyCode.DOWN:
2910 this._keyEvent( "next", event );
2911 break;
2912 }
2913 },
2914 input: function( event ) {
2915 if ( suppressInput ) {
2916 suppressInput = false;
2917 event.preventDefault();
2918 return;
2919 }
2920 this._searchTimeout( event );
2921 },
2922 focus: function() {
2923 this.selectedItem = null;
2924 this.previous = this._value();
2925 },
2926 blur: function( event ) {
2927 if ( this.cancelBlur ) {
2928 delete this.cancelBlur;
2929 return;
2930 }
2931
2932 clearTimeout( this.searching );
2933 this.close( event );
2934 this._change( event );
2935 }
2936 });
2937
2938 this._initSource();
2939 this.menu = $( "<ul>" )
2940 .addClass( "ui-autocomplete ui-front" )
2941 .appendTo( this._appendTo() )
2942 .menu({
2943 // disable ARIA support, the live region takes care of that
2944 role: null
2945 })
2946 .hide()
2947 .menu( "instance" );
2948
2949 this._on( this.menu.element, {
2950 mousedown: function( event ) {
2951 // prevent moving focus out of the text field
2952 event.preventDefault();
2953
2954 // IE doesn't prevent moving focus even with event.preventDefault()
2955 // so we set a flag to know when we should ignore the blur event
2956 this.cancelBlur = true;
2957 this._delay(function() {
2958 delete this.cancelBlur;
2959 });
2960
2961 // clicking on the scrollbar causes focus to shift to the body
2962 // but we can't detect a mouseup or a click immediately afterward
2963 // so we have to track the next mousedown and close the menu if
2964 // the user clicks somewhere outside of the autocomplete
2965 var menuElement = this.menu.element[ 0 ];
2966 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
2967 this._delay(function() {
2968 var that = this;
2969 this.document.one( "mousedown", function( event ) {
2970 if ( event.target !== that.element[ 0 ] &&
2971 event.target !== menuElement &&
2972 !$.contains( menuElement, event.target ) ) {
2973 that.close();
2974 }
2975 });
2976 });
2977 }
2978 },
2979 menufocus: function( event, ui ) {
2980 var label, item;
2981 // support: Firefox
2982 // Prevent accidental activation of menu items in Firefox (#7024 #9118)
2983 if ( this.isNewMenu ) {
2984 this.isNewMenu = false;
2985 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
2986 this.menu.blur();
2987
2988 this.document.one( "mousemove", function() {
2989 $( event.target ).trigger( event.originalEvent );
2990 });
2991
2992 return;
2993 }
2994 }
2995
2996 item = ui.item.data( "ui-autocomplete-item" );
2997 if ( false !== this._trigger( "focus", event, { item: item } ) ) {
2998 // use value to match what will end up in the input, if it was a key event
2999 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
3000 this._value( item.value );
3001 }
3002 }
3003
3004 // Announce the value in the liveRegion
3005 label = ui.item.attr( "aria-label" ) || item.value;
3006 if ( label && $.trim( label ).length ) {
3007 this.liveRegion.children().hide();
3008 $( "<div>" ).text( label ).appendTo( this.liveRegion );
3009 }
3010 },
3011 menuselect: function( event, ui ) {
3012 var item = ui.item.data( "ui-autocomplete-item" ),
3013 previous = this.previous;
3014
3015 // only trigger when focus was lost (click on menu)
3016 if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
3017 this.element.focus();
3018 this.previous = previous;
3019 // #6109 - IE triggers two focus events and the second
3020 // is asynchronous, so we need to reset the previous
3021 // term synchronously and asynchronously :-(
3022 this._delay(function() {
3023 this.previous = previous;
3024 this.selectedItem = item;
3025 });
3026 }
3027
3028 if ( false !== this._trigger( "select", event, { item: item } ) ) {
3029 this._value( item.value );
3030 }
3031 // reset the term after the select event
3032 // this allows custom select handling to work properly
3033 this.term = this._value();
3034
3035 this.close( event );
3036 this.selectedItem = item;
3037 }
3038 });
3039
3040 this.liveRegion = $( "<span>", {
3041 role: "status",
3042 "aria-live": "assertive",
3043 "aria-relevant": "additions"
3044 })
3045 .addClass( "ui-helper-hidden-accessible" )
3046 .appendTo( this.document[ 0 ].body );
3047
3048 // turning off autocomplete prevents the browser from remembering the
3049 // value when navigating through history, so we re-enable autocomplete
3050 // if the page is unloaded before the widget is destroyed. #7790
3051 this._on( this.window, {
3052 beforeunload: function() {
3053 this.element.removeAttr( "autocomplete" );
3054 }
3055 });
3056 },
3057
3058 _destroy: function() {
3059 clearTimeout( this.searching );
3060 this.element
3061 .removeClass( "ui-autocomplete-input" )
3062 .removeAttr( "autocomplete" );
3063 this.menu.element.remove();
3064 this.liveRegion.remove();
3065 },
3066
3067 _setOption: function( key, value ) {
3068 this._super( key, value );
3069 if ( key === "source" ) {
3070 this._initSource();
3071 }
3072 if ( key === "appendTo" ) {
3073 this.menu.element.appendTo( this._appendTo() );
3074 }
3075 if ( key === "disabled" && value && this.xhr ) {
3076 this.xhr.abort();
3077 }
3078 },
3079
3080 _appendTo: function() {
3081 var element = this.options.appendTo;
3082
3083 if ( element ) {
3084 element = element.jquery || element.nodeType ?
3085 $( element ) :
3086 this.document.find( element ).eq( 0 );
3087 }
3088
3089 if ( !element || !element[ 0 ] ) {
3090 element = this.element.closest( ".ui-front" );
3091 }
3092
3093 if ( !element.length ) {
3094 element = this.document[ 0 ].body;
3095 }
3096
3097 return element;
3098 },
3099
3100 _initSource: function() {
3101 var array, url,
3102 that = this;
3103 if ( $.isArray( this.options.source ) ) {
3104 array = this.options.source;
3105 this.source = function( request, response ) {
3106 response( $.ui.autocomplete.filter( array, request.term ) );
3107 };
3108 } else if ( typeof this.options.source === "string" ) {
3109 url = this.options.source;
3110 this.source = function( request, response ) {
3111 if ( that.xhr ) {
3112 that.xhr.abort();
3113 }
3114 that.xhr = $.ajax({
3115 url: url,
3116 data: request,
3117 dataType: "json",
3118 success: function( data ) {
3119 response( data );
3120 },
3121 error: function() {
3122 response([]);
3123 }
3124 });
3125 };
3126 } else {
3127 this.source = this.options.source;
3128 }
3129 },
3130
3131 _searchTimeout: function( event ) {
3132 clearTimeout( this.searching );
3133 this.searching = this._delay(function() {
3134
3135 // Search if the value has changed, or if the user retypes the same value (see #7434)
3136 var equalValues = this.term === this._value(),
3137 menuVisible = this.menu.element.is( ":visible" ),
3138 modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
3139
3140 if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
3141 this.selectedItem = null;
3142 this.search( null, event );
3143 }
3144 }, this.options.delay );
3145 },
3146
3147 search: function( value, event ) {
3148 value = value != null ? value : this._value();
3149
3150 // always save the actual value, not the one passed as an argument
3151 this.term = this._value();
3152
3153 if ( value.length < this.options.minLength ) {
3154 return this.close( event );
3155 }
3156
3157 if ( this._trigger( "search", event ) === false ) {
3158 return;
3159 }
3160
3161 return this._search( value );
3162 },
3163
3164 _search: function( value ) {
3165 this.pending++;
3166 this.element.addClass( "ui-autocomplete-loading" );
3167 this.cancelSearch = false;
3168
3169 this.source( { term: value }, this._response() );
3170 },
3171
3172 _response: function() {
3173 var index = ++this.requestIndex;
3174
3175 return $.proxy(function( content ) {
3176 if ( index === this.requestIndex ) {
3177 this.__response( content );
3178 }
3179
3180 this.pending--;
3181 if ( !this.pending ) {
3182 this.element.removeClass( "ui-autocomplete-loading" );
3183 }
3184 }, this );
3185 },
3186
3187 __response: function( content ) {
3188 if ( content ) {
3189 content = this._normalize( content );
3190 }
3191 this._trigger( "response", null, { content: content } );
3192 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
3193 this._suggest( content );
3194 this._trigger( "open" );
3195 } else {
3196 // use ._close() instead of .close() so we don't cancel future searches
3197 this._close();
3198 }
3199 },
3200
3201 close: function( event ) {
3202 this.cancelSearch = true;
3203 this._close( event );
3204 },
3205
3206 _close: function( event ) {
3207 if ( this.menu.element.is( ":visible" ) ) {
3208 this.menu.element.hide();
3209 this.menu.blur();
3210 this.isNewMenu = true;
3211 this._trigger( "close", event );
3212 }
3213 },
3214
3215 _change: function( event ) {
3216 if ( this.previous !== this._value() ) {
3217 this._trigger( "change", event, { item: this.selectedItem } );
3218 }
3219 },
3220
3221 _normalize: function( items ) {
3222 // assume all items have the right format when the first item is complete
3223 if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
3224 return items;
3225 }
3226 return $.map( items, function( item ) {
3227 if ( typeof item === "string" ) {
3228 return {
3229 label: item,
3230 value: item
3231 };
3232 }
3233 return $.extend( {}, item, {
3234 label: item.label || item.value,
3235 value: item.value || item.label
3236 });
3237 });
3238 },
3239
3240 _suggest: function( items ) {
3241 var ul = this.menu.element.empty();
3242 this._renderMenu( ul, items );
3243 this.isNewMenu = true;
3244 this.menu.refresh();
3245
3246 // size and position menu
3247 ul.show();
3248 this._resizeMenu();
3249 ul.position( $.extend({
3250 of: this.element
3251 }, this.options.position ) );
3252
3253 if ( this.options.autoFocus ) {
3254 this.menu.next();
3255 }
3256 },
3257
3258 _resizeMenu: function() {
3259 var ul = this.menu.element;
3260 ul.outerWidth( Math.max(
3261 // Firefox wraps long text (possibly a rounding bug)
3262 // so we add 1px to avoid the wrapping (#7513)
3263 ul.width( "" ).outerWidth() + 1,
3264 this.element.outerWidth()
3265 ) );
3266 },
3267
3268 _renderMenu: function( ul, items ) {
3269 var that = this;
3270 $.each( items, function( index, item ) {
3271 that._renderItemData( ul, item );
3272 });
3273 },
3274
3275 _renderItemData: function( ul, item ) {
3276 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
3277 },
3278
3279 _renderItem: function( ul, item ) {
3280 return $( "<li>" ).text( item.label ).appendTo( ul );
3281 },
3282
3283 _move: function( direction, event ) {
3284 if ( !this.menu.element.is( ":visible" ) ) {
3285 this.search( null, event );
3286 return;
3287 }
3288 if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
3289 this.menu.isLastItem() && /^next/.test( direction ) ) {
3290
3291 if ( !this.isMultiLine ) {
3292 this._value( this.term );
3293 }
3294
3295 this.menu.blur();
3296 return;
3297 }
3298 this.menu[ direction ]( event );
3299 },
3300
3301 widget: function() {
3302 return this.menu.element;
3303 },
3304
3305 _value: function() {
3306 return this.valueMethod.apply( this.element, arguments );
3307 },
3308
3309 _keyEvent: function( keyEvent, event ) {
3310 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
3311 this._move( keyEvent, event );
3312
3313 // prevents moving cursor to beginning/end of the text field in some browsers
3314 event.preventDefault();
3315 }
3316 }
3317});
3318
3319$.extend( $.ui.autocomplete, {
3320 escapeRegex: function( value ) {
3321 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
3322 },
3323 filter: function( array, term ) {
3324 var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
3325 return $.grep( array, function( value ) {
3326 return matcher.test( value.label || value.value || value );
3327 });
3328 }
3329});
3330
3331// live region extension, adding a `messages` option
3332// NOTE: This is an experimental API. We are still investigating
3333// a full solution for string manipulation and internationalization.
3334$.widget( "ui.autocomplete", $.ui.autocomplete, {
3335 options: {
3336 messages: {
3337 noResults: "No search results.",
3338 results: function( amount ) {
3339 return amount + ( amount > 1 ? " results are" : " result is" ) +
3340 " available, use up and down arrow keys to navigate.";
3341 }
3342 }
3343 },
3344
3345 __response: function( content ) {
3346 var message;
3347 this._superApply( arguments );
3348 if ( this.options.disabled || this.cancelSearch ) {
3349 return;
3350 }
3351 if ( content && content.length ) {
3352 message = this.options.messages.results( content.length );
3353 } else {
3354 message = this.options.messages.noResults;
3355 }
3356 this.liveRegion.children().hide();
3357 $( "<div>" ).text( message ).appendTo( this.liveRegion );
3358 }
3359});
3360
3361var autocomplete = $.ui.autocomplete;
3362
3363
3364/*!
3365 * jQuery UI Button 1.11.2
3366 * http://jqueryui.com
3367 *
3368 * Copyright 2014 jQuery Foundation and other contributors
3369 * Released under the MIT license.
3370 * http://jquery.org/license
3371 *
3372 * http://api.jqueryui.com/button/
3373 */
3374
3375
3376var lastActive,
3377 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
3378 typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
3379 formResetHandler = function() {
3380 var form = $( this );
3381 setTimeout(function() {
3382 form.find( ":ui-button" ).button( "refresh" );
3383 }, 1 );
3384 },
3385 radioGroup = function( radio ) {
3386 var name = radio.name,
3387 form = radio.form,
3388 radios = $( [] );
3389 if ( name ) {
3390 name = name.replace( /'/g, "\\'" );
3391 if ( form ) {
3392 radios = $( form ).find( "[name='" + name + "'][type=radio]" );
3393 } else {
3394 radios = $( "[name='" + name + "'][type=radio]", radio.ownerDocument )
3395 .filter(function() {
3396 return !this.form;
3397 });
3398 }
3399 }
3400 return radios;
3401 };
3402
3403$.widget( "ui.button", {
3404 version: "1.11.2",
3405 defaultElement: "<button>",
3406 options: {
3407 disabled: null,
3408 text: true,
3409 label: null,
3410 icons: {
3411 primary: null,
3412 secondary: null
3413 }
3414 },
3415 _create: function() {
3416 this.element.closest( "form" )
3417 .unbind( "reset" + this.eventNamespace )
3418 .bind( "reset" + this.eventNamespace, formResetHandler );
3419
3420 if ( typeof this.options.disabled !== "boolean" ) {
3421 this.options.disabled = !!this.element.prop( "disabled" );
3422 } else {
3423 this.element.prop( "disabled", this.options.disabled );
3424 }
3425
3426 this._determineButtonType();
3427 this.hasTitle = !!this.buttonElement.attr( "title" );
3428
3429 var that = this,
3430 options = this.options,
3431 toggleButton = this.type === "checkbox" || this.type === "radio",
3432 activeClass = !toggleButton ? "ui-state-active" : "";
3433
3434 if ( options.label === null ) {
3435 options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
3436 }
3437
3438 this._hoverable( this.buttonElement );
3439
3440 this.buttonElement
3441 .addClass( baseClasses )
3442 .attr( "role", "button" )
3443 .bind( "mouseenter" + this.eventNamespace, function() {
3444 if ( options.disabled ) {
3445 return;
3446 }
3447 if ( this === lastActive ) {
3448 $( this ).addClass( "ui-state-active" );
3449 }
3450 })
3451 .bind( "mouseleave" + this.eventNamespace, function() {
3452 if ( options.disabled ) {
3453 return;
3454 }
3455 $( this ).removeClass( activeClass );
3456 })
3457 .bind( "click" + this.eventNamespace, function( event ) {
3458 if ( options.disabled ) {
3459 event.preventDefault();
3460 event.stopImmediatePropagation();
3461 }
3462 });
3463
3464 // Can't use _focusable() because the element that receives focus
3465 // and the element that gets the ui-state-focus class are different
3466 this._on({
3467 focus: function() {
3468 this.buttonElement.addClass( "ui-state-focus" );
3469 },
3470 blur: function() {
3471 this.buttonElement.removeClass( "ui-state-focus" );
3472 }
3473 });
3474
3475 if ( toggleButton ) {
3476 this.element.bind( "change" + this.eventNamespace, function() {
3477 that.refresh();
3478 });
3479 }
3480
3481 if ( this.type === "checkbox" ) {
3482 this.buttonElement.bind( "click" + this.eventNamespace, function() {
3483 if ( options.disabled ) {
3484 return false;
3485 }
3486 });
3487 } else if ( this.type === "radio" ) {
3488 this.buttonElement.bind( "click" + this.eventNamespace, function() {
3489 if ( options.disabled ) {
3490 return false;
3491 }
3492 $( this ).addClass( "ui-state-active" );
3493 that.buttonElement.attr( "aria-pressed", "true" );
3494
3495 var radio = that.element[ 0 ];
3496 radioGroup( radio )
3497 .not( radio )
3498 .map(function() {
3499 return $( this ).button( "widget" )[ 0 ];
3500 })
3501 .removeClass( "ui-state-active" )
3502 .attr( "aria-pressed", "false" );
3503 });
3504 } else {
3505 this.buttonElement
3506 .bind( "mousedown" + this.eventNamespace, function() {
3507 if ( options.disabled ) {
3508 return false;
3509 }
3510 $( this ).addClass( "ui-state-active" );
3511 lastActive = this;
3512 that.document.one( "mouseup", function() {
3513 lastActive = null;
3514 });
3515 })
3516 .bind( "mouseup" + this.eventNamespace, function() {
3517 if ( options.disabled ) {
3518 return false;
3519 }
3520 $( this ).removeClass( "ui-state-active" );
3521 })
3522 .bind( "keydown" + this.eventNamespace, function(event) {
3523 if ( options.disabled ) {
3524 return false;
3525 }
3526 if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
3527 $( this ).addClass( "ui-state-active" );
3528 }
3529 })
3530 // see #8559, we bind to blur here in case the button element loses
3531 // focus between keydown and keyup, it would be left in an "active" state
3532 .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
3533 $( this ).removeClass( "ui-state-active" );
3534 });
3535
3536 if ( this.buttonElement.is("a") ) {
3537 this.buttonElement.keyup(function(event) {
3538 if ( event.keyCode === $.ui.keyCode.SPACE ) {
3539 // TODO pass through original event correctly (just as 2nd argument doesn't work)
3540 $( this ).click();
3541 }
3542 });
3543 }
3544 }
3545
3546 this._setOption( "disabled", options.disabled );
3547 this._resetButton();
3548 },
3549
3550 _determineButtonType: function() {
3551 var ancestor, labelSelector, checked;
3552
3553 if ( this.element.is("[type=checkbox]") ) {
3554 this.type = "checkbox";
3555 } else if ( this.element.is("[type=radio]") ) {
3556 this.type = "radio";
3557 } else if ( this.element.is("input") ) {
3558 this.type = "input";
3559 } else {
3560 this.type = "button";
3561 }
3562
3563 if ( this.type === "checkbox" || this.type === "radio" ) {
3564 // we don't search against the document in case the element
3565 // is disconnected from the DOM
3566 ancestor = this.element.parents().last();
3567 labelSelector = "label[for='" + this.element.attr("id") + "']";
3568 this.buttonElement = ancestor.find( labelSelector );
3569 if ( !this.buttonElement.length ) {
3570 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
3571 this.buttonElement = ancestor.filter( labelSelector );
3572 if ( !this.buttonElement.length ) {
3573 this.buttonElement = ancestor.find( labelSelector );
3574 }
3575 }
3576 this.element.addClass( "ui-helper-hidden-accessible" );
3577
3578 checked = this.element.is( ":checked" );
3579 if ( checked ) {
3580 this.buttonElement.addClass( "ui-state-active" );
3581 }
3582 this.buttonElement.prop( "aria-pressed", checked );
3583 } else {
3584 this.buttonElement = this.element;
3585 }
3586 },
3587
3588 widget: function() {
3589 return this.buttonElement;
3590 },
3591
3592 _destroy: function() {
3593 this.element
3594 .removeClass( "ui-helper-hidden-accessible" );
3595 this.buttonElement
3596 .removeClass( baseClasses + " ui-state-active " + typeClasses )
3597 .removeAttr( "role" )
3598 .removeAttr( "aria-pressed" )
3599 .html( this.buttonElement.find(".ui-button-text").html() );
3600
3601 if ( !this.hasTitle ) {
3602 this.buttonElement.removeAttr( "title" );
3603 }
3604 },
3605
3606 _setOption: function( key, value ) {
3607 this._super( key, value );
3608 if ( key === "disabled" ) {
3609 this.widget().toggleClass( "ui-state-disabled", !!value );
3610 this.element.prop( "disabled", !!value );
3611 if ( value ) {
3612 if ( this.type === "checkbox" || this.type === "radio" ) {
3613 this.buttonElement.removeClass( "ui-state-focus" );
3614 } else {
3615 this.buttonElement.removeClass( "ui-state-focus ui-state-active" );
3616 }
3617 }
3618 return;
3619 }
3620 this._resetButton();
3621 },
3622
3623 refresh: function() {
3624 //See #8237 & #8828
3625 var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
3626
3627 if ( isDisabled !== this.options.disabled ) {
3628 this._setOption( "disabled", isDisabled );
3629 }
3630 if ( this.type === "radio" ) {
3631 radioGroup( this.element[0] ).each(function() {
3632 if ( $( this ).is( ":checked" ) ) {
3633 $( this ).button( "widget" )
3634 .addClass( "ui-state-active" )
3635 .attr( "aria-pressed", "true" );
3636 } else {
3637 $( this ).button( "widget" )
3638 .removeClass( "ui-state-active" )
3639 .attr( "aria-pressed", "false" );
3640 }
3641 });
3642 } else if ( this.type === "checkbox" ) {
3643 if ( this.element.is( ":checked" ) ) {
3644 this.buttonElement
3645 .addClass( "ui-state-active" )
3646 .attr( "aria-pressed", "true" );
3647 } else {
3648 this.buttonElement
3649 .removeClass( "ui-state-active" )
3650 .attr( "aria-pressed", "false" );
3651 }
3652 }
3653 },
3654
3655 _resetButton: function() {
3656 if ( this.type === "input" ) {
3657 if ( this.options.label ) {
3658 this.element.val( this.options.label );
3659 }
3660 return;
3661 }
3662 var buttonElement = this.buttonElement.removeClass( typeClasses ),
3663 buttonText = $( "<span></span>", this.document[0] )
3664 .addClass( "ui-button-text" )
3665 .html( this.options.label )
3666 .appendTo( buttonElement.empty() )
3667 .text(),
3668 icons = this.options.icons,
3669 multipleIcons = icons.primary && icons.secondary,
3670 buttonClasses = [];
3671
3672 if ( icons.primary || icons.secondary ) {
3673 if ( this.options.text ) {
3674 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
3675 }
3676
3677 if ( icons.primary ) {
3678 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
3679 }
3680
3681 if ( icons.secondary ) {
3682 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
3683 }
3684
3685 if ( !this.options.text ) {
3686 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
3687
3688 if ( !this.hasTitle ) {
3689 buttonElement.attr( "title", $.trim( buttonText ) );
3690 }
3691 }
3692 } else {
3693 buttonClasses.push( "ui-button-text-only" );
3694 }
3695 buttonElement.addClass( buttonClasses.join( " " ) );
3696 }
3697});
3698
3699$.widget( "ui.buttonset", {
3700 version: "1.11.2",
3701 options: {
3702 items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
3703 },
3704
3705 _create: function() {
3706 this.element.addClass( "ui-buttonset" );
3707 },
3708
3709 _init: function() {
3710 this.refresh();
3711 },
3712
3713 _setOption: function( key, value ) {
3714 if ( key === "disabled" ) {
3715 this.buttons.button( "option", key, value );
3716 }
3717
3718 this._super( key, value );
3719 },
3720
3721 refresh: function() {
3722 var rtl = this.element.css( "direction" ) === "rtl",
3723 allButtons = this.element.find( this.options.items ),
3724 existingButtons = allButtons.filter( ":ui-button" );
3725
3726 // Initialize new buttons
3727 allButtons.not( ":ui-button" ).button();
3728
3729 // Refresh existing buttons
3730 existingButtons.button( "refresh" );
3731
3732 this.buttons = allButtons
3733 .map(function() {
3734 return $( this ).button( "widget" )[ 0 ];
3735 })
3736 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
3737 .filter( ":first" )
3738 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
3739 .end()
3740 .filter( ":last" )
3741 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
3742 .end()
3743 .end();
3744 },
3745
3746 _destroy: function() {
3747 this.element.removeClass( "ui-buttonset" );
3748 this.buttons
3749 .map(function() {
3750 return $( this ).button( "widget" )[ 0 ];
3751 })
3752 .removeClass( "ui-corner-left ui-corner-right" )
3753 .end()
3754 .button( "destroy" );
3755 }
3756});
3757
3758var button = $.ui.button;
3759
3760
3761/*!
3762 * jQuery UI Datepicker 1.11.2
3763 * http://jqueryui.com
3764 *
3765 * Copyright 2014 jQuery Foundation and other contributors
3766 * Released under the MIT license.
3767 * http://jquery.org/license
3768 *
3769 * http://api.jqueryui.com/datepicker/
3770 */
3771
3772
3773$.extend($.ui, { datepicker: { version: "1.11.2" } });
3774
3775var datepicker_instActive;
3776
3777function datepicker_getZindex( elem ) {
3778 var position, value;
3779 while ( elem.length && elem[ 0 ] !== document ) {
3780 // Ignore z-index if position is set to a value where z-index is ignored by the browser
3781 // This makes behavior of this function consistent across browsers
3782 // WebKit always returns auto if the element is positioned
3783 position = elem.css( "position" );
3784 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
3785 // IE returns 0 when zIndex is not specified
3786 // other browsers return a string
3787 // we ignore the case of nested elements with an explicit value of 0
3788 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
3789 value = parseInt( elem.css( "zIndex" ), 10 );
3790 if ( !isNaN( value ) && value !== 0 ) {
3791 return value;
3792 }
3793 }
3794 elem = elem.parent();
3795 }
3796
3797 return 0;
3798}
3799/* Date picker manager.
3800 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
3801 Settings for (groups of) date pickers are maintained in an instance object,
3802 allowing multiple different settings on the same page. */
3803
3804function Datepicker() {
3805 this._curInst = null; // The current instance in use
3806 this._keyEvent = false; // If the last event was a key event
3807 this._disabledInputs = []; // List of date picker inputs that have been disabled
3808 this._datepickerShowing = false; // True if the popup picker is showing , false if not
3809 this._inDialog = false; // True if showing within a "dialog", false if not
3810 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
3811 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
3812 this._appendClass = "ui-datepicker-append"; // The name of the append marker class
3813 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
3814 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
3815 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
3816 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
3817 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
3818 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
3819 this.regional = []; // Available regional settings, indexed by language code
3820 this.regional[""] = { // Default regional settings
3821 closeText: "Done", // Display text for close link
3822 prevText: "Prev", // Display text for previous month link
3823 nextText: "Next", // Display text for next month link
3824 currentText: "Today", // Display text for current month link
3825 monthNames: ["January","February","March","April","May","June",
3826 "July","August","September","October","November","December"], // Names of months for drop-down and formatting
3827 monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
3828 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
3829 dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
3830 dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
3831 weekHeader: "Wk", // Column header for week of the year
3832 dateFormat: "mm/dd/yy", // See format options on parseDate
3833 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
3834 isRTL: false, // True if right-to-left language, false if left-to-right
3835 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
3836 yearSuffix: "" // Additional text to append to the year in the month headers
3837 };
3838 this._defaults = { // Global defaults for all the date picker instances
3839 showOn: "focus", // "focus" for popup on focus,
3840 // "button" for trigger button, or "both" for either
3841 showAnim: "fadeIn", // Name of jQuery animation for popup
3842 showOptions: {}, // Options for enhanced animations
3843 defaultDate: null, // Used when field is blank: actual date,
3844 // +/-number for offset from today, null for today
3845 appendText: "", // Display text following the input box, e.g. showing the format
3846 buttonText: "...", // Text for trigger button
3847 buttonImage: "", // URL for trigger button image
3848 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
3849 hideIfNoPrevNext: false, // True to hide next/previous month links
3850 // if not applicable, false to just disable them
3851 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
3852 gotoCurrent: false, // True if today link goes back to current selection instead
3853 changeMonth: false, // True if month can be selected directly, false if only prev/next
3854 changeYear: false, // True if year can be selected directly, false if only prev/next
3855 yearRange: "c-10:c+10", // Range of years to display in drop-down,
3856 // either relative to today's year (-nn:+nn), relative to currently displayed year
3857 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
3858 showOtherMonths: false, // True to show dates in other months, false to leave blank
3859 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
3860 showWeek: false, // True to show week of the year, false to not show it
3861 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
3862 // takes a Date and returns the number of the week for it
3863 shortYearCutoff: "+10", // Short year values < this are in the current century,
3864 // > this are in the previous century,
3865 // string value starting with "+" for current year + value
3866 minDate: null, // The earliest selectable date, or null for no limit
3867 maxDate: null, // The latest selectable date, or null for no limit
3868 duration: "fast", // Duration of display/closure
3869 beforeShowDay: null, // Function that takes a date and returns an array with
3870 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
3871 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
3872 beforeShow: null, // Function that takes an input field and
3873 // returns a set of custom settings for the date picker
3874 onSelect: null, // Define a callback function when a date is selected
3875 onChangeMonthYear: null, // Define a callback function when the month or year is changed
3876 onClose: null, // Define a callback function when the datepicker is closed
3877 numberOfMonths: 1, // Number of months to show at a time
3878 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
3879 stepMonths: 1, // Number of months to step back/forward
3880 stepBigMonths: 12, // Number of months to step back/forward for the big links
3881 altField: "", // Selector for an alternate field to store selected dates into
3882 altFormat: "", // The date format to use for the alternate field
3883 constrainInput: true, // The input is constrained by the current date format
3884 showButtonPanel: false, // True to show button panel, false to not show it
3885 autoSize: false, // True to size the input for the date format, false to leave as is
3886 disabled: false // The initial disabled state
3887 };
3888 $.extend(this._defaults, this.regional[""]);
3889 this.regional.en = $.extend( true, {}, this.regional[ "" ]);
3890 this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
3891 this.dpDiv = datepicker_bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
3892}
3893
3894$.extend(Datepicker.prototype, {
3895 /* Class name added to elements to indicate already configured with a date picker. */
3896 markerClassName: "hasDatepicker",
3897
3898 //Keep track of the maximum number of rows displayed (see #7043)
3899 maxRows: 4,
3900
3901 // TODO rename to "widget" when switching to widget factory
3902 _widgetDatepicker: function() {
3903 return this.dpDiv;
3904 },
3905
3906 /* Override the default settings for all instances of the date picker.
3907 * @param settings object - the new settings to use as defaults (anonymous object)
3908 * @return the manager object
3909 */
3910 setDefaults: function(settings) {
3911 datepicker_extendRemove(this._defaults, settings || {});
3912 return this;
3913 },
3914
3915 /* Attach the date picker to a jQuery selection.
3916 * @param target element - the target input field or division or span
3917 * @param settings object - the new settings to use for this date picker instance (anonymous)
3918 */
3919 _attachDatepicker: function(target, settings) {
3920 var nodeName, inline, inst;
3921 nodeName = target.nodeName.toLowerCase();
3922 inline = (nodeName === "div" || nodeName === "span");
3923 if (!target.id) {
3924 this.uuid += 1;
3925 target.id = "dp" + this.uuid;
3926 }
3927 inst = this._newInst($(target), inline);
3928 inst.settings = $.extend({}, settings || {});
3929 if (nodeName === "input") {
3930 this._connectDatepicker(target, inst);
3931 } else if (inline) {
3932 this._inlineDatepicker(target, inst);
3933 }
3934 },
3935
3936 /* Create a new instance object. */
3937 _newInst: function(target, inline) {
3938 var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
3939 return {id: id, input: target, // associated target
3940 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
3941 drawMonth: 0, drawYear: 0, // month being drawn
3942 inline: inline, // is datepicker inline or not
3943 dpDiv: (!inline ? this.dpDiv : // presentation div
3944 datepicker_bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
3945 },
3946
3947 /* Attach the date picker to an input field. */
3948 _connectDatepicker: function(target, inst) {
3949 var input = $(target);
3950 inst.append = $([]);
3951 inst.trigger = $([]);
3952 if (input.hasClass(this.markerClassName)) {
3953 return;
3954 }
3955 this._attachments(input, inst);
3956 input.addClass(this.markerClassName).keydown(this._doKeyDown).
3957 keypress(this._doKeyPress).keyup(this._doKeyUp);
3958 this._autoSize(inst);
3959 $.data(target, "datepicker", inst);
3960 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
3961 if( inst.settings.disabled ) {
3962 this._disableDatepicker( target );
3963 }
3964 },
3965
3966 /* Make attachments based on settings. */
3967 _attachments: function(input, inst) {
3968 var showOn, buttonText, buttonImage,
3969 appendText = this._get(inst, "appendText"),
3970 isRTL = this._get(inst, "isRTL");
3971
3972 if (inst.append) {
3973 inst.append.remove();
3974 }
3975 if (appendText) {
3976 inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
3977 input[isRTL ? "before" : "after"](inst.append);
3978 }
3979
3980 input.unbind("focus", this._showDatepicker);
3981
3982 if (inst.trigger) {
3983 inst.trigger.remove();
3984 }
3985
3986 showOn = this._get(inst, "showOn");
3987 if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
3988 input.focus(this._showDatepicker);
3989 }
3990 if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
3991 buttonText = this._get(inst, "buttonText");
3992 buttonImage = this._get(inst, "buttonImage");
3993 inst.trigger = $(this._get(inst, "buttonImageOnly") ?
3994 $("<img/>").addClass(this._triggerClass).
3995 attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
3996 $("<button type='button'></button>").addClass(this._triggerClass).
3997 html(!buttonImage ? buttonText : $("<img/>").attr(
3998 { src:buttonImage, alt:buttonText, title:buttonText })));
3999 input[isRTL ? "before" : "after"](inst.trigger);
4000 inst.trigger.click(function() {
4001 if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
4002 $.datepicker._hideDatepicker();
4003 } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
4004 $.datepicker._hideDatepicker();
4005 $.datepicker._showDatepicker(input[0]);
4006 } else {
4007 $.datepicker._showDatepicker(input[0]);
4008 }
4009 return false;
4010 });
4011 }
4012 },
4013
4014 /* Apply the maximum length for the date format. */
4015 _autoSize: function(inst) {
4016 if (this._get(inst, "autoSize") && !inst.inline) {
4017 var findMax, max, maxI, i,
4018 date = new Date(2009, 12 - 1, 20), // Ensure double digits
4019 dateFormat = this._get(inst, "dateFormat");
4020
4021 if (dateFormat.match(/[DM]/)) {
4022 findMax = function(names) {
4023 max = 0;
4024 maxI = 0;
4025 for (i = 0; i < names.length; i++) {
4026 if (names[i].length > max) {
4027 max = names[i].length;
4028 maxI = i;
4029 }
4030 }
4031 return maxI;
4032 };
4033 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
4034 "monthNames" : "monthNamesShort"))));
4035 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
4036 "dayNames" : "dayNamesShort"))) + 20 - date.getDay());
4037 }
4038 inst.input.attr("size", this._formatDate(inst, date).length);
4039 }
4040 },
4041
4042 /* Attach an inline date picker to a div. */
4043 _inlineDatepicker: function(target, inst) {
4044 var divSpan = $(target);
4045 if (divSpan.hasClass(this.markerClassName)) {
4046 return;
4047 }
4048 divSpan.addClass(this.markerClassName).append(inst.dpDiv);
4049 $.data(target, "datepicker", inst);
4050 this._setDate(inst, this._getDefaultDate(inst), true);
4051 this._updateDatepicker(inst);
4052 this._updateAlternate(inst);
4053 //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
4054 if( inst.settings.disabled ) {
4055 this._disableDatepicker( target );
4056 }
4057 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
4058 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
4059 inst.dpDiv.css( "display", "block" );
4060 },
4061
4062 /* Pop-up the date picker in a "dialog" box.
4063 * @param input element - ignored
4064 * @param date string or Date - the initial date to display
4065 * @param onSelect function - the function to call when a date is selected
4066 * @param settings object - update the dialog date picker instance's settings (anonymous object)
4067 * @param pos int[2] - coordinates for the dialog's position within the screen or
4068 * event - with x/y coordinates or
4069 * leave empty for default (screen centre)
4070 * @return the manager object
4071 */
4072 _dialogDatepicker: function(input, date, onSelect, settings, pos) {
4073 var id, browserWidth, browserHeight, scrollX, scrollY,
4074 inst = this._dialogInst; // internal instance
4075
4076 if (!inst) {
4077 this.uuid += 1;
4078 id = "dp" + this.uuid;
4079 this._dialogInput = $("<input type='text' id='" + id +
4080 "' style='position: absolute; top: -100px; width: 0px;'/>");
4081 this._dialogInput.keydown(this._doKeyDown);
4082 $("body").append(this._dialogInput);
4083 inst = this._dialogInst = this._newInst(this._dialogInput, false);
4084 inst.settings = {};
4085 $.data(this._dialogInput[0], "datepicker", inst);
4086 }
4087 datepicker_extendRemove(inst.settings, settings || {});
4088 date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
4089 this._dialogInput.val(date);
4090
4091 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
4092 if (!this._pos) {
4093 browserWidth = document.documentElement.clientWidth;
4094 browserHeight = document.documentElement.clientHeight;
4095 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
4096 scrollY = document.documentElement.scrollTop || document.body.scrollTop;
4097 this._pos = // should use actual width/height below
4098 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
4099 }
4100
4101 // move input on screen for focus, but hidden behind dialog
4102 this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
4103 inst.settings.onSelect = onSelect;
4104 this._inDialog = true;
4105 this.dpDiv.addClass(this._dialogClass);
4106 this._showDatepicker(this._dialogInput[0]);
4107 if ($.blockUI) {
4108 $.blockUI(this.dpDiv);
4109 }
4110 $.data(this._dialogInput[0], "datepicker", inst);
4111 return this;
4112 },
4113
4114 /* Detach a datepicker from its control.
4115 * @param target element - the target input field or division or span
4116 */
4117 _destroyDatepicker: function(target) {
4118 var nodeName,
4119 $target = $(target),
4120 inst = $.data(target, "datepicker");
4121
4122 if (!$target.hasClass(this.markerClassName)) {
4123 return;
4124 }
4125
4126 nodeName = target.nodeName.toLowerCase();
4127 $.removeData(target, "datepicker");
4128 if (nodeName === "input") {
4129 inst.append.remove();
4130 inst.trigger.remove();
4131 $target.removeClass(this.markerClassName).
4132 unbind("focus", this._showDatepicker).
4133 unbind("keydown", this._doKeyDown).
4134 unbind("keypress", this._doKeyPress).
4135 unbind("keyup", this._doKeyUp);
4136 } else if (nodeName === "div" || nodeName === "span") {
4137 $target.removeClass(this.markerClassName).empty();
4138 }
4139 },
4140
4141 /* Enable the date picker to a jQuery selection.
4142 * @param target element - the target input field or division or span
4143 */
4144 _enableDatepicker: function(target) {
4145 var nodeName, inline,
4146 $target = $(target),
4147 inst = $.data(target, "datepicker");
4148
4149 if (!$target.hasClass(this.markerClassName)) {
4150 return;
4151 }
4152
4153 nodeName = target.nodeName.toLowerCase();
4154 if (nodeName === "input") {
4155 target.disabled = false;
4156 inst.trigger.filter("button").
4157 each(function() { this.disabled = false; }).end().
4158 filter("img").css({opacity: "1.0", cursor: ""});
4159 } else if (nodeName === "div" || nodeName === "span") {
4160 inline = $target.children("." + this._inlineClass);
4161 inline.children().removeClass("ui-state-disabled");
4162 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
4163 prop("disabled", false);
4164 }
4165 this._disabledInputs = $.map(this._disabledInputs,
4166 function(value) { return (value === target ? null : value); }); // delete entry
4167 },
4168
4169 /* Disable the date picker to a jQuery selection.
4170 * @param target element - the target input field or division or span
4171 */
4172 _disableDatepicker: function(target) {
4173 var nodeName, inline,
4174 $target = $(target),
4175 inst = $.data(target, "datepicker");
4176
4177 if (!$target.hasClass(this.markerClassName)) {
4178 return;
4179 }
4180
4181 nodeName = target.nodeName.toLowerCase();
4182 if (nodeName === "input") {
4183 target.disabled = true;
4184 inst.trigger.filter("button").
4185 each(function() { this.disabled = true; }).end().
4186 filter("img").css({opacity: "0.5", cursor: "default"});
4187 } else if (nodeName === "div" || nodeName === "span") {
4188 inline = $target.children("." + this._inlineClass);
4189 inline.children().addClass("ui-state-disabled");
4190 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
4191 prop("disabled", true);
4192 }
4193 this._disabledInputs = $.map(this._disabledInputs,
4194 function(value) { return (value === target ? null : value); }); // delete entry
4195 this._disabledInputs[this._disabledInputs.length] = target;
4196 },
4197
4198 /* Is the first field in a jQuery collection disabled as a datepicker?
4199 * @param target element - the target input field or division or span
4200 * @return boolean - true if disabled, false if enabled
4201 */
4202 _isDisabledDatepicker: function(target) {
4203 if (!target) {
4204 return false;
4205 }
4206 for (var i = 0; i < this._disabledInputs.length; i++) {
4207 if (this._disabledInputs[i] === target) {
4208 return true;
4209 }
4210 }
4211 return false;
4212 },
4213
4214 /* Retrieve the instance data for the target control.
4215 * @param target element - the target input field or division or span
4216 * @return object - the associated instance data
4217 * @throws error if a jQuery problem getting data
4218 */
4219 _getInst: function(target) {
4220 try {
4221 return $.data(target, "datepicker");
4222 }
4223 catch (err) {
4224 throw "Missing instance data for this datepicker";
4225 }
4226 },
4227
4228 /* Update or retrieve the settings for a date picker attached to an input field or division.
4229 * @param target element - the target input field or division or span
4230 * @param name object - the new settings to update or
4231 * string - the name of the setting to change or retrieve,
4232 * when retrieving also "all" for all instance settings or
4233 * "defaults" for all global defaults
4234 * @param value any - the new value for the setting
4235 * (omit if above is an object or to retrieve a value)
4236 */
4237 _optionDatepicker: function(target, name, value) {
4238 var settings, date, minDate, maxDate,
4239 inst = this._getInst(target);
4240
4241 if (arguments.length === 2 && typeof name === "string") {
4242 return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
4243 (inst ? (name === "all" ? $.extend({}, inst.settings) :
4244 this._get(inst, name)) : null));
4245 }
4246
4247 settings = name || {};
4248 if (typeof name === "string") {
4249 settings = {};
4250 settings[name] = value;
4251 }
4252
4253 if (inst) {
4254 if (this._curInst === inst) {
4255 this._hideDatepicker();
4256 }
4257
4258 date = this._getDateDatepicker(target, true);
4259 minDate = this._getMinMaxDate(inst, "min");
4260 maxDate = this._getMinMaxDate(inst, "max");
4261 datepicker_extendRemove(inst.settings, settings);
4262 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
4263 if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
4264 inst.settings.minDate = this._formatDate(inst, minDate);
4265 }
4266 if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
4267 inst.settings.maxDate = this._formatDate(inst, maxDate);
4268 }
4269 if ( "disabled" in settings ) {
4270 if ( settings.disabled ) {
4271 this._disableDatepicker(target);
4272 } else {
4273 this._enableDatepicker(target);
4274 }
4275 }
4276 this._attachments($(target), inst);
4277 this._autoSize(inst);
4278 this._setDate(inst, date);
4279 this._updateAlternate(inst);
4280 this._updateDatepicker(inst);
4281 }
4282 },
4283
4284 // change method deprecated
4285 _changeDatepicker: function(target, name, value) {
4286 this._optionDatepicker(target, name, value);
4287 },
4288
4289 /* Redraw the date picker attached to an input field or division.
4290 * @param target element - the target input field or division or span
4291 */
4292 _refreshDatepicker: function(target) {
4293 var inst = this._getInst(target);
4294 if (inst) {
4295 this._updateDatepicker(inst);
4296 }
4297 },
4298
4299 /* Set the dates for a jQuery selection.
4300 * @param target element - the target input field or division or span
4301 * @param date Date - the new date
4302 */
4303 _setDateDatepicker: function(target, date) {
4304 var inst = this._getInst(target);
4305 if (inst) {
4306 this._setDate(inst, date);
4307 this._updateDatepicker(inst);
4308 this._updateAlternate(inst);
4309 }
4310 },
4311
4312 /* Get the date(s) for the first entry in a jQuery selection.
4313 * @param target element - the target input field or division or span
4314 * @param noDefault boolean - true if no default date is to be used
4315 * @return Date - the current date
4316 */
4317 _getDateDatepicker: function(target, noDefault) {
4318 var inst = this._getInst(target);
4319 if (inst && !inst.inline) {
4320 this._setDateFromField(inst, noDefault);
4321 }
4322 return (inst ? this._getDate(inst) : null);
4323 },
4324
4325 /* Handle keystrokes. */
4326 _doKeyDown: function(event) {
4327 var onSelect, dateStr, sel,
4328 inst = $.datepicker._getInst(event.target),
4329 handled = true,
4330 isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
4331
4332 inst._keyEvent = true;
4333 if ($.datepicker._datepickerShowing) {
4334 switch (event.keyCode) {
4335 case 9: $.datepicker._hideDatepicker();
4336 handled = false;
4337 break; // hide on tab out
4338 case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
4339 $.datepicker._currentClass + ")", inst.dpDiv);
4340 if (sel[0]) {
4341 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
4342 }
4343
4344 onSelect = $.datepicker._get(inst, "onSelect");
4345 if (onSelect) {
4346 dateStr = $.datepicker._formatDate(inst);
4347
4348 // trigger custom callback
4349 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
4350 } else {
4351 $.datepicker._hideDatepicker();
4352 }
4353
4354 return false; // don't submit the form
4355 case 27: $.datepicker._hideDatepicker();
4356 break; // hide on escape
4357 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4358 -$.datepicker._get(inst, "stepBigMonths") :
4359 -$.datepicker._get(inst, "stepMonths")), "M");
4360 break; // previous month/year on page up/+ ctrl
4361 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4362 +$.datepicker._get(inst, "stepBigMonths") :
4363 +$.datepicker._get(inst, "stepMonths")), "M");
4364 break; // next month/year on page down/+ ctrl
4365 case 35: if (event.ctrlKey || event.metaKey) {
4366 $.datepicker._clearDate(event.target);
4367 }
4368 handled = event.ctrlKey || event.metaKey;
4369 break; // clear on ctrl or command +end
4370 case 36: if (event.ctrlKey || event.metaKey) {
4371 $.datepicker._gotoToday(event.target);
4372 }
4373 handled = event.ctrlKey || event.metaKey;
4374 break; // current on ctrl or command +home
4375 case 37: if (event.ctrlKey || event.metaKey) {
4376 $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
4377 }
4378 handled = event.ctrlKey || event.metaKey;
4379 // -1 day on ctrl or command +left
4380 if (event.originalEvent.altKey) {
4381 $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4382 -$.datepicker._get(inst, "stepBigMonths") :
4383 -$.datepicker._get(inst, "stepMonths")), "M");
4384 }
4385 // next month/year on alt +left on Mac
4386 break;
4387 case 38: if (event.ctrlKey || event.metaKey) {
4388 $.datepicker._adjustDate(event.target, -7, "D");
4389 }
4390 handled = event.ctrlKey || event.metaKey;
4391 break; // -1 week on ctrl or command +up
4392 case 39: if (event.ctrlKey || event.metaKey) {
4393 $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
4394 }
4395 handled = event.ctrlKey || event.metaKey;
4396 // +1 day on ctrl or command +right
4397 if (event.originalEvent.altKey) {
4398 $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4399 +$.datepicker._get(inst, "stepBigMonths") :
4400 +$.datepicker._get(inst, "stepMonths")), "M");
4401 }
4402 // next month/year on alt +right
4403 break;
4404 case 40: if (event.ctrlKey || event.metaKey) {
4405 $.datepicker._adjustDate(event.target, +7, "D");
4406 }
4407 handled = event.ctrlKey || event.metaKey;
4408 break; // +1 week on ctrl or command +down
4409 default: handled = false;
4410 }
4411 } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
4412 $.datepicker._showDatepicker(this);
4413 } else {
4414 handled = false;
4415 }
4416
4417 if (handled) {
4418 event.preventDefault();
4419 event.stopPropagation();
4420 }
4421 },
4422
4423 /* Filter entered characters - based on date format. */
4424 _doKeyPress: function(event) {
4425 var chars, chr,
4426 inst = $.datepicker._getInst(event.target);
4427
4428 if ($.datepicker._get(inst, "constrainInput")) {
4429 chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
4430 chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
4431 return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
4432 }
4433 },
4434
4435 /* Synchronise manual entry and field/alternate field. */
4436 _doKeyUp: function(event) {
4437 var date,
4438 inst = $.datepicker._getInst(event.target);
4439
4440 if (inst.input.val() !== inst.lastVal) {
4441 try {
4442 date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
4443 (inst.input ? inst.input.val() : null),
4444 $.datepicker._getFormatConfig(inst));
4445
4446 if (date) { // only if valid
4447 $.datepicker._setDateFromField(inst);
4448 $.datepicker._updateAlternate(inst);
4449 $.datepicker._updateDatepicker(inst);
4450 }
4451 }
4452 catch (err) {
4453 }
4454 }
4455 return true;
4456 },
4457
4458 /* Pop-up the date picker for a given input field.
4459 * If false returned from beforeShow event handler do not show.
4460 * @param input element - the input field attached to the date picker or
4461 * event - if triggered by focus
4462 */
4463 _showDatepicker: function(input) {
4464 input = input.target || input;
4465 if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
4466 input = $("input", input.parentNode)[0];
4467 }
4468
4469 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
4470 return;
4471 }
4472
4473 var inst, beforeShow, beforeShowSettings, isFixed,
4474 offset, showAnim, duration;
4475
4476 inst = $.datepicker._getInst(input);
4477 if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
4478 $.datepicker._curInst.dpDiv.stop(true, true);
4479 if ( inst && $.datepicker._datepickerShowing ) {
4480 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
4481 }
4482 }
4483
4484 beforeShow = $.datepicker._get(inst, "beforeShow");
4485 beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
4486 if(beforeShowSettings === false){
4487 return;
4488 }
4489 datepicker_extendRemove(inst.settings, beforeShowSettings);
4490
4491 inst.lastVal = null;
4492 $.datepicker._lastInput = input;
4493 $.datepicker._setDateFromField(inst);
4494
4495 if ($.datepicker._inDialog) { // hide cursor
4496 input.value = "";
4497 }
4498 if (!$.datepicker._pos) { // position below input
4499 $.datepicker._pos = $.datepicker._findPos(input);
4500 $.datepicker._pos[1] += input.offsetHeight; // add the height
4501 }
4502
4503 isFixed = false;
4504 $(input).parents().each(function() {
4505 isFixed |= $(this).css("position") === "fixed";
4506 return !isFixed;
4507 });
4508
4509 offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
4510 $.datepicker._pos = null;
4511 //to avoid flashes on Firefox
4512 inst.dpDiv.empty();
4513 // determine sizing offscreen
4514 inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
4515 $.datepicker._updateDatepicker(inst);
4516 // fix width for dynamic number of date pickers
4517 // and adjust position before showing
4518 offset = $.datepicker._checkOffset(inst, offset, isFixed);
4519 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
4520 "static" : (isFixed ? "fixed" : "absolute")), display: "none",
4521 left: offset.left + "px", top: offset.top + "px"});
4522
4523 if (!inst.inline) {
4524 showAnim = $.datepicker._get(inst, "showAnim");
4525 duration = $.datepicker._get(inst, "duration");
4526 inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
4527 $.datepicker._datepickerShowing = true;
4528
4529 if ( $.effects && $.effects.effect[ showAnim ] ) {
4530 inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
4531 } else {
4532 inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
4533 }
4534
4535 if ( $.datepicker._shouldFocusInput( inst ) ) {
4536 inst.input.focus();
4537 }
4538
4539 $.datepicker._curInst = inst;
4540 }
4541 },
4542
4543 /* Generate the date picker content. */
4544 _updateDatepicker: function(inst) {
4545 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
4546 datepicker_instActive = inst; // for delegate hover events
4547 inst.dpDiv.empty().append(this._generateHTML(inst));
4548 this._attachHandlers(inst);
4549
4550 var origyearshtml,
4551 numMonths = this._getNumberOfMonths(inst),
4552 cols = numMonths[1],
4553 width = 17,
4554 activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" );
4555
4556 if ( activeCell.length > 0 ) {
4557 datepicker_handleMouseover.apply( activeCell.get( 0 ) );
4558 }
4559
4560 inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
4561 if (cols > 1) {
4562 inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
4563 }
4564 inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
4565 "Class"]("ui-datepicker-multi");
4566 inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
4567 "Class"]("ui-datepicker-rtl");
4568
4569 if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
4570 inst.input.focus();
4571 }
4572
4573 // deffered render of the years select (to avoid flashes on Firefox)
4574 if( inst.yearshtml ){
4575 origyearshtml = inst.yearshtml;
4576 setTimeout(function(){
4577 //assure that inst.yearshtml didn't change.
4578 if( origyearshtml === inst.yearshtml && inst.yearshtml ){
4579 inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
4580 }
4581 origyearshtml = inst.yearshtml = null;
4582 }, 0);
4583 }
4584 },
4585
4586 // #6694 - don't focus the input if it's already focused
4587 // this breaks the change event in IE
4588 // Support: IE and jQuery <1.9
4589 _shouldFocusInput: function( inst ) {
4590 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
4591 },
4592
4593 /* Check positioning to remain on screen. */
4594 _checkOffset: function(inst, offset, isFixed) {
4595 var dpWidth = inst.dpDiv.outerWidth(),
4596 dpHeight = inst.dpDiv.outerHeight(),
4597 inputWidth = inst.input ? inst.input.outerWidth() : 0,
4598 inputHeight = inst.input ? inst.input.outerHeight() : 0,
4599 viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
4600 viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
4601
4602 offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
4603 offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
4604 offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
4605
4606 // now check if datepicker is showing outside window viewport - move to a better place if so.
4607 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
4608 Math.abs(offset.left + dpWidth - viewWidth) : 0);
4609 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
4610 Math.abs(dpHeight + inputHeight) : 0);
4611
4612 return offset;
4613 },
4614
4615 /* Find an object's position on the screen. */
4616 _findPos: function(obj) {
4617 var position,
4618 inst = this._getInst(obj),
4619 isRTL = this._get(inst, "isRTL");
4620
4621 while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
4622 obj = obj[isRTL ? "previousSibling" : "nextSibling"];
4623 }
4624
4625 position = $(obj).offset();
4626 return [position.left, position.top];
4627 },
4628
4629 /* Hide the date picker from view.
4630 * @param input element - the input field attached to the date picker
4631 */
4632 _hideDatepicker: function(input) {
4633 var showAnim, duration, postProcess, onClose,
4634 inst = this._curInst;
4635
4636 if (!inst || (input && inst !== $.data(input, "datepicker"))) {
4637 return;
4638 }
4639
4640 if (this._datepickerShowing) {
4641 showAnim = this._get(inst, "showAnim");
4642 duration = this._get(inst, "duration");
4643 postProcess = function() {
4644 $.datepicker._tidyDialog(inst);
4645 };
4646
4647 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
4648 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
4649 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
4650 } else {
4651 inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
4652 (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
4653 }
4654
4655 if (!showAnim) {
4656 postProcess();
4657 }
4658 this._datepickerShowing = false;
4659
4660 onClose = this._get(inst, "onClose");
4661 if (onClose) {
4662 onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
4663 }
4664
4665 this._lastInput = null;
4666 if (this._inDialog) {
4667 this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
4668 if ($.blockUI) {
4669 $.unblockUI();
4670 $("body").append(this.dpDiv);
4671 }
4672 }
4673 this._inDialog = false;
4674 }
4675 },
4676
4677 /* Tidy up after a dialog display. */
4678 _tidyDialog: function(inst) {
4679 inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
4680 },
4681
4682 /* Close date picker if clicked elsewhere. */
4683 _checkExternalClick: function(event) {
4684 if (!$.datepicker._curInst) {
4685 return;
4686 }
4687
4688 var $target = $(event.target),
4689 inst = $.datepicker._getInst($target[0]);
4690
4691 if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
4692 $target.parents("#" + $.datepicker._mainDivId).length === 0 &&
4693 !$target.hasClass($.datepicker.markerClassName) &&
4694 !$target.closest("." + $.datepicker._triggerClass).length &&
4695 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
4696 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
4697 $.datepicker._hideDatepicker();
4698 }
4699 },
4700
4701 /* Adjust one of the date sub-fields. */
4702 _adjustDate: function(id, offset, period) {
4703 var target = $(id),
4704 inst = this._getInst(target[0]);
4705
4706 if (this._isDisabledDatepicker(target[0])) {
4707 return;
4708 }
4709 this._adjustInstDate(inst, offset +
4710 (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
4711 period);
4712 this._updateDatepicker(inst);
4713 },
4714
4715 /* Action for current link. */
4716 _gotoToday: function(id) {
4717 var date,
4718 target = $(id),
4719 inst = this._getInst(target[0]);
4720
4721 if (this._get(inst, "gotoCurrent") && inst.currentDay) {
4722 inst.selectedDay = inst.currentDay;
4723 inst.drawMonth = inst.selectedMonth = inst.currentMonth;
4724 inst.drawYear = inst.selectedYear = inst.currentYear;
4725 } else {
4726 date = new Date();
4727 inst.selectedDay = date.getDate();
4728 inst.drawMonth = inst.selectedMonth = date.getMonth();
4729 inst.drawYear = inst.selectedYear = date.getFullYear();
4730 }
4731 this._notifyChange(inst);
4732 this._adjustDate(target);
4733 },
4734
4735 /* Action for selecting a new month/year. */
4736 _selectMonthYear: function(id, select, period) {
4737 var target = $(id),
4738 inst = this._getInst(target[0]);
4739
4740 inst["selected" + (period === "M" ? "Month" : "Year")] =
4741 inst["draw" + (period === "M" ? "Month" : "Year")] =
4742 parseInt(select.options[select.selectedIndex].value,10);
4743
4744 this._notifyChange(inst);
4745 this._adjustDate(target);
4746 },
4747
4748 /* Action for selecting a day. */
4749 _selectDay: function(id, month, year, td) {
4750 var inst,
4751 target = $(id);
4752
4753 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
4754 return;
4755 }
4756
4757 inst = this._getInst(target[0]);
4758 inst.selectedDay = inst.currentDay = $("a", td).html();
4759 inst.selectedMonth = inst.currentMonth = month;
4760 inst.selectedYear = inst.currentYear = year;
4761 this._selectDate(id, this._formatDate(inst,
4762 inst.currentDay, inst.currentMonth, inst.currentYear));
4763 },
4764
4765 /* Erase the input field and hide the date picker. */
4766 _clearDate: function(id) {
4767 var target = $(id);
4768 this._selectDate(target, "");
4769 },
4770
4771 /* Update the input field with the selected date. */
4772 _selectDate: function(id, dateStr) {
4773 var onSelect,
4774 target = $(id),
4775 inst = this._getInst(target[0]);
4776
4777 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
4778 if (inst.input) {
4779 inst.input.val(dateStr);
4780 }
4781 this._updateAlternate(inst);
4782
4783 onSelect = this._get(inst, "onSelect");
4784 if (onSelect) {
4785 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
4786 } else if (inst.input) {
4787 inst.input.trigger("change"); // fire the change event
4788 }
4789
4790 if (inst.inline){
4791 this._updateDatepicker(inst);
4792 } else {
4793 this._hideDatepicker();
4794 this._lastInput = inst.input[0];
4795 if (typeof(inst.input[0]) !== "object") {
4796 inst.input.focus(); // restore focus
4797 }
4798 this._lastInput = null;
4799 }
4800 },
4801
4802 /* Update any alternate field to synchronise with the main field. */
4803 _updateAlternate: function(inst) {
4804 var altFormat, date, dateStr,
4805 altField = this._get(inst, "altField");
4806
4807 if (altField) { // update alternate field too
4808 altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
4809 date = this._getDate(inst);
4810 dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
4811 $(altField).each(function() { $(this).val(dateStr); });
4812 }
4813 },
4814
4815 /* Set as beforeShowDay function to prevent selection of weekends.
4816 * @param date Date - the date to customise
4817 * @return [boolean, string] - is this date selectable?, what is its CSS class?
4818 */
4819 noWeekends: function(date) {
4820 var day = date.getDay();
4821 return [(day > 0 && day < 6), ""];
4822 },
4823
4824 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
4825 * @param date Date - the date to get the week for
4826 * @return number - the number of the week within the year that contains this date
4827 */
4828 iso8601Week: function(date) {
4829 var time,
4830 checkDate = new Date(date.getTime());
4831
4832 // Find Thursday of this week starting on Monday
4833 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
4834
4835 time = checkDate.getTime();
4836 checkDate.setMonth(0); // Compare with Jan 1
4837 checkDate.setDate(1);
4838 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
4839 },
4840
4841 /* Parse a string value into a date object.
4842 * See formatDate below for the possible formats.
4843 *
4844 * @param format string - the expected format of the date
4845 * @param value string - the date in the above format
4846 * @param settings Object - attributes include:
4847 * shortYearCutoff number - the cutoff year for determining the century (optional)
4848 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
4849 * dayNames string[7] - names of the days from Sunday (optional)
4850 * monthNamesShort string[12] - abbreviated names of the months (optional)
4851 * monthNames string[12] - names of the months (optional)
4852 * @return Date - the extracted date value or null if value is blank
4853 */
4854 parseDate: function (format, value, settings) {
4855 if (format == null || value == null) {
4856 throw "Invalid arguments";
4857 }
4858
4859 value = (typeof value === "object" ? value.toString() : value + "");
4860 if (value === "") {
4861 return null;
4862 }
4863
4864 var iFormat, dim, extra,
4865 iValue = 0,
4866 shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
4867 shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
4868 new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
4869 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
4870 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
4871 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
4872 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
4873 year = -1,
4874 month = -1,
4875 day = -1,
4876 doy = -1,
4877 literal = false,
4878 date,
4879 // Check whether a format character is doubled
4880 lookAhead = function(match) {
4881 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
4882 if (matches) {
4883 iFormat++;
4884 }
4885 return matches;
4886 },
4887 // Extract a number from the string value
4888 getNumber = function(match) {
4889 var isDoubled = lookAhead(match),
4890 size = (match === "@" ? 14 : (match === "!" ? 20 :
4891 (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
4892 minSize = (match === "y" ? size : 1),
4893 digits = new RegExp("^\\d{" + minSize + "," + size + "}"),
4894 num = value.substring(iValue).match(digits);
4895 if (!num) {
4896 throw "Missing number at position " + iValue;
4897 }
4898 iValue += num[0].length;
4899 return parseInt(num[0], 10);
4900 },
4901 // Extract a name from the string value and convert to an index
4902 getName = function(match, shortNames, longNames) {
4903 var index = -1,
4904 names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
4905 return [ [k, v] ];
4906 }).sort(function (a, b) {
4907 return -(a[1].length - b[1].length);
4908 });
4909
4910 $.each(names, function (i, pair) {
4911 var name = pair[1];
4912 if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
4913 index = pair[0];
4914 iValue += name.length;
4915 return false;
4916 }
4917 });
4918 if (index !== -1) {
4919 return index + 1;
4920 } else {
4921 throw "Unknown name at position " + iValue;
4922 }
4923 },
4924 // Confirm that a literal character matches the string value
4925 checkLiteral = function() {
4926 if (value.charAt(iValue) !== format.charAt(iFormat)) {
4927 throw "Unexpected literal at position " + iValue;
4928 }
4929 iValue++;
4930 };
4931
4932 for (iFormat = 0; iFormat < format.length; iFormat++) {
4933 if (literal) {
4934 if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
4935 literal = false;
4936 } else {
4937 checkLiteral();
4938 }
4939 } else {
4940 switch (format.charAt(iFormat)) {
4941 case "d":
4942 day = getNumber("d");
4943 break;
4944 case "D":
4945 getName("D", dayNamesShort, dayNames);
4946 break;
4947 case "o":
4948 doy = getNumber("o");
4949 break;
4950 case "m":
4951 month = getNumber("m");
4952 break;
4953 case "M":
4954 month = getName("M", monthNamesShort, monthNames);
4955 break;
4956 case "y":
4957 year = getNumber("y");
4958 break;
4959 case "@":
4960 date = new Date(getNumber("@"));
4961 year = date.getFullYear();
4962 month = date.getMonth() + 1;
4963 day = date.getDate();
4964 break;
4965 case "!":
4966 date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
4967 year = date.getFullYear();
4968 month = date.getMonth() + 1;
4969 day = date.getDate();
4970 break;
4971 case "'":
4972 if (lookAhead("'")){
4973 checkLiteral();
4974 } else {
4975 literal = true;
4976 }
4977 break;
4978 default:
4979 checkLiteral();
4980 }
4981 }
4982 }
4983
4984 if (iValue < value.length){
4985 extra = value.substr(iValue);
4986 if (!/^\s+/.test(extra)) {
4987 throw "Extra/unparsed characters found in date: " + extra;
4988 }
4989 }
4990
4991 if (year === -1) {
4992 year = new Date().getFullYear();
4993 } else if (year < 100) {
4994 year += new Date().getFullYear() - new Date().getFullYear() % 100 +
4995 (year <= shortYearCutoff ? 0 : -100);
4996 }
4997
4998 if (doy > -1) {
4999 month = 1;
5000 day = doy;
5001 do {
5002 dim = this._getDaysInMonth(year, month - 1);
5003 if (day <= dim) {
5004 break;
5005 }
5006 month++;
5007 day -= dim;
5008 } while (true);
5009 }
5010
5011 date = this._daylightSavingAdjust(new Date(year, month - 1, day));
5012 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
5013 throw "Invalid date"; // E.g. 31/02/00
5014 }
5015 return date;
5016 },
5017
5018 /* Standard date formats. */
5019 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
5020 COOKIE: "D, dd M yy",
5021 ISO_8601: "yy-mm-dd",
5022 RFC_822: "D, d M y",
5023 RFC_850: "DD, dd-M-y",
5024 RFC_1036: "D, d M y",
5025 RFC_1123: "D, d M yy",
5026 RFC_2822: "D, d M yy",
5027 RSS: "D, d M y", // RFC 822
5028 TICKS: "!",
5029 TIMESTAMP: "@",
5030 W3C: "yy-mm-dd", // ISO 8601
5031
5032 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
5033 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
5034
5035 /* Format a date object into a string value.
5036 * The format can be combinations of the following:
5037 * d - day of month (no leading zero)
5038 * dd - day of month (two digit)
5039 * o - day of year (no leading zeros)
5040 * oo - day of year (three digit)
5041 * D - day name short
5042 * DD - day name long
5043 * m - month of year (no leading zero)
5044 * mm - month of year (two digit)
5045 * M - month name short
5046 * MM - month name long
5047 * y - year (two digit)
5048 * yy - year (four digit)
5049 * @ - Unix timestamp (ms since 01/01/1970)
5050 * ! - Windows ticks (100ns since 01/01/0001)
5051 * "..." - literal text
5052 * '' - single quote
5053 *
5054 * @param format string - the desired format of the date
5055 * @param date Date - the date value to format
5056 * @param settings Object - attributes include:
5057 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
5058 * dayNames string[7] - names of the days from Sunday (optional)
5059 * monthNamesShort string[12] - abbreviated names of the months (optional)
5060 * monthNames string[12] - names of the months (optional)
5061 * @return string - the date in the above format
5062 */
5063 formatDate: function (format, date, settings) {
5064 if (!date) {
5065 return "";
5066 }
5067
5068 var iFormat,
5069 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
5070 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
5071 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
5072 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
5073 // Check whether a format character is doubled
5074 lookAhead = function(match) {
5075 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
5076 if (matches) {
5077 iFormat++;
5078 }
5079 return matches;
5080 },
5081 // Format a number, with leading zero if necessary
5082 formatNumber = function(match, value, len) {
5083 var num = "" + value;
5084 if (lookAhead(match)) {
5085 while (num.length < len) {
5086 num = "0" + num;
5087 }
5088 }
5089 return num;
5090 },
5091 // Format a name, short or long as requested
5092 formatName = function(match, value, shortNames, longNames) {
5093 return (lookAhead(match) ? longNames[value] : shortNames[value]);
5094 },
5095 output = "",
5096 literal = false;
5097
5098 if (date) {
5099 for (iFormat = 0; iFormat < format.length; iFormat++) {
5100 if (literal) {
5101 if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
5102 literal = false;
5103 } else {
5104 output += format.charAt(iFormat);
5105 }
5106 } else {
5107 switch (format.charAt(iFormat)) {
5108 case "d":
5109 output += formatNumber("d", date.getDate(), 2);
5110 break;
5111 case "D":
5112 output += formatName("D", date.getDay(), dayNamesShort, dayNames);
5113 break;
5114 case "o":
5115 output += formatNumber("o",
5116 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
5117 break;
5118 case "m":
5119 output += formatNumber("m", date.getMonth() + 1, 2);
5120 break;
5121 case "M":
5122 output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
5123 break;
5124 case "y":
5125 output += (lookAhead("y") ? date.getFullYear() :
5126 (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
5127 break;
5128 case "@":
5129 output += date.getTime();
5130 break;
5131 case "!":
5132 output += date.getTime() * 10000 + this._ticksTo1970;
5133 break;
5134 case "'":
5135 if (lookAhead("'")) {
5136 output += "'";
5137 } else {
5138 literal = true;
5139 }
5140 break;
5141 default:
5142 output += format.charAt(iFormat);
5143 }
5144 }
5145 }
5146 }
5147 return output;
5148 },
5149
5150 /* Extract all possible characters from the date format. */
5151 _possibleChars: function (format) {
5152 var iFormat,
5153 chars = "",
5154 literal = false,
5155 // Check whether a format character is doubled
5156 lookAhead = function(match) {
5157 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
5158 if (matches) {
5159 iFormat++;
5160 }
5161 return matches;
5162 };
5163
5164 for (iFormat = 0; iFormat < format.length; iFormat++) {
5165 if (literal) {
5166 if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
5167 literal = false;
5168 } else {
5169 chars += format.charAt(iFormat);
5170 }
5171 } else {
5172 switch (format.charAt(iFormat)) {
5173 case "d": case "m": case "y": case "@":
5174 chars += "0123456789";
5175 break;
5176 case "D": case "M":
5177 return null; // Accept anything
5178 case "'":
5179 if (lookAhead("'")) {
5180 chars += "'";
5181 } else {
5182 literal = true;
5183 }
5184 break;
5185 default:
5186 chars += format.charAt(iFormat);
5187 }
5188 }
5189 }
5190 return chars;
5191 },
5192
5193 /* Get a setting value, defaulting if necessary. */
5194 _get: function(inst, name) {
5195 return inst.settings[name] !== undefined ?
5196 inst.settings[name] : this._defaults[name];
5197 },
5198
5199 /* Parse existing date and initialise date picker. */
5200 _setDateFromField: function(inst, noDefault) {
5201 if (inst.input.val() === inst.lastVal) {
5202 return;
5203 }
5204
5205 var dateFormat = this._get(inst, "dateFormat"),
5206 dates = inst.lastVal = inst.input ? inst.input.val() : null,
5207 defaultDate = this._getDefaultDate(inst),
5208 date = defaultDate,
5209 settings = this._getFormatConfig(inst);
5210
5211 try {
5212 date = this.parseDate(dateFormat, dates, settings) || defaultDate;
5213 } catch (event) {
5214 dates = (noDefault ? "" : dates);
5215 }
5216 inst.selectedDay = date.getDate();
5217 inst.drawMonth = inst.selectedMonth = date.getMonth();
5218 inst.drawYear = inst.selectedYear = date.getFullYear();
5219 inst.currentDay = (dates ? date.getDate() : 0);
5220 inst.currentMonth = (dates ? date.getMonth() : 0);
5221 inst.currentYear = (dates ? date.getFullYear() : 0);
5222 this._adjustInstDate(inst);
5223 },
5224
5225 /* Retrieve the default date shown on opening. */
5226 _getDefaultDate: function(inst) {
5227 return this._restrictMinMax(inst,
5228 this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
5229 },
5230
5231 /* A date may be specified as an exact value or a relative one. */
5232 _determineDate: function(inst, date, defaultDate) {
5233 var offsetNumeric = function(offset) {
5234 var date = new Date();
5235 date.setDate(date.getDate() + offset);
5236 return date;
5237 },
5238 offsetString = function(offset) {
5239 try {
5240 return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
5241 offset, $.datepicker._getFormatConfig(inst));
5242 }
5243 catch (e) {
5244 // Ignore
5245 }
5246
5247 var date = (offset.toLowerCase().match(/^c/) ?
5248 $.datepicker._getDate(inst) : null) || new Date(),
5249 year = date.getFullYear(),
5250 month = date.getMonth(),
5251 day = date.getDate(),
5252 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
5253 matches = pattern.exec(offset);
5254
5255 while (matches) {
5256 switch (matches[2] || "d") {
5257 case "d" : case "D" :
5258 day += parseInt(matches[1],10); break;
5259 case "w" : case "W" :
5260 day += parseInt(matches[1],10) * 7; break;
5261 case "m" : case "M" :
5262 month += parseInt(matches[1],10);
5263 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
5264 break;
5265 case "y": case "Y" :
5266 year += parseInt(matches[1],10);
5267 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
5268 break;
5269 }
5270 matches = pattern.exec(offset);
5271 }
5272 return new Date(year, month, day);
5273 },
5274 newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
5275 (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
5276
5277 newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
5278 if (newDate) {
5279 newDate.setHours(0);
5280 newDate.setMinutes(0);
5281 newDate.setSeconds(0);
5282 newDate.setMilliseconds(0);
5283 }
5284 return this._daylightSavingAdjust(newDate);
5285 },
5286
5287 /* Handle switch to/from daylight saving.
5288 * Hours may be non-zero on daylight saving cut-over:
5289 * > 12 when midnight changeover, but then cannot generate
5290 * midnight datetime, so jump to 1AM, otherwise reset.
5291 * @param date (Date) the date to check
5292 * @return (Date) the corrected date
5293 */
5294 _daylightSavingAdjust: function(date) {
5295 if (!date) {
5296 return null;
5297 }
5298 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
5299 return date;
5300 },
5301
5302 /* Set the date(s) directly. */
5303 _setDate: function(inst, date, noChange) {
5304 var clear = !date,
5305 origMonth = inst.selectedMonth,
5306 origYear = inst.selectedYear,
5307 newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
5308
5309 inst.selectedDay = inst.currentDay = newDate.getDate();
5310 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
5311 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
5312 if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
5313 this._notifyChange(inst);
5314 }
5315 this._adjustInstDate(inst);
5316 if (inst.input) {
5317 inst.input.val(clear ? "" : this._formatDate(inst));
5318 }
5319 },
5320
5321 /* Retrieve the date(s) directly. */
5322 _getDate: function(inst) {
5323 var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
5324 this._daylightSavingAdjust(new Date(
5325 inst.currentYear, inst.currentMonth, inst.currentDay)));
5326 return startDate;
5327 },
5328
5329 /* Attach the onxxx handlers. These are declared statically so
5330 * they work with static code transformers like Caja.
5331 */
5332 _attachHandlers: function(inst) {
5333 var stepMonths = this._get(inst, "stepMonths"),
5334 id = "#" + inst.id.replace( /\\\\/g, "\\" );
5335 inst.dpDiv.find("[data-handler]").map(function () {
5336 var handler = {
5337 prev: function () {
5338 $.datepicker._adjustDate(id, -stepMonths, "M");
5339 },
5340 next: function () {
5341 $.datepicker._adjustDate(id, +stepMonths, "M");
5342 },
5343 hide: function () {
5344 $.datepicker._hideDatepicker();
5345 },
5346 today: function () {
5347 $.datepicker._gotoToday(id);
5348 },
5349 selectDay: function () {
5350 $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
5351 return false;
5352 },
5353 selectMonth: function () {
5354 $.datepicker._selectMonthYear(id, this, "M");
5355 return false;
5356 },
5357 selectYear: function () {
5358 $.datepicker._selectMonthYear(id, this, "Y");
5359 return false;
5360 }
5361 };
5362 $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
5363 });
5364 },
5365
5366 /* Generate the HTML for the current state of the date picker. */
5367 _generateHTML: function(inst) {
5368 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
5369 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
5370 monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
5371 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
5372 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
5373 printDate, dRow, tbody, daySettings, otherMonth, unselectable,
5374 tempDate = new Date(),
5375 today = this._daylightSavingAdjust(
5376 new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
5377 isRTL = this._get(inst, "isRTL"),
5378 showButtonPanel = this._get(inst, "showButtonPanel"),
5379 hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
5380 navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
5381 numMonths = this._getNumberOfMonths(inst),
5382 showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
5383 stepMonths = this._get(inst, "stepMonths"),
5384 isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
5385 currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
5386 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
5387 minDate = this._getMinMaxDate(inst, "min"),
5388 maxDate = this._getMinMaxDate(inst, "max"),
5389 drawMonth = inst.drawMonth - showCurrentAtPos,
5390 drawYear = inst.drawYear;
5391
5392 if (drawMonth < 0) {
5393 drawMonth += 12;
5394 drawYear--;
5395 }
5396 if (maxDate) {
5397 maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
5398 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
5399 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
5400 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
5401 drawMonth--;
5402 if (drawMonth < 0) {
5403 drawMonth = 11;
5404 drawYear--;
5405 }
5406 }
5407 }
5408 inst.drawMonth = drawMonth;
5409 inst.drawYear = drawYear;
5410
5411 prevText = this._get(inst, "prevText");
5412 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
5413 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
5414 this._getFormatConfig(inst)));
5415
5416 prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
5417 "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
5418 " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
5419 (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ prevText +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>"));
5420
5421 nextText = this._get(inst, "nextText");
5422 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
5423 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
5424 this._getFormatConfig(inst)));
5425
5426 next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
5427 "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
5428 " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
5429 (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>"));
5430
5431 currentText = this._get(inst, "currentText");
5432 gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
5433 currentText = (!navigationAsDateFormat ? currentText :
5434 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
5435
5436 controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
5437 this._get(inst, "closeText") + "</button>" : "");
5438
5439 buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
5440 (this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
5441 ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
5442
5443 firstDay = parseInt(this._get(inst, "firstDay"),10);
5444 firstDay = (isNaN(firstDay) ? 0 : firstDay);
5445
5446 showWeek = this._get(inst, "showWeek");
5447 dayNames = this._get(inst, "dayNames");
5448 dayNamesMin = this._get(inst, "dayNamesMin");
5449 monthNames = this._get(inst, "monthNames");
5450 monthNamesShort = this._get(inst, "monthNamesShort");
5451 beforeShowDay = this._get(inst, "beforeShowDay");
5452 showOtherMonths = this._get(inst, "showOtherMonths");
5453 selectOtherMonths = this._get(inst, "selectOtherMonths");
5454 defaultDate = this._getDefaultDate(inst);
5455 html = "";
5456 dow;
5457 for (row = 0; row < numMonths[0]; row++) {
5458 group = "";
5459 this.maxRows = 4;
5460 for (col = 0; col < numMonths[1]; col++) {
5461 selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
5462 cornerClass = " ui-corner-all";
5463 calender = "";
5464 if (isMultiMonth) {
5465 calender += "<div class='ui-datepicker-group";
5466 if (numMonths[1] > 1) {
5467 switch (col) {
5468 case 0: calender += " ui-datepicker-group-first";
5469 cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
5470 case numMonths[1]-1: calender += " ui-datepicker-group-last";
5471 cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
5472 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
5473 }
5474 }
5475 calender += "'>";
5476 }
5477 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
5478 (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
5479 (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
5480 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
5481 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
5482 "</div><table class='ui-datepicker-calendar'><thead>" +
5483 "<tr>";
5484 thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
5485 for (dow = 0; dow < 7; dow++) { // days of the week
5486 day = (dow + firstDay) % 7;
5487 thead += "<th scope='col'" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
5488 "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
5489 }
5490 calender += thead + "</tr></thead><tbody>";
5491 daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
5492 if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
5493 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
5494 }
5495 leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
5496 curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
5497 numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
5498 this.maxRows = numRows;
5499 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
5500 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
5501 calender += "<tr>";
5502 tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
5503 this._get(inst, "calculateWeek")(printDate) + "</td>");
5504 for (dow = 0; dow < 7; dow++) { // create date picker days
5505 daySettings = (beforeShowDay ?
5506 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
5507 otherMonth = (printDate.getMonth() !== drawMonth);
5508 unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
5509 (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
5510 tbody += "<td class='" +
5511 ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
5512 (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
5513 ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
5514 (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
5515 // or defaultDate is current printedDate and defaultDate is selectedDate
5516 " " + this._dayOverClass : "") + // highlight selected day
5517 (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days
5518 (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
5519 (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
5520 (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
5521 ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + // cell title
5522 (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
5523 (otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
5524 (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
5525 (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
5526 (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
5527 (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
5528 "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
5529 printDate.setDate(printDate.getDate() + 1);
5530 printDate = this._daylightSavingAdjust(printDate);
5531 }
5532 calender += tbody + "</tr>";
5533 }
5534 drawMonth++;
5535 if (drawMonth > 11) {
5536 drawMonth = 0;
5537 drawYear++;
5538 }
5539 calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
5540 ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
5541 group += calender;
5542 }
5543 html += group;
5544 }
5545 html += buttonPanel;
5546 inst._keyEvent = false;
5547 return html;
5548 },
5549
5550 /* Generate the month and year header. */
5551 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
5552 secondary, monthNames, monthNamesShort) {
5553
5554 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
5555 changeMonth = this._get(inst, "changeMonth"),
5556 changeYear = this._get(inst, "changeYear"),
5557 showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
5558 html = "<div class='ui-datepicker-title'>",
5559 monthHtml = "";
5560
5561 // month selection
5562 if (secondary || !changeMonth) {
5563 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
5564 } else {
5565 inMinYear = (minDate && minDate.getFullYear() === drawYear);
5566 inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
5567 monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
5568 for ( month = 0; month < 12; month++) {
5569 if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
5570 monthHtml += "<option value='" + month + "'" +
5571 (month === drawMonth ? " selected='selected'" : "") +
5572 ">" + monthNamesShort[month] + "</option>";
5573 }
5574 }
5575 monthHtml += "</select>";
5576 }
5577
5578 if (!showMonthAfterYear) {
5579 html += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");
5580 }
5581
5582 // year selection
5583 if ( !inst.yearshtml ) {
5584 inst.yearshtml = "";
5585 if (secondary || !changeYear) {
5586 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
5587 } else {
5588 // determine range of years to display
5589 years = this._get(inst, "yearRange").split(":");
5590 thisYear = new Date().getFullYear();
5591 determineYear = function(value) {
5592 var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
5593 (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
5594 parseInt(value, 10)));
5595 return (isNaN(year) ? thisYear : year);
5596 };
5597 year = determineYear(years[0]);
5598 endYear = Math.max(year, determineYear(years[1] || ""));
5599 year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
5600 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
5601 inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
5602 for (; year <= endYear; year++) {
5603 inst.yearshtml += "<option value='" + year + "'" +
5604 (year === drawYear ? " selected='selected'" : "") +
5605 ">" + year + "</option>";
5606 }
5607 inst.yearshtml += "</select>";
5608
5609 html += inst.yearshtml;
5610 inst.yearshtml = null;
5611 }
5612 }
5613
5614 html += this._get(inst, "yearSuffix");
5615 if (showMonthAfterYear) {
5616 html += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;
5617 }
5618 html += "</div>"; // Close datepicker_header
5619 return html;
5620 },
5621
5622 /* Adjust one of the date sub-fields. */
5623 _adjustInstDate: function(inst, offset, period) {
5624 var year = inst.drawYear + (period === "Y" ? offset : 0),
5625 month = inst.drawMonth + (period === "M" ? offset : 0),
5626 day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
5627 date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
5628
5629 inst.selectedDay = date.getDate();
5630 inst.drawMonth = inst.selectedMonth = date.getMonth();
5631 inst.drawYear = inst.selectedYear = date.getFullYear();
5632 if (period === "M" || period === "Y") {
5633 this._notifyChange(inst);
5634 }
5635 },
5636
5637 /* Ensure a date is within any min/max bounds. */
5638 _restrictMinMax: function(inst, date) {
5639 var minDate = this._getMinMaxDate(inst, "min"),
5640 maxDate = this._getMinMaxDate(inst, "max"),
5641 newDate = (minDate && date < minDate ? minDate : date);
5642 return (maxDate && newDate > maxDate ? maxDate : newDate);
5643 },
5644
5645 /* Notify change of month/year. */
5646 _notifyChange: function(inst) {
5647 var onChange = this._get(inst, "onChangeMonthYear");
5648 if (onChange) {
5649 onChange.apply((inst.input ? inst.input[0] : null),
5650 [inst.selectedYear, inst.selectedMonth + 1, inst]);
5651 }
5652 },
5653
5654 /* Determine the number of months to show. */
5655 _getNumberOfMonths: function(inst) {
5656 var numMonths = this._get(inst, "numberOfMonths");
5657 return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
5658 },
5659
5660 /* Determine the current maximum date - ensure no time components are set. */
5661 _getMinMaxDate: function(inst, minMax) {
5662 return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
5663 },
5664
5665 /* Find the number of days in a given month. */
5666 _getDaysInMonth: function(year, month) {
5667 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
5668 },
5669
5670 /* Find the day of the week of the first of a month. */
5671 _getFirstDayOfMonth: function(year, month) {
5672 return new Date(year, month, 1).getDay();
5673 },
5674
5675 /* Determines if we should allow a "next/prev" month display change. */
5676 _canAdjustMonth: function(inst, offset, curYear, curMonth) {
5677 var numMonths = this._getNumberOfMonths(inst),
5678 date = this._daylightSavingAdjust(new Date(curYear,
5679 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
5680
5681 if (offset < 0) {
5682 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
5683 }
5684 return this._isInRange(inst, date);
5685 },
5686
5687 /* Is the given date in the accepted range? */
5688 _isInRange: function(inst, date) {
5689 var yearSplit, currentYear,
5690 minDate = this._getMinMaxDate(inst, "min"),
5691 maxDate = this._getMinMaxDate(inst, "max"),
5692 minYear = null,
5693 maxYear = null,
5694 years = this._get(inst, "yearRange");
5695 if (years){
5696 yearSplit = years.split(":");
5697 currentYear = new Date().getFullYear();
5698 minYear = parseInt(yearSplit[0], 10);
5699 maxYear = parseInt(yearSplit[1], 10);
5700 if ( yearSplit[0].match(/[+\-].*/) ) {
5701 minYear += currentYear;
5702 }
5703 if ( yearSplit[1].match(/[+\-].*/) ) {
5704 maxYear += currentYear;
5705 }
5706 }
5707
5708 return ((!minDate || date.getTime() >= minDate.getTime()) &&
5709 (!maxDate || date.getTime() <= maxDate.getTime()) &&
5710 (!minYear || date.getFullYear() >= minYear) &&
5711 (!maxYear || date.getFullYear() <= maxYear));
5712 },
5713
5714 /* Provide the configuration settings for formatting/parsing. */
5715 _getFormatConfig: function(inst) {
5716 var shortYearCutoff = this._get(inst, "shortYearCutoff");
5717 shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
5718 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
5719 return {shortYearCutoff: shortYearCutoff,
5720 dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
5721 monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
5722 },
5723
5724 /* Format the given date for display. */
5725 _formatDate: function(inst, day, month, year) {
5726 if (!day) {
5727 inst.currentDay = inst.selectedDay;
5728 inst.currentMonth = inst.selectedMonth;
5729 inst.currentYear = inst.selectedYear;
5730 }
5731 var date = (day ? (typeof day === "object" ? day :
5732 this._daylightSavingAdjust(new Date(year, month, day))) :
5733 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
5734 return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
5735 }
5736});
5737
5738/*
5739 * Bind hover events for datepicker elements.
5740 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
5741 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
5742 */
5743function datepicker_bindHover(dpDiv) {
5744 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
5745 return dpDiv.delegate(selector, "mouseout", function() {
5746 $(this).removeClass("ui-state-hover");
5747 if (this.className.indexOf("ui-datepicker-prev") !== -1) {
5748 $(this).removeClass("ui-datepicker-prev-hover");
5749 }
5750 if (this.className.indexOf("ui-datepicker-next") !== -1) {
5751 $(this).removeClass("ui-datepicker-next-hover");
5752 }
5753 })
5754 .delegate( selector, "mouseover", datepicker_handleMouseover );
5755}
5756
5757function datepicker_handleMouseover() {
5758 if (!$.datepicker._isDisabledDatepicker( datepicker_instActive.inline? datepicker_instActive.dpDiv.parent()[0] : datepicker_instActive.input[0])) {
5759 $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
5760 $(this).addClass("ui-state-hover");
5761 if (this.className.indexOf("ui-datepicker-prev") !== -1) {
5762 $(this).addClass("ui-datepicker-prev-hover");
5763 }
5764 if (this.className.indexOf("ui-datepicker-next") !== -1) {
5765 $(this).addClass("ui-datepicker-next-hover");
5766 }
5767 }
5768}
5769
5770/* jQuery extend now ignores nulls! */
5771function datepicker_extendRemove(target, props) {
5772 $.extend(target, props);
5773 for (var name in props) {
5774 if (props[name] == null) {
5775 target[name] = props[name];
5776 }
5777 }
5778 return target;
5779}
5780
5781/* Invoke the datepicker functionality.
5782 @param options string - a command, optionally followed by additional parameters or
5783 Object - settings for attaching new datepicker functionality
5784 @return jQuery object */
5785$.fn.datepicker = function(options){
5786
5787 /* Verify an empty collection wasn't passed - Fixes #6976 */
5788 if ( !this.length ) {
5789 return this;
5790 }
5791
5792 /* Initialise the date picker. */
5793 if (!$.datepicker.initialized) {
5794 $(document).mousedown($.datepicker._checkExternalClick);
5795 $.datepicker.initialized = true;
5796 }
5797
5798 /* Append datepicker main container to body if not exist. */
5799 if ($("#"+$.datepicker._mainDivId).length === 0) {
5800 $("body").append($.datepicker.dpDiv);
5801 }
5802
5803 var otherArgs = Array.prototype.slice.call(arguments, 1);
5804 if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
5805 return $.datepicker["_" + options + "Datepicker"].
5806 apply($.datepicker, [this[0]].concat(otherArgs));
5807 }
5808 if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
5809 return $.datepicker["_" + options + "Datepicker"].
5810 apply($.datepicker, [this[0]].concat(otherArgs));
5811 }
5812 return this.each(function() {
5813 typeof options === "string" ?
5814 $.datepicker["_" + options + "Datepicker"].
5815 apply($.datepicker, [this].concat(otherArgs)) :
5816 $.datepicker._attachDatepicker(this, options);
5817 });
5818};
5819
5820$.datepicker = new Datepicker(); // singleton instance
5821$.datepicker.initialized = false;
5822$.datepicker.uuid = new Date().getTime();
5823$.datepicker.version = "1.11.2";
5824
5825var datepicker = $.datepicker;
5826
5827
5828/*!
5829 * jQuery UI Draggable 1.11.2
5830 * http://jqueryui.com
5831 *
5832 * Copyright 2014 jQuery Foundation and other contributors
5833 * Released under the MIT license.
5834 * http://jquery.org/license
5835 *
5836 * http://api.jqueryui.com/draggable/
5837 */
5838
5839
5840$.widget("ui.draggable", $.ui.mouse, {
5841 version: "1.11.2",
5842 widgetEventPrefix: "drag",
5843 options: {
5844 addClasses: true,
5845 appendTo: "parent",
5846 axis: false,
5847 connectToSortable: false,
5848 containment: false,
5849 cursor: "auto",
5850 cursorAt: false,
5851 grid: false,
5852 handle: false,
5853 helper: "original",
5854 iframeFix: false,
5855 opacity: false,
5856 refreshPositions: false,
5857 revert: false,
5858 revertDuration: 500,
5859 scope: "default",
5860 scroll: true,
5861 scrollSensitivity: 20,
5862 scrollSpeed: 20,
5863 snap: false,
5864 snapMode: "both",
5865 snapTolerance: 20,
5866 stack: false,
5867 zIndex: false,
5868
5869 // callbacks
5870 drag: null,
5871 start: null,
5872 stop: null
5873 },
5874 _create: function() {
5875
5876 if ( this.options.helper === "original" ) {
5877 this._setPositionRelative();
5878 }
5879 if (this.options.addClasses){
5880 this.element.addClass("ui-draggable");
5881 }
5882 if (this.options.disabled){
5883 this.element.addClass("ui-draggable-disabled");
5884 }
5885 this._setHandleClassName();
5886
5887 this._mouseInit();
5888 },
5889
5890 _setOption: function( key, value ) {
5891 this._super( key, value );
5892 if ( key === "handle" ) {
5893 this._removeHandleClassName();
5894 this._setHandleClassName();
5895 }
5896 },
5897
5898 _destroy: function() {
5899 if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
5900 this.destroyOnClear = true;
5901 return;
5902 }
5903 this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
5904 this._removeHandleClassName();
5905 this._mouseDestroy();
5906 },
5907
5908 _mouseCapture: function(event) {
5909 var o = this.options;
5910
5911 this._blurActiveElement( event );
5912
5913 // among others, prevent a drag on a resizable-handle
5914 if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
5915 return false;
5916 }
5917
5918 //Quit if we're not on a valid handle
5919 this.handle = this._getHandle(event);
5920 if (!this.handle) {
5921 return false;
5922 }
5923
5924 this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
5925
5926 return true;
5927
5928 },
5929
5930 _blockFrames: function( selector ) {
5931 this.iframeBlocks = this.document.find( selector ).map(function() {
5932 var iframe = $( this );
5933
5934 return $( "<div>" )
5935 .css( "position", "absolute" )
5936 .appendTo( iframe.parent() )
5937 .outerWidth( iframe.outerWidth() )
5938 .outerHeight( iframe.outerHeight() )
5939 .offset( iframe.offset() )[ 0 ];
5940 });
5941 },
5942
5943 _unblockFrames: function() {
5944 if ( this.iframeBlocks ) {
5945 this.iframeBlocks.remove();
5946 delete this.iframeBlocks;
5947 }
5948 },
5949
5950 _blurActiveElement: function( event ) {
5951 var document = this.document[ 0 ];
5952
5953 // Only need to blur if the event occurred on the draggable itself, see #10527
5954 if ( !this.handleElement.is( event.target ) ) {
5955 return;
5956 }
5957
5958 // support: IE9
5959 // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
5960 try {
5961
5962 // Support: IE9, IE10
5963 // If the <body> is blurred, IE will switch windows, see #9520
5964 if ( document.activeElement && document.activeElement.nodeName.toLowerCase() !== "body" ) {
5965
5966 // Blur any element that currently has focus, see #4261
5967 $( document.activeElement ).blur();
5968 }
5969 } catch ( error ) {}
5970 },
5971
5972 _mouseStart: function(event) {
5973
5974 var o = this.options;
5975
5976 //Create and append the visible helper
5977 this.helper = this._createHelper(event);
5978
5979 this.helper.addClass("ui-draggable-dragging");
5980
5981 //Cache the helper size
5982 this._cacheHelperProportions();
5983
5984 //If ddmanager is used for droppables, set the global draggable
5985 if ($.ui.ddmanager) {
5986 $.ui.ddmanager.current = this;
5987 }
5988
5989 /*
5990 * - Position generation -
5991 * This block generates everything position related - it's the core of draggables.
5992 */
5993
5994 //Cache the margins of the original element
5995 this._cacheMargins();
5996
5997 //Store the helper's css position
5998 this.cssPosition = this.helper.css( "position" );
5999 this.scrollParent = this.helper.scrollParent( true );
6000 this.offsetParent = this.helper.offsetParent();
6001 this.hasFixedAncestor = this.helper.parents().filter(function() {
6002 return $( this ).css( "position" ) === "fixed";
6003 }).length > 0;
6004
6005 //The element's absolute position on the page minus margins
6006 this.positionAbs = this.element.offset();
6007 this._refreshOffsets( event );
6008
6009 //Generate the original position
6010 this.originalPosition = this.position = this._generatePosition( event, false );
6011 this.originalPageX = event.pageX;
6012 this.originalPageY = event.pageY;
6013
6014 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
6015 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
6016
6017 //Set a containment if given in the options
6018 this._setContainment();
6019
6020 //Trigger event + callbacks
6021 if (this._trigger("start", event) === false) {
6022 this._clear();
6023 return false;
6024 }
6025
6026 //Recache the helper size
6027 this._cacheHelperProportions();
6028
6029 //Prepare the droppable offsets
6030 if ($.ui.ddmanager && !o.dropBehaviour) {
6031 $.ui.ddmanager.prepareOffsets(this, event);
6032 }
6033
6034 // Reset helper's right/bottom css if they're set and set explicit width/height instead
6035 // as this prevents resizing of elements with right/bottom set (see #7772)
6036 this._normalizeRightBottom();
6037
6038 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
6039
6040 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
6041 if ( $.ui.ddmanager ) {
6042 $.ui.ddmanager.dragStart(this, event);
6043 }
6044
6045 return true;
6046 },
6047
6048 _refreshOffsets: function( event ) {
6049 this.offset = {
6050 top: this.positionAbs.top - this.margins.top,
6051 left: this.positionAbs.left - this.margins.left,
6052 scroll: false,
6053 parent: this._getParentOffset(),
6054 relative: this._getRelativeOffset()
6055 };
6056
6057 this.offset.click = {
6058 left: event.pageX - this.offset.left,
6059 top: event.pageY - this.offset.top
6060 };
6061 },
6062
6063 _mouseDrag: function(event, noPropagation) {
6064 // reset any necessary cached properties (see #5009)
6065 if ( this.hasFixedAncestor ) {
6066 this.offset.parent = this._getParentOffset();
6067 }
6068
6069 //Compute the helpers position
6070 this.position = this._generatePosition( event, true );
6071 this.positionAbs = this._convertPositionTo("absolute");
6072
6073 //Call plugins and callbacks and use the resulting position if something is returned
6074 if (!noPropagation) {
6075 var ui = this._uiHash();
6076 if (this._trigger("drag", event, ui) === false) {
6077 this._mouseUp({});
6078 return false;
6079 }
6080 this.position = ui.position;
6081 }
6082
6083 this.helper[ 0 ].style.left = this.position.left + "px";
6084 this.helper[ 0 ].style.top = this.position.top + "px";
6085
6086 if ($.ui.ddmanager) {
6087 $.ui.ddmanager.drag(this, event);
6088 }
6089
6090 return false;
6091 },
6092
6093 _mouseStop: function(event) {
6094
6095 //If we are using droppables, inform the manager about the drop
6096 var that = this,
6097 dropped = false;
6098 if ($.ui.ddmanager && !this.options.dropBehaviour) {
6099 dropped = $.ui.ddmanager.drop(this, event);
6100 }
6101
6102 //if a drop comes from outside (a sortable)
6103 if (this.dropped) {
6104 dropped = this.dropped;
6105 this.dropped = false;
6106 }
6107
6108 if ((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
6109 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
6110 if (that._trigger("stop", event) !== false) {
6111 that._clear();
6112 }
6113 });
6114 } else {
6115 if (this._trigger("stop", event) !== false) {
6116 this._clear();
6117 }
6118 }
6119
6120 return false;
6121 },
6122
6123 _mouseUp: function( event ) {
6124 this._unblockFrames();
6125
6126 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
6127 if ( $.ui.ddmanager ) {
6128 $.ui.ddmanager.dragStop(this, event);
6129 }
6130
6131 // Only need to focus if the event occurred on the draggable itself, see #10527
6132 if ( this.handleElement.is( event.target ) ) {
6133 // The interaction is over; whether or not the click resulted in a drag, focus the element
6134 this.element.focus();
6135 }
6136
6137 return $.ui.mouse.prototype._mouseUp.call(this, event);
6138 },
6139
6140 cancel: function() {
6141
6142 if (this.helper.is(".ui-draggable-dragging")) {
6143 this._mouseUp({});
6144 } else {
6145 this._clear();
6146 }
6147
6148 return this;
6149
6150 },
6151
6152 _getHandle: function(event) {
6153 return this.options.handle ?
6154 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
6155 true;
6156 },
6157
6158 _setHandleClassName: function() {
6159 this.handleElement = this.options.handle ?
6160 this.element.find( this.options.handle ) : this.element;
6161 this.handleElement.addClass( "ui-draggable-handle" );
6162 },
6163
6164 _removeHandleClassName: function() {
6165 this.handleElement.removeClass( "ui-draggable-handle" );
6166 },
6167
6168 _createHelper: function(event) {
6169
6170 var o = this.options,
6171 helperIsFunction = $.isFunction( o.helper ),
6172 helper = helperIsFunction ?
6173 $( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
6174 ( o.helper === "clone" ?
6175 this.element.clone().removeAttr( "id" ) :
6176 this.element );
6177
6178 if (!helper.parents("body").length) {
6179 helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
6180 }
6181
6182 // http://bugs.jqueryui.com/ticket/9446
6183 // a helper function can return the original element
6184 // which wouldn't have been set to relative in _create
6185 if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
6186 this._setPositionRelative();
6187 }
6188
6189 if (helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
6190 helper.css("position", "absolute");
6191 }
6192
6193 return helper;
6194
6195 },
6196
6197 _setPositionRelative: function() {
6198 if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
6199 this.element[ 0 ].style.position = "relative";
6200 }
6201 },
6202
6203 _adjustOffsetFromHelper: function(obj) {
6204 if (typeof obj === "string") {
6205 obj = obj.split(" ");
6206 }
6207 if ($.isArray(obj)) {
6208 obj = { left: +obj[0], top: +obj[1] || 0 };
6209 }
6210 if ("left" in obj) {
6211 this.offset.click.left = obj.left + this.margins.left;
6212 }
6213 if ("right" in obj) {
6214 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
6215 }
6216 if ("top" in obj) {
6217 this.offset.click.top = obj.top + this.margins.top;
6218 }
6219 if ("bottom" in obj) {
6220 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
6221 }
6222 },
6223
6224 _isRootNode: function( element ) {
6225 return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
6226 },
6227
6228 _getParentOffset: function() {
6229
6230 //Get the offsetParent and cache its position
6231 var po = this.offsetParent.offset(),
6232 document = this.document[ 0 ];
6233
6234 // This is a special case where we need to modify a offset calculated on start, since the following happened:
6235 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
6236 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
6237 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
6238 if (this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
6239 po.left += this.scrollParent.scrollLeft();
6240 po.top += this.scrollParent.scrollTop();
6241 }
6242
6243 if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
6244 po = { top: 0, left: 0 };
6245 }
6246
6247 return {
6248 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0),
6249 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)
6250 };
6251
6252 },
6253
6254 _getRelativeOffset: function() {
6255 if ( this.cssPosition !== "relative" ) {
6256 return { top: 0, left: 0 };
6257 }
6258
6259 var p = this.element.position(),
6260 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
6261
6262 return {
6263 top: p.top - ( parseInt(this.helper.css( "top" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
6264 left: p.left - ( parseInt(this.helper.css( "left" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
6265 };
6266
6267 },
6268
6269 _cacheMargins: function() {
6270 this.margins = {
6271 left: (parseInt(this.element.css("marginLeft"), 10) || 0),
6272 top: (parseInt(this.element.css("marginTop"), 10) || 0),
6273 right: (parseInt(this.element.css("marginRight"), 10) || 0),
6274 bottom: (parseInt(this.element.css("marginBottom"), 10) || 0)
6275 };
6276 },
6277
6278 _cacheHelperProportions: function() {
6279 this.helperProportions = {
6280 width: this.helper.outerWidth(),
6281 height: this.helper.outerHeight()
6282 };
6283 },
6284
6285 _setContainment: function() {
6286
6287 var isUserScrollable, c, ce,
6288 o = this.options,
6289 document = this.document[ 0 ];
6290
6291 this.relativeContainer = null;
6292
6293 if ( !o.containment ) {
6294 this.containment = null;
6295 return;
6296 }
6297
6298 if ( o.containment === "window" ) {
6299 this.containment = [
6300 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
6301 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
6302 $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,
6303 $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
6304 ];
6305 return;
6306 }
6307
6308 if ( o.containment === "document") {
6309 this.containment = [
6310 0,
6311 0,
6312 $( document ).width() - this.helperProportions.width - this.margins.left,
6313 ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
6314 ];
6315 return;
6316 }
6317
6318 if ( o.containment.constructor === Array ) {
6319 this.containment = o.containment;
6320 return;
6321 }
6322
6323 if ( o.containment === "parent" ) {
6324 o.containment = this.helper[ 0 ].parentNode;
6325 }
6326
6327 c = $( o.containment );
6328 ce = c[ 0 ];
6329
6330 if ( !ce ) {
6331 return;
6332 }
6333
6334 isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
6335
6336 this.containment = [
6337 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
6338 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
6339 ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
6340 ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
6341 ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
6342 this.helperProportions.width -
6343 this.margins.left -
6344 this.margins.right,
6345 ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
6346 ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
6347 ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
6348 this.helperProportions.height -
6349 this.margins.top -
6350 this.margins.bottom
6351 ];
6352 this.relativeContainer = c;
6353 },
6354
6355 _convertPositionTo: function(d, pos) {
6356
6357 if (!pos) {
6358 pos = this.position;
6359 }
6360
6361 var mod = d === "absolute" ? 1 : -1,
6362 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
6363
6364 return {
6365 top: (
6366 pos.top + // The absolute mouse position
6367 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
6368 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
6369 ( ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod)
6370 ),
6371 left: (
6372 pos.left + // The absolute mouse position
6373 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
6374 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
6375 ( ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod)
6376 )
6377 };
6378
6379 },
6380
6381 _generatePosition: function( event, constrainPosition ) {
6382
6383 var containment, co, top, left,
6384 o = this.options,
6385 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
6386 pageX = event.pageX,
6387 pageY = event.pageY;
6388
6389 // Cache the scroll
6390 if ( !scrollIsRootNode || !this.offset.scroll ) {
6391 this.offset.scroll = {
6392 top: this.scrollParent.scrollTop(),
6393 left: this.scrollParent.scrollLeft()
6394 };
6395 }
6396
6397 /*
6398 * - Position constraining -
6399 * Constrain the position to a mix of grid, containment.
6400 */
6401
6402 // If we are not dragging yet, we won't check for options
6403 if ( constrainPosition ) {
6404 if ( this.containment ) {
6405 if ( this.relativeContainer ){
6406 co = this.relativeContainer.offset();
6407 containment = [
6408 this.containment[ 0 ] + co.left,
6409 this.containment[ 1 ] + co.top,
6410 this.containment[ 2 ] + co.left,
6411 this.containment[ 3 ] + co.top
6412 ];
6413 } else {
6414 containment = this.containment;
6415 }
6416
6417 if (event.pageX - this.offset.click.left < containment[0]) {
6418 pageX = containment[0] + this.offset.click.left;
6419 }
6420 if (event.pageY - this.offset.click.top < containment[1]) {
6421 pageY = containment[1] + this.offset.click.top;
6422 }
6423 if (event.pageX - this.offset.click.left > containment[2]) {
6424 pageX = containment[2] + this.offset.click.left;
6425 }
6426 if (event.pageY - this.offset.click.top > containment[3]) {
6427 pageY = containment[3] + this.offset.click.top;
6428 }
6429 }
6430
6431 if (o.grid) {
6432 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
6433 top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
6434 pageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
6435
6436 left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
6437 pageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
6438 }
6439
6440 if ( o.axis === "y" ) {
6441 pageX = this.originalPageX;
6442 }
6443
6444 if ( o.axis === "x" ) {
6445 pageY = this.originalPageY;
6446 }
6447 }
6448
6449 return {
6450 top: (
6451 pageY - // The absolute mouse position
6452 this.offset.click.top - // Click offset (relative to the element)
6453 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
6454 this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
6455 ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
6456 ),
6457 left: (
6458 pageX - // The absolute mouse position
6459 this.offset.click.left - // Click offset (relative to the element)
6460 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
6461 this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
6462 ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
6463 )
6464 };
6465
6466 },
6467
6468 _clear: function() {
6469 this.helper.removeClass("ui-draggable-dragging");
6470 if (this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
6471 this.helper.remove();
6472 }
6473 this.helper = null;
6474 this.cancelHelperRemoval = false;
6475 if ( this.destroyOnClear ) {
6476 this.destroy();
6477 }
6478 },
6479
6480 _normalizeRightBottom: function() {
6481 if ( this.options.axis !== "y" && this.helper.css( "right" ) !== "auto" ) {
6482 this.helper.width( this.helper.width() );
6483 this.helper.css( "right", "auto" );
6484 }
6485 if ( this.options.axis !== "x" && this.helper.css( "bottom" ) !== "auto" ) {
6486 this.helper.height( this.helper.height() );
6487 this.helper.css( "bottom", "auto" );
6488 }
6489 },
6490
6491 // From now on bulk stuff - mainly helpers
6492
6493 _trigger: function( type, event, ui ) {
6494 ui = ui || this._uiHash();
6495 $.ui.plugin.call( this, type, [ event, ui, this ], true );
6496
6497 // Absolute position and offset (see #6884 ) have to be recalculated after plugins
6498 if ( /^(drag|start|stop)/.test( type ) ) {
6499 this.positionAbs = this._convertPositionTo( "absolute" );
6500 ui.offset = this.positionAbs;
6501 }
6502 return $.Widget.prototype._trigger.call( this, type, event, ui );
6503 },
6504
6505 plugins: {},
6506
6507 _uiHash: function() {
6508 return {
6509 helper: this.helper,
6510 position: this.position,
6511 originalPosition: this.originalPosition,
6512 offset: this.positionAbs
6513 };
6514 }
6515
6516});
6517
6518$.ui.plugin.add( "draggable", "connectToSortable", {
6519 start: function( event, ui, draggable ) {
6520 var uiSortable = $.extend( {}, ui, {
6521 item: draggable.element
6522 });
6523
6524 draggable.sortables = [];
6525 $( draggable.options.connectToSortable ).each(function() {
6526 var sortable = $( this ).sortable( "instance" );
6527
6528 if ( sortable && !sortable.options.disabled ) {
6529 draggable.sortables.push( sortable );
6530
6531 // refreshPositions is called at drag start to refresh the containerCache
6532 // which is used in drag. This ensures it's initialized and synchronized
6533 // with any changes that might have happened on the page since initialization.
6534 sortable.refreshPositions();
6535 sortable._trigger("activate", event, uiSortable);
6536 }
6537 });
6538 },
6539 stop: function( event, ui, draggable ) {
6540 var uiSortable = $.extend( {}, ui, {
6541 item: draggable.element
6542 });
6543
6544 draggable.cancelHelperRemoval = false;
6545
6546 $.each( draggable.sortables, function() {
6547 var sortable = this;
6548
6549 if ( sortable.isOver ) {
6550 sortable.isOver = 0;
6551
6552 // Allow this sortable to handle removing the helper
6553 draggable.cancelHelperRemoval = true;
6554 sortable.cancelHelperRemoval = false;
6555
6556 // Use _storedCSS To restore properties in the sortable,
6557 // as this also handles revert (#9675) since the draggable
6558 // may have modified them in unexpected ways (#8809)
6559 sortable._storedCSS = {
6560 position: sortable.placeholder.css( "position" ),
6561 top: sortable.placeholder.css( "top" ),
6562 left: sortable.placeholder.css( "left" )
6563 };
6564
6565 sortable._mouseStop(event);
6566
6567 // Once drag has ended, the sortable should return to using
6568 // its original helper, not the shared helper from draggable
6569 sortable.options.helper = sortable.options._helper;
6570 } else {
6571 // Prevent this Sortable from removing the helper.
6572 // However, don't set the draggable to remove the helper
6573 // either as another connected Sortable may yet handle the removal.
6574 sortable.cancelHelperRemoval = true;
6575
6576 sortable._trigger( "deactivate", event, uiSortable );
6577 }
6578 });
6579 },
6580 drag: function( event, ui, draggable ) {
6581 $.each( draggable.sortables, function() {
6582 var innermostIntersecting = false,
6583 sortable = this;
6584
6585 // Copy over variables that sortable's _intersectsWith uses
6586 sortable.positionAbs = draggable.positionAbs;
6587 sortable.helperProportions = draggable.helperProportions;
6588 sortable.offset.click = draggable.offset.click;
6589
6590 if ( sortable._intersectsWith( sortable.containerCache ) ) {
6591 innermostIntersecting = true;
6592
6593 $.each( draggable.sortables, function() {
6594 // Copy over variables that sortable's _intersectsWith uses
6595 this.positionAbs = draggable.positionAbs;
6596 this.helperProportions = draggable.helperProportions;
6597 this.offset.click = draggable.offset.click;
6598
6599 if ( this !== sortable &&
6600 this._intersectsWith( this.containerCache ) &&
6601 $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
6602 innermostIntersecting = false;
6603 }
6604
6605 return innermostIntersecting;
6606 });
6607 }
6608
6609 if ( innermostIntersecting ) {
6610 // If it intersects, we use a little isOver variable and set it once,
6611 // so that the move-in stuff gets fired only once.
6612 if ( !sortable.isOver ) {
6613 sortable.isOver = 1;
6614
6615 sortable.currentItem = ui.helper
6616 .appendTo( sortable.element )
6617 .data( "ui-sortable-item", true );
6618
6619 // Store helper option to later restore it
6620 sortable.options._helper = sortable.options.helper;
6621
6622 sortable.options.helper = function() {
6623 return ui.helper[ 0 ];
6624 };
6625
6626 // Fire the start events of the sortable with our passed browser event,
6627 // and our own helper (so it doesn't create a new one)
6628 event.target = sortable.currentItem[ 0 ];
6629 sortable._mouseCapture( event, true );
6630 sortable._mouseStart( event, true, true );
6631
6632 // Because the browser event is way off the new appended portlet,
6633 // modify necessary variables to reflect the changes
6634 sortable.offset.click.top = draggable.offset.click.top;
6635 sortable.offset.click.left = draggable.offset.click.left;
6636 sortable.offset.parent.left -= draggable.offset.parent.left -
6637 sortable.offset.parent.left;
6638 sortable.offset.parent.top -= draggable.offset.parent.top -
6639 sortable.offset.parent.top;
6640
6641 draggable._trigger( "toSortable", event );
6642
6643 // Inform draggable that the helper is in a valid drop zone,
6644 // used solely in the revert option to handle "valid/invalid".
6645 draggable.dropped = sortable.element;
6646
6647 // Need to refreshPositions of all sortables in the case that
6648 // adding to one sortable changes the location of the other sortables (#9675)
6649 $.each( draggable.sortables, function() {
6650 this.refreshPositions();
6651 });
6652
6653 // hack so receive/update callbacks work (mostly)
6654 draggable.currentItem = draggable.element;
6655 sortable.fromOutside = draggable;
6656 }
6657
6658 if ( sortable.currentItem ) {
6659 sortable._mouseDrag( event );
6660 // Copy the sortable's position because the draggable's can potentially reflect
6661 // a relative position, while sortable is always absolute, which the dragged
6662 // element has now become. (#8809)
6663 ui.position = sortable.position;
6664 }
6665 } else {
6666 // If it doesn't intersect with the sortable, and it intersected before,
6667 // we fake the drag stop of the sortable, but make sure it doesn't remove
6668 // the helper by using cancelHelperRemoval.
6669 if ( sortable.isOver ) {
6670
6671 sortable.isOver = 0;
6672 sortable.cancelHelperRemoval = true;
6673
6674 // Calling sortable's mouseStop would trigger a revert,
6675 // so revert must be temporarily false until after mouseStop is called.
6676 sortable.options._revert = sortable.options.revert;
6677 sortable.options.revert = false;
6678
6679 sortable._trigger( "out", event, sortable._uiHash( sortable ) );
6680 sortable._mouseStop( event, true );
6681
6682 // restore sortable behaviors that were modfied
6683 // when the draggable entered the sortable area (#9481)
6684 sortable.options.revert = sortable.options._revert;
6685 sortable.options.helper = sortable.options._helper;
6686
6687 if ( sortable.placeholder ) {
6688 sortable.placeholder.remove();
6689 }
6690
6691 // Recalculate the draggable's offset considering the sortable
6692 // may have modified them in unexpected ways (#8809)
6693 draggable._refreshOffsets( event );
6694 ui.position = draggable._generatePosition( event, true );
6695
6696 draggable._trigger( "fromSortable", event );
6697
6698 // Inform draggable that the helper is no longer in a valid drop zone
6699 draggable.dropped = false;
6700
6701 // Need to refreshPositions of all sortables just in case removing
6702 // from one sortable changes the location of other sortables (#9675)
6703 $.each( draggable.sortables, function() {
6704 this.refreshPositions();
6705 });
6706 }
6707 }
6708 });
6709 }
6710});
6711
6712$.ui.plugin.add("draggable", "cursor", {
6713 start: function( event, ui, instance ) {
6714 var t = $( "body" ),
6715 o = instance.options;
6716
6717 if (t.css("cursor")) {
6718 o._cursor = t.css("cursor");
6719 }
6720 t.css("cursor", o.cursor);
6721 },
6722 stop: function( event, ui, instance ) {
6723 var o = instance.options;
6724 if (o._cursor) {
6725 $("body").css("cursor", o._cursor);
6726 }
6727 }
6728});
6729
6730$.ui.plugin.add("draggable", "opacity", {
6731 start: function( event, ui, instance ) {
6732 var t = $( ui.helper ),
6733 o = instance.options;
6734 if (t.css("opacity")) {
6735 o._opacity = t.css("opacity");
6736 }
6737 t.css("opacity", o.opacity);
6738 },
6739 stop: function( event, ui, instance ) {
6740 var o = instance.options;
6741 if (o._opacity) {
6742 $(ui.helper).css("opacity", o._opacity);
6743 }
6744 }
6745});
6746
6747$.ui.plugin.add("draggable", "scroll", {
6748 start: function( event, ui, i ) {
6749 if ( !i.scrollParentNotHidden ) {
6750 i.scrollParentNotHidden = i.helper.scrollParent( false );
6751 }
6752
6753 if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] && i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
6754 i.overflowOffset = i.scrollParentNotHidden.offset();
6755 }
6756 },
6757 drag: function( event, ui, i ) {
6758
6759 var o = i.options,
6760 scrolled = false,
6761 scrollParent = i.scrollParentNotHidden[ 0 ],
6762 document = i.document[ 0 ];
6763
6764 if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
6765 if ( !o.axis || o.axis !== "x" ) {
6766 if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY < o.scrollSensitivity ) {
6767 scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
6768 } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
6769 scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
6770 }
6771 }
6772
6773 if ( !o.axis || o.axis !== "y" ) {
6774 if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX < o.scrollSensitivity ) {
6775 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
6776 } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
6777 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
6778 }
6779 }
6780
6781 } else {
6782
6783 if (!o.axis || o.axis !== "x") {
6784 if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
6785 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
6786 } else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
6787 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
6788 }
6789 }
6790
6791 if (!o.axis || o.axis !== "y") {
6792 if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
6793 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
6794 } else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
6795 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
6796 }
6797 }
6798
6799 }
6800
6801 if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
6802 $.ui.ddmanager.prepareOffsets(i, event);
6803 }
6804
6805 }
6806});
6807
6808$.ui.plugin.add("draggable", "snap", {
6809 start: function( event, ui, i ) {
6810
6811 var o = i.options;
6812
6813 i.snapElements = [];
6814
6815 $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
6816 var $t = $(this),
6817 $o = $t.offset();
6818 if (this !== i.element[0]) {
6819 i.snapElements.push({
6820 item: this,
6821 width: $t.outerWidth(), height: $t.outerHeight(),
6822 top: $o.top, left: $o.left
6823 });
6824 }
6825 });
6826
6827 },
6828 drag: function( event, ui, inst ) {
6829
6830 var ts, bs, ls, rs, l, r, t, b, i, first,
6831 o = inst.options,
6832 d = o.snapTolerance,
6833 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
6834 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
6835
6836 for (i = inst.snapElements.length - 1; i >= 0; i--){
6837
6838 l = inst.snapElements[i].left - inst.margins.left;
6839 r = l + inst.snapElements[i].width;
6840 t = inst.snapElements[i].top - inst.margins.top;
6841 b = t + inst.snapElements[i].height;
6842
6843 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {
6844 if (inst.snapElements[i].snapping) {
6845 (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
6846 }
6847 inst.snapElements[i].snapping = false;
6848 continue;
6849 }
6850
6851 if (o.snapMode !== "inner") {
6852 ts = Math.abs(t - y2) <= d;
6853 bs = Math.abs(b - y1) <= d;
6854 ls = Math.abs(l - x2) <= d;
6855 rs = Math.abs(r - x1) <= d;
6856 if (ts) {
6857 ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top;
6858 }
6859 if (bs) {
6860 ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top;
6861 }
6862 if (ls) {
6863 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left;
6864 }
6865 if (rs) {
6866 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left;
6867 }
6868 }
6869
6870 first = (ts || bs || ls || rs);
6871
6872 if (o.snapMode !== "outer") {
6873 ts = Math.abs(t - y1) <= d;
6874 bs = Math.abs(b - y2) <= d;
6875 ls = Math.abs(l - x1) <= d;
6876 rs = Math.abs(r - x2) <= d;
6877 if (ts) {
6878 ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top;
6879 }
6880 if (bs) {
6881 ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top;
6882 }
6883 if (ls) {
6884 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left;
6885 }
6886 if (rs) {
6887 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left;
6888 }
6889 }
6890
6891 if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
6892 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
6893 }
6894 inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
6895
6896 }
6897
6898 }
6899});
6900
6901$.ui.plugin.add("draggable", "stack", {
6902 start: function( event, ui, instance ) {
6903 var min,
6904 o = instance.options,
6905 group = $.makeArray($(o.stack)).sort(function(a, b) {
6906 return (parseInt($(a).css("zIndex"), 10) || 0) - (parseInt($(b).css("zIndex"), 10) || 0);
6907 });
6908
6909 if (!group.length) { return; }
6910
6911 min = parseInt($(group[0]).css("zIndex"), 10) || 0;
6912 $(group).each(function(i) {
6913 $(this).css("zIndex", min + i);
6914 });
6915 this.css("zIndex", (min + group.length));
6916 }
6917});
6918
6919$.ui.plugin.add("draggable", "zIndex", {
6920 start: function( event, ui, instance ) {
6921 var t = $( ui.helper ),
6922 o = instance.options;
6923
6924 if (t.css("zIndex")) {
6925 o._zIndex = t.css("zIndex");
6926 }
6927 t.css("zIndex", o.zIndex);
6928 },
6929 stop: function( event, ui, instance ) {
6930 var o = instance.options;
6931
6932 if (o._zIndex) {
6933 $(ui.helper).css("zIndex", o._zIndex);
6934 }
6935 }
6936});
6937
6938var draggable = $.ui.draggable;
6939
6940
6941/*!
6942 * jQuery UI Resizable 1.11.2
6943 * http://jqueryui.com
6944 *
6945 * Copyright 2014 jQuery Foundation and other contributors
6946 * Released under the MIT license.
6947 * http://jquery.org/license
6948 *
6949 * http://api.jqueryui.com/resizable/
6950 */
6951
6952
6953$.widget("ui.resizable", $.ui.mouse, {
6954 version: "1.11.2",
6955 widgetEventPrefix: "resize",
6956 options: {
6957 alsoResize: false,
6958 animate: false,
6959 animateDuration: "slow",
6960 animateEasing: "swing",
6961 aspectRatio: false,
6962 autoHide: false,
6963 containment: false,
6964 ghost: false,
6965 grid: false,
6966 handles: "e,s,se",
6967 helper: false,
6968 maxHeight: null,
6969 maxWidth: null,
6970 minHeight: 10,
6971 minWidth: 10,
6972 // See #7960
6973 zIndex: 90,
6974
6975 // callbacks
6976 resize: null,
6977 start: null,
6978 stop: null
6979 },
6980
6981 _num: function( value ) {
6982 return parseInt( value, 10 ) || 0;
6983 },
6984
6985 _isNumber: function( value ) {
6986 return !isNaN( parseInt( value, 10 ) );
6987 },
6988
6989 _hasScroll: function( el, a ) {
6990
6991 if ( $( el ).css( "overflow" ) === "hidden") {
6992 return false;
6993 }
6994
6995 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
6996 has = false;
6997
6998 if ( el[ scroll ] > 0 ) {
6999 return true;
7000 }
7001
7002 // TODO: determine which cases actually cause this to happen
7003 // if the element doesn't have the scroll set, see if it's possible to
7004 // set the scroll
7005 el[ scroll ] = 1;
7006 has = ( el[ scroll ] > 0 );
7007 el[ scroll ] = 0;
7008 return has;
7009 },
7010
7011 _create: function() {
7012
7013 var n, i, handle, axis, hname,
7014 that = this,
7015 o = this.options;
7016 this.element.addClass("ui-resizable");
7017
7018 $.extend(this, {
7019 _aspectRatio: !!(o.aspectRatio),
7020 aspectRatio: o.aspectRatio,
7021 originalElement: this.element,
7022 _proportionallyResizeElements: [],
7023 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
7024 });
7025
7026 // Wrap the element if it cannot hold child nodes
7027 if (this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
7028
7029 this.element.wrap(
7030 $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
7031 position: this.element.css("position"),
7032 width: this.element.outerWidth(),
7033 height: this.element.outerHeight(),
7034 top: this.element.css("top"),
7035 left: this.element.css("left")
7036 })
7037 );
7038
7039 this.element = this.element.parent().data(
7040 "ui-resizable", this.element.resizable( "instance" )
7041 );
7042
7043 this.elementIsWrapper = true;
7044
7045 this.element.css({
7046 marginLeft: this.originalElement.css("marginLeft"),
7047 marginTop: this.originalElement.css("marginTop"),
7048 marginRight: this.originalElement.css("marginRight"),
7049 marginBottom: this.originalElement.css("marginBottom")
7050 });
7051 this.originalElement.css({
7052 marginLeft: 0,
7053 marginTop: 0,
7054 marginRight: 0,
7055 marginBottom: 0
7056 });
7057 // support: Safari
7058 // Prevent Safari textarea resize
7059 this.originalResizeStyle = this.originalElement.css("resize");
7060 this.originalElement.css("resize", "none");
7061
7062 this._proportionallyResizeElements.push( this.originalElement.css({
7063 position: "static",
7064 zoom: 1,
7065 display: "block"
7066 }) );
7067
7068 // support: IE9
7069 // avoid IE jump (hard set the margin)
7070 this.originalElement.css({ margin: this.originalElement.css("margin") });
7071
7072 this._proportionallyResize();
7073 }
7074
7075 this.handles = o.handles ||
7076 ( !$(".ui-resizable-handle", this.element).length ?
7077 "e,s,se" : {
7078 n: ".ui-resizable-n",
7079 e: ".ui-resizable-e",
7080 s: ".ui-resizable-s",
7081 w: ".ui-resizable-w",
7082 se: ".ui-resizable-se",
7083 sw: ".ui-resizable-sw",
7084 ne: ".ui-resizable-ne",
7085 nw: ".ui-resizable-nw"
7086 } );
7087
7088 if (this.handles.constructor === String) {
7089
7090 if ( this.handles === "all") {
7091 this.handles = "n,e,s,w,se,sw,ne,nw";
7092 }
7093
7094 n = this.handles.split(",");
7095 this.handles = {};
7096
7097 for (i = 0; i < n.length; i++) {
7098
7099 handle = $.trim(n[i]);
7100 hname = "ui-resizable-" + handle;
7101 axis = $("<div class='ui-resizable-handle " + hname + "'></div>");
7102
7103 axis.css({ zIndex: o.zIndex });
7104
7105 // TODO : What's going on here?
7106 if ("se" === handle) {
7107 axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
7108 }
7109
7110 this.handles[handle] = ".ui-resizable-" + handle;
7111 this.element.append(axis);
7112 }
7113
7114 }
7115
7116 this._renderAxis = function(target) {
7117
7118 var i, axis, padPos, padWrapper;
7119
7120 target = target || this.element;
7121
7122 for (i in this.handles) {
7123
7124 if (this.handles[i].constructor === String) {
7125 this.handles[i] = this.element.children( this.handles[ i ] ).first().show();
7126 }
7127
7128 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
7129
7130 axis = $(this.handles[i], this.element);
7131
7132 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
7133
7134 padPos = [ "padding",
7135 /ne|nw|n/.test(i) ? "Top" :
7136 /se|sw|s/.test(i) ? "Bottom" :
7137 /^e$/.test(i) ? "Right" : "Left" ].join("");
7138
7139 target.css(padPos, padWrapper);
7140
7141 this._proportionallyResize();
7142
7143 }
7144
7145 // TODO: What's that good for? There's not anything to be executed left
7146 if (!$(this.handles[i]).length) {
7147 continue;
7148 }
7149 }
7150 };
7151
7152 // TODO: make renderAxis a prototype function
7153 this._renderAxis(this.element);
7154
7155 this._handles = $(".ui-resizable-handle", this.element)
7156 .disableSelection();
7157
7158 this._handles.mouseover(function() {
7159 if (!that.resizing) {
7160 if (this.className) {
7161 axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
7162 }
7163 that.axis = axis && axis[1] ? axis[1] : "se";
7164 }
7165 });
7166
7167 if (o.autoHide) {
7168 this._handles.hide();
7169 $(this.element)
7170 .addClass("ui-resizable-autohide")
7171 .mouseenter(function() {
7172 if (o.disabled) {
7173 return;
7174 }
7175 $(this).removeClass("ui-resizable-autohide");
7176 that._handles.show();
7177 })
7178 .mouseleave(function() {
7179 if (o.disabled) {
7180 return;
7181 }
7182 if (!that.resizing) {
7183 $(this).addClass("ui-resizable-autohide");
7184 that._handles.hide();
7185 }
7186 });
7187 }
7188
7189 this._mouseInit();
7190
7191 },
7192
7193 _destroy: function() {
7194
7195 this._mouseDestroy();
7196
7197 var wrapper,
7198 _destroy = function(exp) {
7199 $(exp)
7200 .removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
7201 .removeData("resizable")
7202 .removeData("ui-resizable")
7203 .unbind(".resizable")
7204 .find(".ui-resizable-handle")
7205 .remove();
7206 };
7207
7208 // TODO: Unwrap at same DOM position
7209 if (this.elementIsWrapper) {
7210 _destroy(this.element);
7211 wrapper = this.element;
7212 this.originalElement.css({
7213 position: wrapper.css("position"),
7214 width: wrapper.outerWidth(),
7215 height: wrapper.outerHeight(),
7216 top: wrapper.css("top"),
7217 left: wrapper.css("left")
7218 }).insertAfter( wrapper );
7219 wrapper.remove();
7220 }
7221
7222 this.originalElement.css("resize", this.originalResizeStyle);
7223 _destroy(this.originalElement);
7224
7225 return this;
7226 },
7227
7228 _mouseCapture: function(event) {
7229 var i, handle,
7230 capture = false;
7231
7232 for (i in this.handles) {
7233 handle = $(this.handles[i])[0];
7234 if (handle === event.target || $.contains(handle, event.target)) {
7235 capture = true;
7236 }
7237 }
7238
7239 return !this.options.disabled && capture;
7240 },
7241
7242 _mouseStart: function(event) {
7243
7244 var curleft, curtop, cursor,
7245 o = this.options,
7246 el = this.element;
7247
7248 this.resizing = true;
7249
7250 this._renderProxy();
7251
7252 curleft = this._num(this.helper.css("left"));
7253 curtop = this._num(this.helper.css("top"));
7254
7255 if (o.containment) {
7256 curleft += $(o.containment).scrollLeft() || 0;
7257 curtop += $(o.containment).scrollTop() || 0;
7258 }
7259
7260 this.offset = this.helper.offset();
7261 this.position = { left: curleft, top: curtop };
7262
7263 this.size = this._helper ? {
7264 width: this.helper.width(),
7265 height: this.helper.height()
7266 } : {
7267 width: el.width(),
7268 height: el.height()
7269 };
7270
7271 this.originalSize = this._helper ? {
7272 width: el.outerWidth(),
7273 height: el.outerHeight()
7274 } : {
7275 width: el.width(),
7276 height: el.height()
7277 };
7278
7279 this.sizeDiff = {
7280 width: el.outerWidth() - el.width(),
7281 height: el.outerHeight() - el.height()
7282 };
7283
7284 this.originalPosition = { left: curleft, top: curtop };
7285 this.originalMousePosition = { left: event.pageX, top: event.pageY };
7286
7287 this.aspectRatio = (typeof o.aspectRatio === "number") ?
7288 o.aspectRatio :
7289 ((this.originalSize.width / this.originalSize.height) || 1);
7290
7291 cursor = $(".ui-resizable-" + this.axis).css("cursor");
7292 $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
7293
7294 el.addClass("ui-resizable-resizing");
7295 this._propagate("start", event);
7296 return true;
7297 },
7298
7299 _mouseDrag: function(event) {
7300
7301 var data, props,
7302 smp = this.originalMousePosition,
7303 a = this.axis,
7304 dx = (event.pageX - smp.left) || 0,
7305 dy = (event.pageY - smp.top) || 0,
7306 trigger = this._change[a];
7307
7308 this._updatePrevProperties();
7309
7310 if (!trigger) {
7311 return false;
7312 }
7313
7314 data = trigger.apply(this, [ event, dx, dy ]);
7315
7316 this._updateVirtualBoundaries(event.shiftKey);
7317 if (this._aspectRatio || event.shiftKey) {
7318 data = this._updateRatio(data, event);
7319 }
7320
7321 data = this._respectSize(data, event);
7322
7323 this._updateCache(data);
7324
7325 this._propagate("resize", event);
7326
7327 props = this._applyChanges();
7328
7329 if ( !this._helper && this._proportionallyResizeElements.length ) {
7330 this._proportionallyResize();
7331 }
7332
7333 if ( !$.isEmptyObject( props ) ) {
7334 this._updatePrevProperties();
7335 this._trigger( "resize", event, this.ui() );
7336 this._applyChanges();
7337 }
7338
7339 return false;
7340 },
7341
7342 _mouseStop: function(event) {
7343
7344 this.resizing = false;
7345 var pr, ista, soffseth, soffsetw, s, left, top,
7346 o = this.options, that = this;
7347
7348 if (this._helper) {
7349
7350 pr = this._proportionallyResizeElements;
7351 ista = pr.length && (/textarea/i).test(pr[0].nodeName);
7352 soffseth = ista && this._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height;
7353 soffsetw = ista ? 0 : that.sizeDiff.width;
7354
7355 s = {
7356 width: (that.helper.width() - soffsetw),
7357 height: (that.helper.height() - soffseth)
7358 };
7359 left = (parseInt(that.element.css("left"), 10) +
7360 (that.position.left - that.originalPosition.left)) || null;
7361 top = (parseInt(that.element.css("top"), 10) +
7362 (that.position.top - that.originalPosition.top)) || null;
7363
7364 if (!o.animate) {
7365 this.element.css($.extend(s, { top: top, left: left }));
7366 }
7367
7368 that.helper.height(that.size.height);
7369 that.helper.width(that.size.width);
7370
7371 if (this._helper && !o.animate) {
7372 this._proportionallyResize();
7373 }
7374 }
7375
7376 $("body").css("cursor", "auto");
7377
7378 this.element.removeClass("ui-resizable-resizing");
7379
7380 this._propagate("stop", event);
7381
7382 if (this._helper) {
7383 this.helper.remove();
7384 }
7385
7386 return false;
7387
7388 },
7389
7390 _updatePrevProperties: function() {
7391 this.prevPosition = {
7392 top: this.position.top,
7393 left: this.position.left
7394 };
7395 this.prevSize = {
7396 width: this.size.width,
7397 height: this.size.height
7398 };
7399 },
7400
7401 _applyChanges: function() {
7402 var props = {};
7403
7404 if ( this.position.top !== this.prevPosition.top ) {
7405 props.top = this.position.top + "px";
7406 }
7407 if ( this.position.left !== this.prevPosition.left ) {
7408 props.left = this.position.left + "px";
7409 }
7410 if ( this.size.width !== this.prevSize.width ) {
7411 props.width = this.size.width + "px";
7412 }
7413 if ( this.size.height !== this.prevSize.height ) {
7414 props.height = this.size.height + "px";
7415 }
7416
7417 this.helper.css( props );
7418
7419 return props;
7420 },
7421
7422 _updateVirtualBoundaries: function(forceAspectRatio) {
7423 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
7424 o = this.options;
7425
7426 b = {
7427 minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0,
7428 maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity,
7429 minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0,
7430 maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity
7431 };
7432
7433 if (this._aspectRatio || forceAspectRatio) {
7434 pMinWidth = b.minHeight * this.aspectRatio;
7435 pMinHeight = b.minWidth / this.aspectRatio;
7436 pMaxWidth = b.maxHeight * this.aspectRatio;
7437 pMaxHeight = b.maxWidth / this.aspectRatio;
7438
7439 if (pMinWidth > b.minWidth) {
7440 b.minWidth = pMinWidth;
7441 }
7442 if (pMinHeight > b.minHeight) {
7443 b.minHeight = pMinHeight;
7444 }
7445 if (pMaxWidth < b.maxWidth) {
7446 b.maxWidth = pMaxWidth;
7447 }
7448 if (pMaxHeight < b.maxHeight) {
7449 b.maxHeight = pMaxHeight;
7450 }
7451 }
7452 this._vBoundaries = b;
7453 },
7454
7455 _updateCache: function(data) {
7456 this.offset = this.helper.offset();
7457 if (this._isNumber(data.left)) {
7458 this.position.left = data.left;
7459 }
7460 if (this._isNumber(data.top)) {
7461 this.position.top = data.top;
7462 }
7463 if (this._isNumber(data.height)) {
7464 this.size.height = data.height;
7465 }
7466 if (this._isNumber(data.width)) {
7467 this.size.width = data.width;
7468 }
7469 },
7470
7471 _updateRatio: function( data ) {
7472
7473 var cpos = this.position,
7474 csize = this.size,
7475 a = this.axis;
7476
7477 if (this._isNumber(data.height)) {
7478 data.width = (data.height * this.aspectRatio);
7479 } else if (this._isNumber(data.width)) {
7480 data.height = (data.width / this.aspectRatio);
7481 }
7482
7483 if (a === "sw") {
7484 data.left = cpos.left + (csize.width - data.width);
7485 data.top = null;
7486 }
7487 if (a === "nw") {
7488 data.top = cpos.top + (csize.height - data.height);
7489 data.left = cpos.left + (csize.width - data.width);
7490 }
7491
7492 return data;
7493 },
7494
7495 _respectSize: function( data ) {
7496
7497 var o = this._vBoundaries,
7498 a = this.axis,
7499 ismaxw = this._isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width),
7500 ismaxh = this._isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
7501 isminw = this._isNumber(data.width) && o.minWidth && (o.minWidth > data.width),
7502 isminh = this._isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
7503 dw = this.originalPosition.left + this.originalSize.width,
7504 dh = this.position.top + this.size.height,
7505 cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
7506 if (isminw) {
7507 data.width = o.minWidth;
7508 }
7509 if (isminh) {
7510 data.height = o.minHeight;
7511 }
7512 if (ismaxw) {
7513 data.width = o.maxWidth;
7514 }
7515 if (ismaxh) {
7516 data.height = o.maxHeight;
7517 }
7518
7519 if (isminw && cw) {
7520 data.left = dw - o.minWidth;
7521 }
7522 if (ismaxw && cw) {
7523 data.left = dw - o.maxWidth;
7524 }
7525 if (isminh && ch) {
7526 data.top = dh - o.minHeight;
7527 }
7528 if (ismaxh && ch) {
7529 data.top = dh - o.maxHeight;
7530 }
7531
7532 // Fixing jump error on top/left - bug #2330
7533 if (!data.width && !data.height && !data.left && data.top) {
7534 data.top = null;
7535 } else if (!data.width && !data.height && !data.top && data.left) {
7536 data.left = null;
7537 }
7538
7539 return data;
7540 },
7541
7542 _getPaddingPlusBorderDimensions: function( element ) {
7543 var i = 0,
7544 widths = [],
7545 borders = [
7546 element.css( "borderTopWidth" ),
7547 element.css( "borderRightWidth" ),
7548 element.css( "borderBottomWidth" ),
7549 element.css( "borderLeftWidth" )
7550 ],
7551 paddings = [
7552 element.css( "paddingTop" ),
7553 element.css( "paddingRight" ),
7554 element.css( "paddingBottom" ),
7555 element.css( "paddingLeft" )
7556 ];
7557
7558 for ( ; i < 4; i++ ) {
7559 widths[ i ] = ( parseInt( borders[ i ], 10 ) || 0 );
7560 widths[ i ] += ( parseInt( paddings[ i ], 10 ) || 0 );
7561 }
7562
7563 return {
7564 height: widths[ 0 ] + widths[ 2 ],
7565 width: widths[ 1 ] + widths[ 3 ]
7566 };
7567 },
7568
7569 _proportionallyResize: function() {
7570
7571 if (!this._proportionallyResizeElements.length) {
7572 return;
7573 }
7574
7575 var prel,
7576 i = 0,
7577 element = this.helper || this.element;
7578
7579 for ( ; i < this._proportionallyResizeElements.length; i++) {
7580
7581 prel = this._proportionallyResizeElements[i];
7582
7583 // TODO: Seems like a bug to cache this.outerDimensions
7584 // considering that we are in a loop.
7585 if (!this.outerDimensions) {
7586 this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
7587 }
7588
7589 prel.css({
7590 height: (element.height() - this.outerDimensions.height) || 0,
7591 width: (element.width() - this.outerDimensions.width) || 0
7592 });
7593
7594 }
7595
7596 },
7597
7598 _renderProxy: function() {
7599
7600 var el = this.element, o = this.options;
7601 this.elementOffset = el.offset();
7602
7603 if (this._helper) {
7604
7605 this.helper = this.helper || $("<div style='overflow:hidden;'></div>");
7606
7607 this.helper.addClass(this._helper).css({
7608 width: this.element.outerWidth() - 1,
7609 height: this.element.outerHeight() - 1,
7610 position: "absolute",
7611 left: this.elementOffset.left + "px",
7612 top: this.elementOffset.top + "px",
7613 zIndex: ++o.zIndex //TODO: Don't modify option
7614 });
7615
7616 this.helper
7617 .appendTo("body")
7618 .disableSelection();
7619
7620 } else {
7621 this.helper = this.element;
7622 }
7623
7624 },
7625
7626 _change: {
7627 e: function(event, dx) {
7628 return { width: this.originalSize.width + dx };
7629 },
7630 w: function(event, dx) {
7631 var cs = this.originalSize, sp = this.originalPosition;
7632 return { left: sp.left + dx, width: cs.width - dx };
7633 },
7634 n: function(event, dx, dy) {
7635 var cs = this.originalSize, sp = this.originalPosition;
7636 return { top: sp.top + dy, height: cs.height - dy };
7637 },
7638 s: function(event, dx, dy) {
7639 return { height: this.originalSize.height + dy };
7640 },
7641 se: function(event, dx, dy) {
7642 return $.extend(this._change.s.apply(this, arguments),
7643 this._change.e.apply(this, [ event, dx, dy ]));
7644 },
7645 sw: function(event, dx, dy) {
7646 return $.extend(this._change.s.apply(this, arguments),
7647 this._change.w.apply(this, [ event, dx, dy ]));
7648 },
7649 ne: function(event, dx, dy) {
7650 return $.extend(this._change.n.apply(this, arguments),
7651 this._change.e.apply(this, [ event, dx, dy ]));
7652 },
7653 nw: function(event, dx, dy) {
7654 return $.extend(this._change.n.apply(this, arguments),
7655 this._change.w.apply(this, [ event, dx, dy ]));
7656 }
7657 },
7658
7659 _propagate: function(n, event) {
7660 $.ui.plugin.call(this, n, [ event, this.ui() ]);
7661 (n !== "resize" && this._trigger(n, event, this.ui()));
7662 },
7663
7664 plugins: {},
7665
7666 ui: function() {
7667 return {
7668 originalElement: this.originalElement,
7669 element: this.element,
7670 helper: this.helper,
7671 position: this.position,
7672 size: this.size,
7673 originalSize: this.originalSize,
7674 originalPosition: this.originalPosition
7675 };
7676 }
7677
7678});
7679
7680/*
7681 * Resizable Extensions
7682 */
7683
7684$.ui.plugin.add("resizable", "animate", {
7685
7686 stop: function( event ) {
7687 var that = $(this).resizable( "instance" ),
7688 o = that.options,
7689 pr = that._proportionallyResizeElements,
7690 ista = pr.length && (/textarea/i).test(pr[0].nodeName),
7691 soffseth = ista && that._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height,
7692 soffsetw = ista ? 0 : that.sizeDiff.width,
7693 style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
7694 left = (parseInt(that.element.css("left"), 10) +
7695 (that.position.left - that.originalPosition.left)) || null,
7696 top = (parseInt(that.element.css("top"), 10) +
7697 (that.position.top - that.originalPosition.top)) || null;
7698
7699 that.element.animate(
7700 $.extend(style, top && left ? { top: top, left: left } : {}), {
7701 duration: o.animateDuration,
7702 easing: o.animateEasing,
7703 step: function() {
7704
7705 var data = {
7706 width: parseInt(that.element.css("width"), 10),
7707 height: parseInt(that.element.css("height"), 10),
7708 top: parseInt(that.element.css("top"), 10),
7709 left: parseInt(that.element.css("left"), 10)
7710 };
7711
7712 if (pr && pr.length) {
7713 $(pr[0]).css({ width: data.width, height: data.height });
7714 }
7715
7716 // propagating resize, and updating values for each animation step
7717 that._updateCache(data);
7718 that._propagate("resize", event);
7719
7720 }
7721 }
7722 );
7723 }
7724
7725});
7726
7727$.ui.plugin.add( "resizable", "containment", {
7728
7729 start: function() {
7730 var element, p, co, ch, cw, width, height,
7731 that = $( this ).resizable( "instance" ),
7732 o = that.options,
7733 el = that.element,
7734 oc = o.containment,
7735 ce = ( oc instanceof $ ) ? oc.get( 0 ) : ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
7736
7737 if ( !ce ) {
7738 return;
7739 }
7740
7741 that.containerElement = $( ce );
7742
7743 if ( /document/.test( oc ) || oc === document ) {
7744 that.containerOffset = {
7745 left: 0,
7746 top: 0
7747 };
7748 that.containerPosition = {
7749 left: 0,
7750 top: 0
7751 };
7752
7753 that.parentData = {
7754 element: $( document ),
7755 left: 0,
7756 top: 0,
7757 width: $( document ).width(),
7758 height: $( document ).height() || document.body.parentNode.scrollHeight
7759 };
7760 } else {
7761 element = $( ce );
7762 p = [];
7763 $([ "Top", "Right", "Left", "Bottom" ]).each(function( i, name ) {
7764 p[ i ] = that._num( element.css( "padding" + name ) );
7765 });
7766
7767 that.containerOffset = element.offset();
7768 that.containerPosition = element.position();
7769 that.containerSize = {
7770 height: ( element.innerHeight() - p[ 3 ] ),
7771 width: ( element.innerWidth() - p[ 1 ] )
7772 };
7773
7774 co = that.containerOffset;
7775 ch = that.containerSize.height;
7776 cw = that.containerSize.width;
7777 width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
7778 height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;
7779
7780 that.parentData = {
7781 element: ce,
7782 left: co.left,
7783 top: co.top,
7784 width: width,
7785 height: height
7786 };
7787 }
7788 },
7789
7790 resize: function( event ) {
7791 var woset, hoset, isParent, isOffsetRelative,
7792 that = $( this ).resizable( "instance" ),
7793 o = that.options,
7794 co = that.containerOffset,
7795 cp = that.position,
7796 pRatio = that._aspectRatio || event.shiftKey,
7797 cop = {
7798 top: 0,
7799 left: 0
7800 },
7801 ce = that.containerElement,
7802 continueResize = true;
7803
7804 if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
7805 cop = co;
7806 }
7807
7808 if ( cp.left < ( that._helper ? co.left : 0 ) ) {
7809 that.size.width = that.size.width +
7810 ( that._helper ?
7811 ( that.position.left - co.left ) :
7812 ( that.position.left - cop.left ) );
7813
7814 if ( pRatio ) {
7815 that.size.height = that.size.width / that.aspectRatio;
7816 continueResize = false;
7817 }
7818 that.position.left = o.helper ? co.left : 0;
7819 }
7820
7821 if ( cp.top < ( that._helper ? co.top : 0 ) ) {
7822 that.size.height = that.size.height +
7823 ( that._helper ?
7824 ( that.position.top - co.top ) :
7825 that.position.top );
7826
7827 if ( pRatio ) {
7828 that.size.width = that.size.height * that.aspectRatio;
7829 continueResize = false;
7830 }
7831 that.position.top = that._helper ? co.top : 0;
7832 }
7833
7834 isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
7835 isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
7836
7837 if ( isParent && isOffsetRelative ) {
7838 that.offset.left = that.parentData.left + that.position.left;
7839 that.offset.top = that.parentData.top + that.position.top;
7840 } else {
7841 that.offset.left = that.element.offset().left;
7842 that.offset.top = that.element.offset().top;
7843 }
7844
7845 woset = Math.abs( that.sizeDiff.width +
7846 (that._helper ?
7847 that.offset.left - cop.left :
7848 (that.offset.left - co.left)) );
7849
7850 hoset = Math.abs( that.sizeDiff.height +
7851 (that._helper ?
7852 that.offset.top - cop.top :
7853 (that.offset.top - co.top)) );
7854
7855 if ( woset + that.size.width >= that.parentData.width ) {
7856 that.size.width = that.parentData.width - woset;
7857 if ( pRatio ) {
7858 that.size.height = that.size.width / that.aspectRatio;
7859 continueResize = false;
7860 }
7861 }
7862
7863 if ( hoset + that.size.height >= that.parentData.height ) {
7864 that.size.height = that.parentData.height - hoset;
7865 if ( pRatio ) {
7866 that.size.width = that.size.height * that.aspectRatio;
7867 continueResize = false;
7868 }
7869 }
7870
7871 if ( !continueResize ){
7872 that.position.left = that.prevPosition.left;
7873 that.position.top = that.prevPosition.top;
7874 that.size.width = that.prevSize.width;
7875 that.size.height = that.prevSize.height;
7876 }
7877 },
7878
7879 stop: function() {
7880 var that = $( this ).resizable( "instance" ),
7881 o = that.options,
7882 co = that.containerOffset,
7883 cop = that.containerPosition,
7884 ce = that.containerElement,
7885 helper = $( that.helper ),
7886 ho = helper.offset(),
7887 w = helper.outerWidth() - that.sizeDiff.width,
7888 h = helper.outerHeight() - that.sizeDiff.height;
7889
7890 if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
7891 $( this ).css({
7892 left: ho.left - cop.left - co.left,
7893 width: w,
7894 height: h
7895 });
7896 }
7897
7898 if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
7899 $( this ).css({
7900 left: ho.left - cop.left - co.left,
7901 width: w,
7902 height: h
7903 });
7904 }
7905 }
7906});
7907
7908$.ui.plugin.add("resizable", "alsoResize", {
7909
7910 start: function() {
7911 var that = $(this).resizable( "instance" ),
7912 o = that.options,
7913 _store = function(exp) {
7914 $(exp).each(function() {
7915 var el = $(this);
7916 el.data("ui-resizable-alsoresize", {
7917 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
7918 left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
7919 });
7920 });
7921 };
7922
7923 if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) {
7924 if (o.alsoResize.length) {
7925 o.alsoResize = o.alsoResize[0];
7926 _store(o.alsoResize);
7927 } else {
7928 $.each(o.alsoResize, function(exp) {
7929 _store(exp);
7930 });
7931 }
7932 } else {
7933 _store(o.alsoResize);
7934 }
7935 },
7936
7937 resize: function(event, ui) {
7938 var that = $(this).resizable( "instance" ),
7939 o = that.options,
7940 os = that.originalSize,
7941 op = that.originalPosition,
7942 delta = {
7943 height: (that.size.height - os.height) || 0,
7944 width: (that.size.width - os.width) || 0,
7945 top: (that.position.top - op.top) || 0,
7946 left: (that.position.left - op.left) || 0
7947 },
7948
7949 _alsoResize = function(exp, c) {
7950 $(exp).each(function() {
7951 var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
7952 css = c && c.length ?
7953 c :
7954 el.parents(ui.originalElement[0]).length ?
7955 [ "width", "height" ] :
7956 [ "width", "height", "top", "left" ];
7957
7958 $.each(css, function(i, prop) {
7959 var sum = (start[prop] || 0) + (delta[prop] || 0);
7960 if (sum && sum >= 0) {
7961 style[prop] = sum || null;
7962 }
7963 });
7964
7965 el.css(style);
7966 });
7967 };
7968
7969 if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) {
7970 $.each(o.alsoResize, function(exp, c) {
7971 _alsoResize(exp, c);
7972 });
7973 } else {
7974 _alsoResize(o.alsoResize);
7975 }
7976 },
7977
7978 stop: function() {
7979 $(this).removeData("resizable-alsoresize");
7980 }
7981});
7982
7983$.ui.plugin.add("resizable", "ghost", {
7984
7985 start: function() {
7986
7987 var that = $(this).resizable( "instance" ), o = that.options, cs = that.size;
7988
7989 that.ghost = that.originalElement.clone();
7990 that.ghost
7991 .css({
7992 opacity: 0.25,
7993 display: "block",
7994 position: "relative",
7995 height: cs.height,
7996 width: cs.width,
7997 margin: 0,
7998 left: 0,
7999 top: 0
8000 })
8001 .addClass("ui-resizable-ghost")
8002 .addClass(typeof o.ghost === "string" ? o.ghost : "");
8003
8004 that.ghost.appendTo(that.helper);
8005
8006 },
8007
8008 resize: function() {
8009 var that = $(this).resizable( "instance" );
8010 if (that.ghost) {
8011 that.ghost.css({
8012 position: "relative",
8013 height: that.size.height,
8014 width: that.size.width
8015 });
8016 }
8017 },
8018
8019 stop: function() {
8020 var that = $(this).resizable( "instance" );
8021 if (that.ghost && that.helper) {
8022 that.helper.get(0).removeChild(that.ghost.get(0));
8023 }
8024 }
8025
8026});
8027
8028$.ui.plugin.add("resizable", "grid", {
8029
8030 resize: function() {
8031 var outerDimensions,
8032 that = $(this).resizable( "instance" ),
8033 o = that.options,
8034 cs = that.size,
8035 os = that.originalSize,
8036 op = that.originalPosition,
8037 a = that.axis,
8038 grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
8039 gridX = (grid[0] || 1),
8040 gridY = (grid[1] || 1),
8041 ox = Math.round((cs.width - os.width) / gridX) * gridX,
8042 oy = Math.round((cs.height - os.height) / gridY) * gridY,
8043 newWidth = os.width + ox,
8044 newHeight = os.height + oy,
8045 isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
8046 isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
8047 isMinWidth = o.minWidth && (o.minWidth > newWidth),
8048 isMinHeight = o.minHeight && (o.minHeight > newHeight);
8049
8050 o.grid = grid;
8051
8052 if (isMinWidth) {
8053 newWidth += gridX;
8054 }
8055 if (isMinHeight) {
8056 newHeight += gridY;
8057 }
8058 if (isMaxWidth) {
8059 newWidth -= gridX;
8060 }
8061 if (isMaxHeight) {
8062 newHeight -= gridY;
8063 }
8064
8065 if (/^(se|s|e)$/.test(a)) {
8066 that.size.width = newWidth;
8067 that.size.height = newHeight;
8068 } else if (/^(ne)$/.test(a)) {
8069 that.size.width = newWidth;
8070 that.size.height = newHeight;
8071 that.position.top = op.top - oy;
8072 } else if (/^(sw)$/.test(a)) {
8073 that.size.width = newWidth;
8074 that.size.height = newHeight;
8075 that.position.left = op.left - ox;
8076 } else {
8077 if ( newHeight - gridY <= 0 || newWidth - gridX <= 0) {
8078 outerDimensions = that._getPaddingPlusBorderDimensions( this );
8079 }
8080
8081 if ( newHeight - gridY > 0 ) {
8082 that.size.height = newHeight;
8083 that.position.top = op.top - oy;
8084 } else {
8085 newHeight = gridY - outerDimensions.height;
8086 that.size.height = newHeight;
8087 that.position.top = op.top + os.height - newHeight;
8088 }
8089 if ( newWidth - gridX > 0 ) {
8090 that.size.width = newWidth;
8091 that.position.left = op.left - ox;
8092 } else {
8093 newWidth = gridY - outerDimensions.height;
8094 that.size.width = newWidth;
8095 that.position.left = op.left + os.width - newWidth;
8096 }
8097 }
8098 }
8099
8100});
8101
8102var resizable = $.ui.resizable;
8103
8104
8105/*!
8106 * jQuery UI Dialog 1.11.2
8107 * http://jqueryui.com
8108 *
8109 * Copyright 2014 jQuery Foundation and other contributors
8110 * Released under the MIT license.
8111 * http://jquery.org/license
8112 *
8113 * http://api.jqueryui.com/dialog/
8114 */
8115
8116
8117var dialog = $.widget( "ui.dialog", {
8118 version: "1.11.2",
8119 options: {
8120 appendTo: "body",
8121 autoOpen: true,
8122 buttons: [],
8123 closeOnEscape: true,
8124 closeText: "Close",
8125 dialogClass: "",
8126 draggable: true,
8127 hide: null,
8128 height: "auto",
8129 maxHeight: null,
8130 maxWidth: null,
8131 minHeight: 150,
8132 minWidth: 150,
8133 modal: false,
8134 position: {
8135 my: "center",
8136 at: "center",
8137 of: window,
8138 collision: "fit",
8139 // Ensure the titlebar is always visible
8140 using: function( pos ) {
8141 var topOffset = $( this ).css( pos ).offset().top;
8142 if ( topOffset < 0 ) {
8143 $( this ).css( "top", pos.top - topOffset );
8144 }
8145 }
8146 },
8147 resizable: true,
8148 show: null,
8149 title: null,
8150 width: 300,
8151
8152 // callbacks
8153 beforeClose: null,
8154 close: null,
8155 drag: null,
8156 dragStart: null,
8157 dragStop: null,
8158 focus: null,
8159 open: null,
8160 resize: null,
8161 resizeStart: null,
8162 resizeStop: null
8163 },
8164
8165 sizeRelatedOptions: {
8166 buttons: true,
8167 height: true,
8168 maxHeight: true,
8169 maxWidth: true,
8170 minHeight: true,
8171 minWidth: true,
8172 width: true
8173 },
8174
8175 resizableRelatedOptions: {
8176 maxHeight: true,
8177 maxWidth: true,
8178 minHeight: true,
8179 minWidth: true
8180 },
8181
8182 _create: function() {
8183 this.originalCss = {
8184 display: this.element[ 0 ].style.display,
8185 width: this.element[ 0 ].style.width,
8186 minHeight: this.element[ 0 ].style.minHeight,
8187 maxHeight: this.element[ 0 ].style.maxHeight,
8188 height: this.element[ 0 ].style.height
8189 };
8190 this.originalPosition = {
8191 parent: this.element.parent(),
8192 index: this.element.parent().children().index( this.element )
8193 };
8194 this.originalTitle = this.element.attr( "title" );
8195 this.options.title = this.options.title || this.originalTitle;
8196
8197 this._createWrapper();
8198
8199 this.element
8200 .show()
8201 .removeAttr( "title" )
8202 .addClass( "ui-dialog-content ui-widget-content" )
8203 .appendTo( this.uiDialog );
8204
8205 this._createTitlebar();
8206 this._createButtonPane();
8207
8208 if ( this.options.draggable && $.fn.draggable ) {
8209 this._makeDraggable();
8210 }
8211 if ( this.options.resizable && $.fn.resizable ) {
8212 this._makeResizable();
8213 }
8214
8215 this._isOpen = false;
8216
8217 this._trackFocus();
8218 },
8219
8220 _init: function() {
8221 if ( this.options.autoOpen ) {
8222 this.open();
8223 }
8224 },
8225
8226 _appendTo: function() {
8227 var element = this.options.appendTo;
8228 if ( element && (element.jquery || element.nodeType) ) {
8229 return $( element );
8230 }
8231 return this.document.find( element || "body" ).eq( 0 );
8232 },
8233
8234 _destroy: function() {
8235 var next,
8236 originalPosition = this.originalPosition;
8237
8238 this._destroyOverlay();
8239
8240 this.element
8241 .removeUniqueId()
8242 .removeClass( "ui-dialog-content ui-widget-content" )
8243 .css( this.originalCss )
8244 // Without detaching first, the following becomes really slow
8245 .detach();
8246
8247 this.uiDialog.stop( true, true ).remove();
8248
8249 if ( this.originalTitle ) {
8250 this.element.attr( "title", this.originalTitle );
8251 }
8252
8253 next = originalPosition.parent.children().eq( originalPosition.index );
8254 // Don't try to place the dialog next to itself (#8613)
8255 if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
8256 next.before( this.element );
8257 } else {
8258 originalPosition.parent.append( this.element );
8259 }
8260 },
8261
8262 widget: function() {
8263 return this.uiDialog;
8264 },
8265
8266 disable: $.noop,
8267 enable: $.noop,
8268
8269 close: function( event ) {
8270 var activeElement,
8271 that = this;
8272
8273 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
8274 return;
8275 }
8276
8277 this._isOpen = false;
8278 this._focusedElement = null;
8279 this._destroyOverlay();
8280 this._untrackInstance();
8281
8282 if ( !this.opener.filter( ":focusable" ).focus().length ) {
8283
8284 // support: IE9
8285 // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
8286 try {
8287 activeElement = this.document[ 0 ].activeElement;
8288
8289 // Support: IE9, IE10
8290 // If the <body> is blurred, IE will switch windows, see #4520
8291 if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) {
8292
8293 // Hiding a focused element doesn't trigger blur in WebKit
8294 // so in case we have nothing to focus on, explicitly blur the active element
8295 // https://bugs.webkit.org/show_bug.cgi?id=47182
8296 $( activeElement ).blur();
8297 }
8298 } catch ( error ) {}
8299 }
8300
8301 this._hide( this.uiDialog, this.options.hide, function() {
8302 that._trigger( "close", event );
8303 });
8304 },
8305
8306 isOpen: function() {
8307 return this._isOpen;
8308 },
8309
8310 moveToTop: function() {
8311 this._moveToTop();
8312 },
8313
8314 _moveToTop: function( event, silent ) {
8315 var moved = false,
8316 zIndicies = this.uiDialog.siblings( ".ui-front:visible" ).map(function() {
8317 return +$( this ).css( "z-index" );
8318 }).get(),
8319 zIndexMax = Math.max.apply( null, zIndicies );
8320
8321 if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
8322 this.uiDialog.css( "z-index", zIndexMax + 1 );
8323 moved = true;
8324 }
8325
8326 if ( moved && !silent ) {
8327 this._trigger( "focus", event );
8328 }
8329 return moved;
8330 },
8331
8332 open: function() {
8333 var that = this;
8334 if ( this._isOpen ) {
8335 if ( this._moveToTop() ) {
8336 this._focusTabbable();
8337 }
8338 return;
8339 }
8340
8341 this._isOpen = true;
8342 this.opener = $( this.document[ 0 ].activeElement );
8343
8344 this._size();
8345 this._position();
8346 this._createOverlay();
8347 this._moveToTop( null, true );
8348
8349 // Ensure the overlay is moved to the top with the dialog, but only when
8350 // opening. The overlay shouldn't move after the dialog is open so that
8351 // modeless dialogs opened after the modal dialog stack properly.
8352 if ( this.overlay ) {
8353 this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
8354 }
8355
8356 this._show( this.uiDialog, this.options.show, function() {
8357 that._focusTabbable();
8358 that._trigger( "focus" );
8359 });
8360
8361 // Track the dialog immediately upon openening in case a focus event
8362 // somehow occurs outside of the dialog before an element inside the
8363 // dialog is focused (#10152)
8364 this._makeFocusTarget();
8365
8366 this._trigger( "open" );
8367 },
8368
8369 _focusTabbable: function() {
8370 // Set focus to the first match:
8371 // 1. An element that was focused previously
8372 // 2. First element inside the dialog matching [autofocus]
8373 // 3. Tabbable element inside the content element
8374 // 4. Tabbable element inside the buttonpane
8375 // 5. The close button
8376 // 6. The dialog itself
8377 var hasFocus = this._focusedElement;
8378 if ( !hasFocus ) {
8379 hasFocus = this.element.find( "[autofocus]" );
8380 }
8381 if ( !hasFocus.length ) {
8382 hasFocus = this.element.find( ":tabbable" );
8383 }
8384 if ( !hasFocus.length ) {
8385 hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
8386 }
8387 if ( !hasFocus.length ) {
8388 hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
8389 }
8390 if ( !hasFocus.length ) {
8391 hasFocus = this.uiDialog;
8392 }
8393 hasFocus.eq( 0 ).focus();
8394 },
8395
8396 _keepFocus: function( event ) {
8397 function checkFocus() {
8398 var activeElement = this.document[0].activeElement,
8399 isActive = this.uiDialog[0] === activeElement ||
8400 $.contains( this.uiDialog[0], activeElement );
8401 if ( !isActive ) {
8402 this._focusTabbable();
8403 }
8404 }
8405 event.preventDefault();
8406 checkFocus.call( this );
8407 // support: IE
8408 // IE <= 8 doesn't prevent moving focus even with event.preventDefault()
8409 // so we check again later
8410 this._delay( checkFocus );
8411 },
8412
8413 _createWrapper: function() {
8414 this.uiDialog = $("<div>")
8415 .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
8416 this.options.dialogClass )
8417 .hide()
8418 .attr({
8419 // Setting tabIndex makes the div focusable
8420 tabIndex: -1,
8421 role: "dialog"
8422 })
8423 .appendTo( this._appendTo() );
8424
8425 this._on( this.uiDialog, {
8426 keydown: function( event ) {
8427 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
8428 event.keyCode === $.ui.keyCode.ESCAPE ) {
8429 event.preventDefault();
8430 this.close( event );
8431 return;
8432 }
8433
8434 // prevent tabbing out of dialogs
8435 if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
8436 return;
8437 }
8438 var tabbables = this.uiDialog.find( ":tabbable" ),
8439 first = tabbables.filter( ":first" ),
8440 last = tabbables.filter( ":last" );
8441
8442 if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
8443 this._delay(function() {
8444 first.focus();
8445 });
8446 event.preventDefault();
8447 } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
8448 this._delay(function() {
8449 last.focus();
8450 });
8451 event.preventDefault();
8452 }
8453 },
8454 mousedown: function( event ) {
8455 if ( this._moveToTop( event ) ) {
8456 this._focusTabbable();
8457 }
8458 }
8459 });
8460
8461 // We assume that any existing aria-describedby attribute means
8462 // that the dialog content is marked up properly
8463 // otherwise we brute force the content as the description
8464 if ( !this.element.find( "[aria-describedby]" ).length ) {
8465 this.uiDialog.attr({
8466 "aria-describedby": this.element.uniqueId().attr( "id" )
8467 });
8468 }
8469 },
8470
8471 _createTitlebar: function() {
8472 var uiDialogTitle;
8473
8474 this.uiDialogTitlebar = $( "<div>" )
8475 .addClass( "ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix" )
8476 .prependTo( this.uiDialog );
8477 this._on( this.uiDialogTitlebar, {
8478 mousedown: function( event ) {
8479 // Don't prevent click on close button (#8838)
8480 // Focusing a dialog that is partially scrolled out of view
8481 // causes the browser to scroll it into view, preventing the click event
8482 if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
8483 // Dialog isn't getting focus when dragging (#8063)
8484 this.uiDialog.focus();
8485 }
8486 }
8487 });
8488
8489 // support: IE
8490 // Use type="button" to prevent enter keypresses in textboxes from closing the
8491 // dialog in IE (#9312)
8492 this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
8493 .button({
8494 label: this.options.closeText,
8495 icons: {
8496 primary: "ui-icon-closethick"
8497 },
8498 text: false
8499 })
8500 .addClass( "ui-dialog-titlebar-close" )
8501 .appendTo( this.uiDialogTitlebar );
8502 this._on( this.uiDialogTitlebarClose, {
8503 click: function( event ) {
8504 event.preventDefault();
8505 this.close( event );
8506 }
8507 });
8508
8509 uiDialogTitle = $( "<span>" )
8510 .uniqueId()
8511 .addClass( "ui-dialog-title" )
8512 .prependTo( this.uiDialogTitlebar );
8513 this._title( uiDialogTitle );
8514
8515 this.uiDialog.attr({
8516 "aria-labelledby": uiDialogTitle.attr( "id" )
8517 });
8518 },
8519
8520 _title: function( title ) {
8521 if ( !this.options.title ) {
8522 title.html( "&#160;" );
8523 }
8524 title.text( this.options.title );
8525 },
8526
8527 _createButtonPane: function() {
8528 this.uiDialogButtonPane = $( "<div>" )
8529 .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" );
8530
8531 this.uiButtonSet = $( "<div>" )
8532 .addClass( "ui-dialog-buttonset" )
8533 .appendTo( this.uiDialogButtonPane );
8534
8535 this._createButtons();
8536 },
8537
8538 _createButtons: function() {
8539 var that = this,
8540 buttons = this.options.buttons;
8541
8542 // if we already have a button pane, remove it
8543 this.uiDialogButtonPane.remove();
8544 this.uiButtonSet.empty();
8545
8546 if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {
8547 this.uiDialog.removeClass( "ui-dialog-buttons" );
8548 return;
8549 }
8550
8551 $.each( buttons, function( name, props ) {
8552 var click, buttonOptions;
8553 props = $.isFunction( props ) ?
8554 { click: props, text: name } :
8555 props;
8556 // Default to a non-submitting button
8557 props = $.extend( { type: "button" }, props );
8558 // Change the context for the click callback to be the main element
8559 click = props.click;
8560 props.click = function() {
8561 click.apply( that.element[ 0 ], arguments );
8562 };
8563 buttonOptions = {
8564 icons: props.icons,
8565 text: props.showText
8566 };
8567 delete props.icons;
8568 delete props.showText;
8569 $( "<button></button>", props )
8570 .button( buttonOptions )
8571 .appendTo( that.uiButtonSet );
8572 });
8573 this.uiDialog.addClass( "ui-dialog-buttons" );
8574 this.uiDialogButtonPane.appendTo( this.uiDialog );
8575 },
8576
8577 _makeDraggable: function() {
8578 var that = this,
8579 options = this.options;
8580
8581 function filteredUi( ui ) {
8582 return {
8583 position: ui.position,
8584 offset: ui.offset
8585 };
8586 }
8587
8588 this.uiDialog.draggable({
8589 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
8590 handle: ".ui-dialog-titlebar",
8591 containment: "document",
8592 start: function( event, ui ) {
8593 $( this ).addClass( "ui-dialog-dragging" );
8594 that._blockFrames();
8595 that._trigger( "dragStart", event, filteredUi( ui ) );
8596 },
8597 drag: function( event, ui ) {
8598 that._trigger( "drag", event, filteredUi( ui ) );
8599 },
8600 stop: function( event, ui ) {
8601 var left = ui.offset.left - that.document.scrollLeft(),
8602 top = ui.offset.top - that.document.scrollTop();
8603
8604 options.position = {
8605 my: "left top",
8606 at: "left" + (left >= 0 ? "+" : "") + left + " " +
8607 "top" + (top >= 0 ? "+" : "") + top,
8608 of: that.window
8609 };
8610 $( this ).removeClass( "ui-dialog-dragging" );
8611 that._unblockFrames();
8612 that._trigger( "dragStop", event, filteredUi( ui ) );
8613 }
8614 });
8615 },
8616
8617 _makeResizable: function() {
8618 var that = this,
8619 options = this.options,
8620 handles = options.resizable,
8621 // .ui-resizable has position: relative defined in the stylesheet
8622 // but dialogs have to use absolute or fixed positioning
8623 position = this.uiDialog.css("position"),
8624 resizeHandles = typeof handles === "string" ?
8625 handles :
8626 "n,e,s,w,se,sw,ne,nw";
8627
8628 function filteredUi( ui ) {
8629 return {
8630 originalPosition: ui.originalPosition,
8631 originalSize: ui.originalSize,
8632 position: ui.position,
8633 size: ui.size
8634 };
8635 }
8636
8637 this.uiDialog.resizable({
8638 cancel: ".ui-dialog-content",
8639 containment: "document",
8640 alsoResize: this.element,
8641 maxWidth: options.maxWidth,
8642 maxHeight: options.maxHeight,
8643 minWidth: options.minWidth,
8644 minHeight: this._minHeight(),
8645 handles: resizeHandles,
8646 start: function( event, ui ) {
8647 $( this ).addClass( "ui-dialog-resizing" );
8648 that._blockFrames();
8649 that._trigger( "resizeStart", event, filteredUi( ui ) );
8650 },
8651 resize: function( event, ui ) {
8652 that._trigger( "resize", event, filteredUi( ui ) );
8653 },
8654 stop: function( event, ui ) {
8655 var offset = that.uiDialog.offset(),
8656 left = offset.left - that.document.scrollLeft(),
8657 top = offset.top - that.document.scrollTop();
8658
8659 options.height = that.uiDialog.height();
8660 options.width = that.uiDialog.width();
8661 options.position = {
8662 my: "left top",
8663 at: "left" + (left >= 0 ? "+" : "") + left + " " +
8664 "top" + (top >= 0 ? "+" : "") + top,
8665 of: that.window
8666 };
8667 $( this ).removeClass( "ui-dialog-resizing" );
8668 that._unblockFrames();
8669 that._trigger( "resizeStop", event, filteredUi( ui ) );
8670 }
8671 })
8672 .css( "position", position );
8673 },
8674
8675 _trackFocus: function() {
8676 this._on( this.widget(), {
8677 focusin: function( event ) {
8678 this._makeFocusTarget();
8679 this._focusedElement = $( event.target );
8680 }
8681 });
8682 },
8683
8684 _makeFocusTarget: function() {
8685 this._untrackInstance();
8686 this._trackingInstances().unshift( this );
8687 },
8688
8689 _untrackInstance: function() {
8690 var instances = this._trackingInstances(),
8691 exists = $.inArray( this, instances );
8692 if ( exists !== -1 ) {
8693 instances.splice( exists, 1 );
8694 }
8695 },
8696
8697 _trackingInstances: function() {
8698 var instances = this.document.data( "ui-dialog-instances" );
8699 if ( !instances ) {
8700 instances = [];
8701 this.document.data( "ui-dialog-instances", instances );
8702 }
8703 return instances;
8704 },
8705
8706 _minHeight: function() {
8707 var options = this.options;
8708
8709 return options.height === "auto" ?
8710 options.minHeight :
8711 Math.min( options.minHeight, options.height );
8712 },
8713
8714 _position: function() {
8715 // Need to show the dialog to get the actual offset in the position plugin
8716 var isVisible = this.uiDialog.is( ":visible" );
8717 if ( !isVisible ) {
8718 this.uiDialog.show();
8719 }
8720 this.uiDialog.position( this.options.position );
8721 if ( !isVisible ) {
8722 this.uiDialog.hide();
8723 }
8724 },
8725
8726 _setOptions: function( options ) {
8727 var that = this,
8728 resize = false,
8729 resizableOptions = {};
8730
8731 $.each( options, function( key, value ) {
8732 that._setOption( key, value );
8733
8734 if ( key in that.sizeRelatedOptions ) {
8735 resize = true;
8736 }
8737 if ( key in that.resizableRelatedOptions ) {
8738 resizableOptions[ key ] = value;
8739 }
8740 });
8741
8742 if ( resize ) {
8743 this._size();
8744 this._position();
8745 }
8746 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
8747 this.uiDialog.resizable( "option", resizableOptions );
8748 }
8749 },
8750
8751 _setOption: function( key, value ) {
8752 var isDraggable, isResizable,
8753 uiDialog = this.uiDialog;
8754
8755 if ( key === "dialogClass" ) {
8756 uiDialog
8757 .removeClass( this.options.dialogClass )
8758 .addClass( value );
8759 }
8760
8761 if ( key === "disabled" ) {
8762 return;
8763 }
8764
8765 this._super( key, value );
8766
8767 if ( key === "appendTo" ) {
8768 this.uiDialog.appendTo( this._appendTo() );
8769 }
8770
8771 if ( key === "buttons" ) {
8772 this._createButtons();
8773 }
8774
8775 if ( key === "closeText" ) {
8776 this.uiDialogTitlebarClose.button({
8777 // Ensure that we always pass a string
8778 label: "" + value
8779 });
8780 }
8781
8782 if ( key === "draggable" ) {
8783 isDraggable = uiDialog.is( ":data(ui-draggable)" );
8784 if ( isDraggable && !value ) {
8785 uiDialog.draggable( "destroy" );
8786 }
8787
8788 if ( !isDraggable && value ) {
8789 this._makeDraggable();
8790 }
8791 }
8792
8793 if ( key === "position" ) {
8794 this._position();
8795 }
8796
8797 if ( key === "resizable" ) {
8798 // currently resizable, becoming non-resizable
8799 isResizable = uiDialog.is( ":data(ui-resizable)" );
8800 if ( isResizable && !value ) {
8801 uiDialog.resizable( "destroy" );
8802 }
8803
8804 // currently resizable, changing handles
8805 if ( isResizable && typeof value === "string" ) {
8806 uiDialog.resizable( "option", "handles", value );
8807 }
8808
8809 // currently non-resizable, becoming resizable
8810 if ( !isResizable && value !== false ) {
8811 this._makeResizable();
8812 }
8813 }
8814
8815 if ( key === "title" ) {
8816 this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
8817 }
8818 },
8819
8820 _size: function() {
8821 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
8822 // divs will both have width and height set, so we need to reset them
8823 var nonContentHeight, minContentHeight, maxContentHeight,
8824 options = this.options;
8825
8826 // Reset content sizing
8827 this.element.show().css({
8828 width: "auto",
8829 minHeight: 0,
8830 maxHeight: "none",
8831 height: 0
8832 });
8833
8834 if ( options.minWidth > options.width ) {
8835 options.width = options.minWidth;
8836 }
8837
8838 // reset wrapper sizing
8839 // determine the height of all the non-content elements
8840 nonContentHeight = this.uiDialog.css({
8841 height: "auto",
8842 width: options.width
8843 })
8844 .outerHeight();
8845 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
8846 maxContentHeight = typeof options.maxHeight === "number" ?
8847 Math.max( 0, options.maxHeight - nonContentHeight ) :
8848 "none";
8849
8850 if ( options.height === "auto" ) {
8851 this.element.css({
8852 minHeight: minContentHeight,
8853 maxHeight: maxContentHeight,
8854 height: "auto"
8855 });
8856 } else {
8857 this.element.height( Math.max( 0, options.height - nonContentHeight ) );
8858 }
8859
8860 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
8861 this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
8862 }
8863 },
8864
8865 _blockFrames: function() {
8866 this.iframeBlocks = this.document.find( "iframe" ).map(function() {
8867 var iframe = $( this );
8868
8869 return $( "<div>" )
8870 .css({
8871 position: "absolute",
8872 width: iframe.outerWidth(),
8873 height: iframe.outerHeight()
8874 })
8875 .appendTo( iframe.parent() )
8876 .offset( iframe.offset() )[0];
8877 });
8878 },
8879
8880 _unblockFrames: function() {
8881 if ( this.iframeBlocks ) {
8882 this.iframeBlocks.remove();
8883 delete this.iframeBlocks;
8884 }
8885 },
8886
8887 _allowInteraction: function( event ) {
8888 if ( $( event.target ).closest( ".ui-dialog" ).length ) {
8889 return true;
8890 }
8891
8892 // TODO: Remove hack when datepicker implements
8893 // the .ui-front logic (#8989)
8894 return !!$( event.target ).closest( ".ui-datepicker" ).length;
8895 },
8896
8897 _createOverlay: function() {
8898 if ( !this.options.modal ) {
8899 return;
8900 }
8901
8902 // We use a delay in case the overlay is created from an
8903 // event that we're going to be cancelling (#2804)
8904 var isOpening = true;
8905 this._delay(function() {
8906 isOpening = false;
8907 });
8908
8909 if ( !this.document.data( "ui-dialog-overlays" ) ) {
8910
8911 // Prevent use of anchors and inputs
8912 // Using _on() for an event handler shared across many instances is
8913 // safe because the dialogs stack and must be closed in reverse order
8914 this._on( this.document, {
8915 focusin: function( event ) {
8916 if ( isOpening ) {
8917 return;
8918 }
8919
8920 if ( !this._allowInteraction( event ) ) {
8921 event.preventDefault();
8922 this._trackingInstances()[ 0 ]._focusTabbable();
8923 }
8924 }
8925 });
8926 }
8927
8928 this.overlay = $( "<div>" )
8929 .addClass( "ui-widget-overlay ui-front" )
8930 .appendTo( this._appendTo() );
8931 this._on( this.overlay, {
8932 mousedown: "_keepFocus"
8933 });
8934 this.document.data( "ui-dialog-overlays",
8935 (this.document.data( "ui-dialog-overlays" ) || 0) + 1 );
8936 },
8937
8938 _destroyOverlay: function() {
8939 if ( !this.options.modal ) {
8940 return;
8941 }
8942
8943 if ( this.overlay ) {
8944 var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
8945
8946 if ( !overlays ) {
8947 this.document
8948 .unbind( "focusin" )
8949 .removeData( "ui-dialog-overlays" );
8950 } else {
8951 this.document.data( "ui-dialog-overlays", overlays );
8952 }
8953
8954 this.overlay.remove();
8955 this.overlay = null;
8956 }
8957 }
8958});
8959
8960
8961/*!
8962 * jQuery UI Droppable 1.11.2
8963 * http://jqueryui.com
8964 *
8965 * Copyright 2014 jQuery Foundation and other contributors
8966 * Released under the MIT license.
8967 * http://jquery.org/license
8968 *
8969 * http://api.jqueryui.com/droppable/
8970 */
8971
8972
8973$.widget( "ui.droppable", {
8974 version: "1.11.2",
8975 widgetEventPrefix: "drop",
8976 options: {
8977 accept: "*",
8978 activeClass: false,
8979 addClasses: true,
8980 greedy: false,
8981 hoverClass: false,
8982 scope: "default",
8983 tolerance: "intersect",
8984
8985 // callbacks
8986 activate: null,
8987 deactivate: null,
8988 drop: null,
8989 out: null,
8990 over: null
8991 },
8992 _create: function() {
8993
8994 var proportions,
8995 o = this.options,
8996 accept = o.accept;
8997
8998 this.isover = false;
8999 this.isout = true;
9000
9001 this.accept = $.isFunction( accept ) ? accept : function( d ) {
9002 return d.is( accept );
9003 };
9004
9005 this.proportions = function( /* valueToWrite */ ) {
9006 if ( arguments.length ) {
9007 // Store the droppable's proportions
9008 proportions = arguments[ 0 ];
9009 } else {
9010 // Retrieve or derive the droppable's proportions
9011 return proportions ?
9012 proportions :
9013 proportions = {
9014 width: this.element[ 0 ].offsetWidth,
9015 height: this.element[ 0 ].offsetHeight
9016 };
9017 }
9018 };
9019
9020 this._addToManager( o.scope );
9021
9022 o.addClasses && this.element.addClass( "ui-droppable" );
9023
9024 },
9025
9026 _addToManager: function( scope ) {
9027 // Add the reference and positions to the manager
9028 $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
9029 $.ui.ddmanager.droppables[ scope ].push( this );
9030 },
9031
9032 _splice: function( drop ) {
9033 var i = 0;
9034 for ( ; i < drop.length; i++ ) {
9035 if ( drop[ i ] === this ) {
9036 drop.splice( i, 1 );
9037 }
9038 }
9039 },
9040
9041 _destroy: function() {
9042 var drop = $.ui.ddmanager.droppables[ this.options.scope ];
9043
9044 this._splice( drop );
9045
9046 this.element.removeClass( "ui-droppable ui-droppable-disabled" );
9047 },
9048
9049 _setOption: function( key, value ) {
9050
9051 if ( key === "accept" ) {
9052 this.accept = $.isFunction( value ) ? value : function( d ) {
9053 return d.is( value );
9054 };
9055 } else if ( key === "scope" ) {
9056 var drop = $.ui.ddmanager.droppables[ this.options.scope ];
9057
9058 this._splice( drop );
9059 this._addToManager( value );
9060 }
9061
9062 this._super( key, value );
9063 },
9064
9065 _activate: function( event ) {
9066 var draggable = $.ui.ddmanager.current;
9067 if ( this.options.activeClass ) {
9068 this.element.addClass( this.options.activeClass );
9069 }
9070 if ( draggable ){
9071 this._trigger( "activate", event, this.ui( draggable ) );
9072 }
9073 },
9074
9075 _deactivate: function( event ) {
9076 var draggable = $.ui.ddmanager.current;
9077 if ( this.options.activeClass ) {
9078 this.element.removeClass( this.options.activeClass );
9079 }
9080 if ( draggable ){
9081 this._trigger( "deactivate", event, this.ui( draggable ) );
9082 }
9083 },
9084
9085 _over: function( event ) {
9086
9087 var draggable = $.ui.ddmanager.current;
9088
9089 // Bail if draggable and droppable are same element
9090 if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
9091 return;
9092 }
9093
9094 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9095 if ( this.options.hoverClass ) {
9096 this.element.addClass( this.options.hoverClass );
9097 }
9098 this._trigger( "over", event, this.ui( draggable ) );
9099 }
9100
9101 },
9102
9103 _out: function( event ) {
9104
9105 var draggable = $.ui.ddmanager.current;
9106
9107 // Bail if draggable and droppable are same element
9108 if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
9109 return;
9110 }
9111
9112 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9113 if ( this.options.hoverClass ) {
9114 this.element.removeClass( this.options.hoverClass );
9115 }
9116 this._trigger( "out", event, this.ui( draggable ) );
9117 }
9118
9119 },
9120
9121 _drop: function( event, custom ) {
9122
9123 var draggable = custom || $.ui.ddmanager.current,
9124 childrenIntersection = false;
9125
9126 // Bail if draggable and droppable are same element
9127 if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
9128 return false;
9129 }
9130
9131 this.element.find( ":data(ui-droppable)" ).not( ".ui-draggable-dragging" ).each(function() {
9132 var inst = $( this ).droppable( "instance" );
9133 if (
9134 inst.options.greedy &&
9135 !inst.options.disabled &&
9136 inst.options.scope === draggable.options.scope &&
9137 inst.accept.call( inst.element[ 0 ], ( draggable.currentItem || draggable.element ) ) &&
9138 $.ui.intersect( draggable, $.extend( inst, { offset: inst.element.offset() } ), inst.options.tolerance, event )
9139 ) { childrenIntersection = true; return false; }
9140 });
9141 if ( childrenIntersection ) {
9142 return false;
9143 }
9144
9145 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9146 if ( this.options.activeClass ) {
9147 this.element.removeClass( this.options.activeClass );
9148 }
9149 if ( this.options.hoverClass ) {
9150 this.element.removeClass( this.options.hoverClass );
9151 }
9152 this._trigger( "drop", event, this.ui( draggable ) );
9153 return this.element;
9154 }
9155
9156 return false;
9157
9158 },
9159
9160 ui: function( c ) {
9161 return {
9162 draggable: ( c.currentItem || c.element ),
9163 helper: c.helper,
9164 position: c.position,
9165 offset: c.positionAbs
9166 };
9167 }
9168
9169});
9170
9171$.ui.intersect = (function() {
9172 function isOverAxis( x, reference, size ) {
9173 return ( x >= reference ) && ( x < ( reference + size ) );
9174 }
9175
9176 return function( draggable, droppable, toleranceMode, event ) {
9177
9178 if ( !droppable.offset ) {
9179 return false;
9180 }
9181
9182 var x1 = ( draggable.positionAbs || draggable.position.absolute ).left + draggable.margins.left,
9183 y1 = ( draggable.positionAbs || draggable.position.absolute ).top + draggable.margins.top,
9184 x2 = x1 + draggable.helperProportions.width,
9185 y2 = y1 + draggable.helperProportions.height,
9186 l = droppable.offset.left,
9187 t = droppable.offset.top,
9188 r = l + droppable.proportions().width,
9189 b = t + droppable.proportions().height;
9190
9191 switch ( toleranceMode ) {
9192 case "fit":
9193 return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
9194 case "intersect":
9195 return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
9196 x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
9197 t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
9198 y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
9199 case "pointer":
9200 return isOverAxis( event.pageY, t, droppable.proportions().height ) && isOverAxis( event.pageX, l, droppable.proportions().width );
9201 case "touch":
9202 return (
9203 ( y1 >= t && y1 <= b ) || // Top edge touching
9204 ( y2 >= t && y2 <= b ) || // Bottom edge touching
9205 ( y1 < t && y2 > b ) // Surrounded vertically
9206 ) && (
9207 ( x1 >= l && x1 <= r ) || // Left edge touching
9208 ( x2 >= l && x2 <= r ) || // Right edge touching
9209 ( x1 < l && x2 > r ) // Surrounded horizontally
9210 );
9211 default:
9212 return false;
9213 }
9214 };
9215})();
9216
9217/*
9218 This manager tracks offsets of draggables and droppables
9219*/
9220$.ui.ddmanager = {
9221 current: null,
9222 droppables: { "default": [] },
9223 prepareOffsets: function( t, event ) {
9224
9225 var i, j,
9226 m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
9227 type = event ? event.type : null, // workaround for #2317
9228 list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
9229
9230 droppablesLoop: for ( i = 0; i < m.length; i++ ) {
9231
9232 // No disabled and non-accepted
9233 if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], ( t.currentItem || t.element ) ) ) ) {
9234 continue;
9235 }
9236
9237 // Filter out elements in the current dragged item
9238 for ( j = 0; j < list.length; j++ ) {
9239 if ( list[ j ] === m[ i ].element[ 0 ] ) {
9240 m[ i ].proportions().height = 0;
9241 continue droppablesLoop;
9242 }
9243 }
9244
9245 m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
9246 if ( !m[ i ].visible ) {
9247 continue;
9248 }
9249
9250 // Activate the droppable if used directly from draggables
9251 if ( type === "mousedown" ) {
9252 m[ i ]._activate.call( m[ i ], event );
9253 }
9254
9255 m[ i ].offset = m[ i ].element.offset();
9256 m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight });
9257
9258 }
9259
9260 },
9261 drop: function( draggable, event ) {
9262
9263 var dropped = false;
9264 // Create a copy of the droppables in case the list changes during the drop (#9116)
9265 $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
9266
9267 if ( !this.options ) {
9268 return;
9269 }
9270 if ( !this.options.disabled && this.visible && $.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
9271 dropped = this._drop.call( this, event ) || dropped;
9272 }
9273
9274 if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9275 this.isout = true;
9276 this.isover = false;
9277 this._deactivate.call( this, event );
9278 }
9279
9280 });
9281 return dropped;
9282
9283 },
9284 dragStart: function( draggable, event ) {
9285 // Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
9286 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
9287 if ( !draggable.options.refreshPositions ) {
9288 $.ui.ddmanager.prepareOffsets( draggable, event );
9289 }
9290 });
9291 },
9292 drag: function( draggable, event ) {
9293
9294 // If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
9295 if ( draggable.options.refreshPositions ) {
9296 $.ui.ddmanager.prepareOffsets( draggable, event );
9297 }
9298
9299 // Run through all droppables and check their positions based on specific tolerance options
9300 $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
9301
9302 if ( this.options.disabled || this.greedyChild || !this.visible ) {
9303 return;
9304 }
9305
9306 var parentInstance, scope, parent,
9307 intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
9308 c = !intersects && this.isover ? "isout" : ( intersects && !this.isover ? "isover" : null );
9309 if ( !c ) {
9310 return;
9311 }
9312
9313 if ( this.options.greedy ) {
9314 // find droppable parents with same scope
9315 scope = this.options.scope;
9316 parent = this.element.parents( ":data(ui-droppable)" ).filter(function() {
9317 return $( this ).droppable( "instance" ).options.scope === scope;
9318 });
9319
9320 if ( parent.length ) {
9321 parentInstance = $( parent[ 0 ] ).droppable( "instance" );
9322 parentInstance.greedyChild = ( c === "isover" );
9323 }
9324 }
9325
9326 // we just moved into a greedy child
9327 if ( parentInstance && c === "isover" ) {
9328 parentInstance.isover = false;
9329 parentInstance.isout = true;
9330 parentInstance._out.call( parentInstance, event );
9331 }
9332
9333 this[ c ] = true;
9334 this[c === "isout" ? "isover" : "isout"] = false;
9335 this[c === "isover" ? "_over" : "_out"].call( this, event );
9336
9337 // we just moved out of a greedy child
9338 if ( parentInstance && c === "isout" ) {
9339 parentInstance.isout = false;
9340 parentInstance.isover = true;
9341 parentInstance._over.call( parentInstance, event );
9342 }
9343 });
9344
9345 },
9346 dragStop: function( draggable, event ) {
9347 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
9348 // Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
9349 if ( !draggable.options.refreshPositions ) {
9350 $.ui.ddmanager.prepareOffsets( draggable, event );
9351 }
9352 }
9353};
9354
9355var droppable = $.ui.droppable;
9356
9357
9358/*!
9359 * jQuery UI Effects 1.11.2
9360 * http://jqueryui.com
9361 *
9362 * Copyright 2014 jQuery Foundation and other contributors
9363 * Released under the MIT license.
9364 * http://jquery.org/license
9365 *
9366 * http://api.jqueryui.com/category/effects-core/
9367 */
9368
9369
9370var dataSpace = "ui-effects-",
9371
9372 // Create a local jQuery because jQuery Color relies on it and the
9373 // global may not exist with AMD and a custom build (#10199)
9374 jQuery = $;
9375
9376$.effects = {
9377 effect: {}
9378};
9379
9380/*!
9381 * jQuery Color Animations v2.1.2
9382 * https://github.com/jquery/jquery-color
9383 *
9384 * Copyright 2014 jQuery Foundation and other contributors
9385 * Released under the MIT license.
9386 * http://jquery.org/license
9387 *
9388 * Date: Wed Jan 16 08:47:09 2013 -0600
9389 */
9390(function( jQuery, undefined ) {
9391
9392 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
9393
9394 // plusequals test for += 100 -= 100
9395 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
9396 // a set of RE's that can match strings and generate color tuples.
9397 stringParsers = [ {
9398 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9399 parse: function( execResult ) {
9400 return [
9401 execResult[ 1 ],
9402 execResult[ 2 ],
9403 execResult[ 3 ],
9404 execResult[ 4 ]
9405 ];
9406 }
9407 }, {
9408 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9409 parse: function( execResult ) {
9410 return [
9411 execResult[ 1 ] * 2.55,
9412 execResult[ 2 ] * 2.55,
9413 execResult[ 3 ] * 2.55,
9414 execResult[ 4 ]
9415 ];
9416 }
9417 }, {
9418 // this regex ignores A-F because it's compared against an already lowercased string
9419 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
9420 parse: function( execResult ) {
9421 return [
9422 parseInt( execResult[ 1 ], 16 ),
9423 parseInt( execResult[ 2 ], 16 ),
9424 parseInt( execResult[ 3 ], 16 )
9425 ];
9426 }
9427 }, {
9428 // this regex ignores A-F because it's compared against an already lowercased string
9429 re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
9430 parse: function( execResult ) {
9431 return [
9432 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
9433 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
9434 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
9435 ];
9436 }
9437 }, {
9438 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9439 space: "hsla",
9440 parse: function( execResult ) {
9441 return [
9442 execResult[ 1 ],
9443 execResult[ 2 ] / 100,
9444 execResult[ 3 ] / 100,
9445 execResult[ 4 ]
9446 ];
9447 }
9448 } ],
9449
9450 // jQuery.Color( )
9451 color = jQuery.Color = function( color, green, blue, alpha ) {
9452 return new jQuery.Color.fn.parse( color, green, blue, alpha );
9453 },
9454 spaces = {
9455 rgba: {
9456 props: {
9457 red: {
9458 idx: 0,
9459 type: "byte"
9460 },
9461 green: {
9462 idx: 1,
9463 type: "byte"
9464 },
9465 blue: {
9466 idx: 2,
9467 type: "byte"
9468 }
9469 }
9470 },
9471
9472 hsla: {
9473 props: {
9474 hue: {
9475 idx: 0,
9476 type: "degrees"
9477 },
9478 saturation: {
9479 idx: 1,
9480 type: "percent"
9481 },
9482 lightness: {
9483 idx: 2,
9484 type: "percent"
9485 }
9486 }
9487 }
9488 },
9489 propTypes = {
9490 "byte": {
9491 floor: true,
9492 max: 255
9493 },
9494 "percent": {
9495 max: 1
9496 },
9497 "degrees": {
9498 mod: 360,
9499 floor: true
9500 }
9501 },
9502 support = color.support = {},
9503
9504 // element for support tests
9505 supportElem = jQuery( "<p>" )[ 0 ],
9506
9507 // colors = jQuery.Color.names
9508 colors,
9509
9510 // local aliases of functions called often
9511 each = jQuery.each;
9512
9513// determine rgba support immediately
9514supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
9515support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
9516
9517// define cache name and alpha properties
9518// for rgba and hsla spaces
9519each( spaces, function( spaceName, space ) {
9520 space.cache = "_" + spaceName;
9521 space.props.alpha = {
9522 idx: 3,
9523 type: "percent",
9524 def: 1
9525 };
9526});
9527
9528function clamp( value, prop, allowEmpty ) {
9529 var type = propTypes[ prop.type ] || {};
9530
9531 if ( value == null ) {
9532 return (allowEmpty || !prop.def) ? null : prop.def;
9533 }
9534
9535 // ~~ is an short way of doing floor for positive numbers
9536 value = type.floor ? ~~value : parseFloat( value );
9537
9538 // IE will pass in empty strings as value for alpha,
9539 // which will hit this case
9540 if ( isNaN( value ) ) {
9541 return prop.def;
9542 }
9543
9544 if ( type.mod ) {
9545 // we add mod before modding to make sure that negatives values
9546 // get converted properly: -10 -> 350
9547 return (value + type.mod) % type.mod;
9548 }
9549
9550 // for now all property types without mod have min and max
9551 return 0 > value ? 0 : type.max < value ? type.max : value;
9552}
9553
9554function stringParse( string ) {
9555 var inst = color(),
9556 rgba = inst._rgba = [];
9557
9558 string = string.toLowerCase();
9559
9560 each( stringParsers, function( i, parser ) {
9561 var parsed,
9562 match = parser.re.exec( string ),
9563 values = match && parser.parse( match ),
9564 spaceName = parser.space || "rgba";
9565
9566 if ( values ) {
9567 parsed = inst[ spaceName ]( values );
9568
9569 // if this was an rgba parse the assignment might happen twice
9570 // oh well....
9571 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
9572 rgba = inst._rgba = parsed._rgba;
9573
9574 // exit each( stringParsers ) here because we matched
9575 return false;
9576 }
9577 });
9578
9579 // Found a stringParser that handled it
9580 if ( rgba.length ) {
9581
9582 // if this came from a parsed string, force "transparent" when alpha is 0
9583 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
9584 if ( rgba.join() === "0,0,0,0" ) {
9585 jQuery.extend( rgba, colors.transparent );
9586 }
9587 return inst;
9588 }
9589
9590 // named colors
9591 return colors[ string ];
9592}
9593
9594color.fn = jQuery.extend( color.prototype, {
9595 parse: function( red, green, blue, alpha ) {
9596 if ( red === undefined ) {
9597 this._rgba = [ null, null, null, null ];
9598 return this;
9599 }
9600 if ( red.jquery || red.nodeType ) {
9601 red = jQuery( red ).css( green );
9602 green = undefined;
9603 }
9604
9605 var inst = this,
9606 type = jQuery.type( red ),
9607 rgba = this._rgba = [];
9608
9609 // more than 1 argument specified - assume ( red, green, blue, alpha )
9610 if ( green !== undefined ) {
9611 red = [ red, green, blue, alpha ];
9612 type = "array";
9613 }
9614
9615 if ( type === "string" ) {
9616 return this.parse( stringParse( red ) || colors._default );
9617 }
9618
9619 if ( type === "array" ) {
9620 each( spaces.rgba.props, function( key, prop ) {
9621 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
9622 });
9623 return this;
9624 }
9625
9626 if ( type === "object" ) {
9627 if ( red instanceof color ) {
9628 each( spaces, function( spaceName, space ) {
9629 if ( red[ space.cache ] ) {
9630 inst[ space.cache ] = red[ space.cache ].slice();
9631 }
9632 });
9633 } else {
9634 each( spaces, function( spaceName, space ) {
9635 var cache = space.cache;
9636 each( space.props, function( key, prop ) {
9637
9638 // if the cache doesn't exist, and we know how to convert
9639 if ( !inst[ cache ] && space.to ) {
9640
9641 // if the value was null, we don't need to copy it
9642 // if the key was alpha, we don't need to copy it either
9643 if ( key === "alpha" || red[ key ] == null ) {
9644 return;
9645 }
9646 inst[ cache ] = space.to( inst._rgba );
9647 }
9648
9649 // this is the only case where we allow nulls for ALL properties.
9650 // call clamp with alwaysAllowEmpty
9651 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
9652 });
9653
9654 // everything defined but alpha?
9655 if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
9656 // use the default of 1
9657 inst[ cache ][ 3 ] = 1;
9658 if ( space.from ) {
9659 inst._rgba = space.from( inst[ cache ] );
9660 }
9661 }
9662 });
9663 }
9664 return this;
9665 }
9666 },
9667 is: function( compare ) {
9668 var is = color( compare ),
9669 same = true,
9670 inst = this;
9671
9672 each( spaces, function( _, space ) {
9673 var localCache,
9674 isCache = is[ space.cache ];
9675 if (isCache) {
9676 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
9677 each( space.props, function( _, prop ) {
9678 if ( isCache[ prop.idx ] != null ) {
9679 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
9680 return same;
9681 }
9682 });
9683 }
9684 return same;
9685 });
9686 return same;
9687 },
9688 _space: function() {
9689 var used = [],
9690 inst = this;
9691 each( spaces, function( spaceName, space ) {
9692 if ( inst[ space.cache ] ) {
9693 used.push( spaceName );
9694 }
9695 });
9696 return used.pop();
9697 },
9698 transition: function( other, distance ) {
9699 var end = color( other ),
9700 spaceName = end._space(),
9701 space = spaces[ spaceName ],
9702 startColor = this.alpha() === 0 ? color( "transparent" ) : this,
9703 start = startColor[ space.cache ] || space.to( startColor._rgba ),
9704 result = start.slice();
9705
9706 end = end[ space.cache ];
9707 each( space.props, function( key, prop ) {
9708 var index = prop.idx,
9709 startValue = start[ index ],
9710 endValue = end[ index ],
9711 type = propTypes[ prop.type ] || {};
9712
9713 // if null, don't override start value
9714 if ( endValue === null ) {
9715 return;
9716 }
9717 // if null - use end
9718 if ( startValue === null ) {
9719 result[ index ] = endValue;
9720 } else {
9721 if ( type.mod ) {
9722 if ( endValue - startValue > type.mod / 2 ) {
9723 startValue += type.mod;
9724 } else if ( startValue - endValue > type.mod / 2 ) {
9725 startValue -= type.mod;
9726 }
9727 }
9728 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
9729 }
9730 });
9731 return this[ spaceName ]( result );
9732 },
9733 blend: function( opaque ) {
9734 // if we are already opaque - return ourself
9735 if ( this._rgba[ 3 ] === 1 ) {
9736 return this;
9737 }
9738
9739 var rgb = this._rgba.slice(),
9740 a = rgb.pop(),
9741 blend = color( opaque )._rgba;
9742
9743 return color( jQuery.map( rgb, function( v, i ) {
9744 return ( 1 - a ) * blend[ i ] + a * v;
9745 }));
9746 },
9747 toRgbaString: function() {
9748 var prefix = "rgba(",
9749 rgba = jQuery.map( this._rgba, function( v, i ) {
9750 return v == null ? ( i > 2 ? 1 : 0 ) : v;
9751 });
9752
9753 if ( rgba[ 3 ] === 1 ) {
9754 rgba.pop();
9755 prefix = "rgb(";
9756 }
9757
9758 return prefix + rgba.join() + ")";
9759 },
9760 toHslaString: function() {
9761 var prefix = "hsla(",
9762 hsla = jQuery.map( this.hsla(), function( v, i ) {
9763 if ( v == null ) {
9764 v = i > 2 ? 1 : 0;
9765 }
9766
9767 // catch 1 and 2
9768 if ( i && i < 3 ) {
9769 v = Math.round( v * 100 ) + "%";
9770 }
9771 return v;
9772 });
9773
9774 if ( hsla[ 3 ] === 1 ) {
9775 hsla.pop();
9776 prefix = "hsl(";
9777 }
9778 return prefix + hsla.join() + ")";
9779 },
9780 toHexString: function( includeAlpha ) {
9781 var rgba = this._rgba.slice(),
9782 alpha = rgba.pop();
9783
9784 if ( includeAlpha ) {
9785 rgba.push( ~~( alpha * 255 ) );
9786 }
9787
9788 return "#" + jQuery.map( rgba, function( v ) {
9789
9790 // default to 0 when nulls exist
9791 v = ( v || 0 ).toString( 16 );
9792 return v.length === 1 ? "0" + v : v;
9793 }).join("");
9794 },
9795 toString: function() {
9796 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
9797 }
9798});
9799color.fn.parse.prototype = color.fn;
9800
9801// hsla conversions adapted from:
9802// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
9803
9804function hue2rgb( p, q, h ) {
9805 h = ( h + 1 ) % 1;
9806 if ( h * 6 < 1 ) {
9807 return p + ( q - p ) * h * 6;
9808 }
9809 if ( h * 2 < 1) {
9810 return q;
9811 }
9812 if ( h * 3 < 2 ) {
9813 return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
9814 }
9815 return p;
9816}
9817
9818spaces.hsla.to = function( rgba ) {
9819 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
9820 return [ null, null, null, rgba[ 3 ] ];
9821 }
9822 var r = rgba[ 0 ] / 255,
9823 g = rgba[ 1 ] / 255,
9824 b = rgba[ 2 ] / 255,
9825 a = rgba[ 3 ],
9826 max = Math.max( r, g, b ),
9827 min = Math.min( r, g, b ),
9828 diff = max - min,
9829 add = max + min,
9830 l = add * 0.5,
9831 h, s;
9832
9833 if ( min === max ) {
9834 h = 0;
9835 } else if ( r === max ) {
9836 h = ( 60 * ( g - b ) / diff ) + 360;
9837 } else if ( g === max ) {
9838 h = ( 60 * ( b - r ) / diff ) + 120;
9839 } else {
9840 h = ( 60 * ( r - g ) / diff ) + 240;
9841 }
9842
9843 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
9844 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
9845 if ( diff === 0 ) {
9846 s = 0;
9847 } else if ( l <= 0.5 ) {
9848 s = diff / add;
9849 } else {
9850 s = diff / ( 2 - add );
9851 }
9852 return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
9853};
9854
9855spaces.hsla.from = function( hsla ) {
9856 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
9857 return [ null, null, null, hsla[ 3 ] ];
9858 }
9859 var h = hsla[ 0 ] / 360,
9860 s = hsla[ 1 ],
9861 l = hsla[ 2 ],
9862 a = hsla[ 3 ],
9863 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
9864 p = 2 * l - q;
9865
9866 return [
9867 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
9868 Math.round( hue2rgb( p, q, h ) * 255 ),
9869 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
9870 a
9871 ];
9872};
9873
9874each( spaces, function( spaceName, space ) {
9875 var props = space.props,
9876 cache = space.cache,
9877 to = space.to,
9878 from = space.from;
9879
9880 // makes rgba() and hsla()
9881 color.fn[ spaceName ] = function( value ) {
9882
9883 // generate a cache for this space if it doesn't exist
9884 if ( to && !this[ cache ] ) {
9885 this[ cache ] = to( this._rgba );
9886 }
9887 if ( value === undefined ) {
9888 return this[ cache ].slice();
9889 }
9890
9891 var ret,
9892 type = jQuery.type( value ),
9893 arr = ( type === "array" || type === "object" ) ? value : arguments,
9894 local = this[ cache ].slice();
9895
9896 each( props, function( key, prop ) {
9897 var val = arr[ type === "object" ? key : prop.idx ];
9898 if ( val == null ) {
9899 val = local[ prop.idx ];
9900 }
9901 local[ prop.idx ] = clamp( val, prop );
9902 });
9903
9904 if ( from ) {
9905 ret = color( from( local ) );
9906 ret[ cache ] = local;
9907 return ret;
9908 } else {
9909 return color( local );
9910 }
9911 };
9912
9913 // makes red() green() blue() alpha() hue() saturation() lightness()
9914 each( props, function( key, prop ) {
9915 // alpha is included in more than one space
9916 if ( color.fn[ key ] ) {
9917 return;
9918 }
9919 color.fn[ key ] = function( value ) {
9920 var vtype = jQuery.type( value ),
9921 fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
9922 local = this[ fn ](),
9923 cur = local[ prop.idx ],
9924 match;
9925
9926 if ( vtype === "undefined" ) {
9927 return cur;
9928 }
9929
9930 if ( vtype === "function" ) {
9931 value = value.call( this, cur );
9932 vtype = jQuery.type( value );
9933 }
9934 if ( value == null && prop.empty ) {
9935 return this;
9936 }
9937 if ( vtype === "string" ) {
9938 match = rplusequals.exec( value );
9939 if ( match ) {
9940 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
9941 }
9942 }
9943 local[ prop.idx ] = value;
9944 return this[ fn ]( local );
9945 };
9946 });
9947});
9948
9949// add cssHook and .fx.step function for each named hook.
9950// accept a space separated string of properties
9951color.hook = function( hook ) {
9952 var hooks = hook.split( " " );
9953 each( hooks, function( i, hook ) {
9954 jQuery.cssHooks[ hook ] = {
9955 set: function( elem, value ) {
9956 var parsed, curElem,
9957 backgroundColor = "";
9958
9959 if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
9960 value = color( parsed || value );
9961 if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
9962 curElem = hook === "backgroundColor" ? elem.parentNode : elem;
9963 while (
9964 (backgroundColor === "" || backgroundColor === "transparent") &&
9965 curElem && curElem.style
9966 ) {
9967 try {
9968 backgroundColor = jQuery.css( curElem, "backgroundColor" );
9969 curElem = curElem.parentNode;
9970 } catch ( e ) {
9971 }
9972 }
9973
9974 value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
9975 backgroundColor :
9976 "_default" );
9977 }
9978
9979 value = value.toRgbaString();
9980 }
9981 try {
9982 elem.style[ hook ] = value;
9983 } catch ( e ) {
9984 // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
9985 }
9986 }
9987 };
9988 jQuery.fx.step[ hook ] = function( fx ) {
9989 if ( !fx.colorInit ) {
9990 fx.start = color( fx.elem, hook );
9991 fx.end = color( fx.end );
9992 fx.colorInit = true;
9993 }
9994 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
9995 };
9996 });
9997
9998};
9999
10000color.hook( stepHooks );
10001
10002jQuery.cssHooks.borderColor = {
10003 expand: function( value ) {
10004 var expanded = {};
10005
10006 each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
10007 expanded[ "border" + part + "Color" ] = value;
10008 });
10009 return expanded;
10010 }
10011};
10012
10013// Basic color names only.
10014// Usage of any of the other color names requires adding yourself or including
10015// jquery.color.svg-names.js.
10016colors = jQuery.Color.names = {
10017 // 4.1. Basic color keywords
10018 aqua: "#00ffff",
10019 black: "#000000",
10020 blue: "#0000ff",
10021 fuchsia: "#ff00ff",
10022 gray: "#808080",
10023 green: "#008000",
10024 lime: "#00ff00",
10025 maroon: "#800000",
10026 navy: "#000080",
10027 olive: "#808000",
10028 purple: "#800080",
10029 red: "#ff0000",
10030 silver: "#c0c0c0",
10031 teal: "#008080",
10032 white: "#ffffff",
10033 yellow: "#ffff00",
10034
10035 // 4.2.3. "transparent" color keyword
10036 transparent: [ null, null, null, 0 ],
10037
10038 _default: "#ffffff"
10039};
10040
10041})( jQuery );
10042
10043/******************************************************************************/
10044/****************************** CLASS ANIMATIONS ******************************/
10045/******************************************************************************/
10046(function() {
10047
10048var classAnimationActions = [ "add", "remove", "toggle" ],
10049 shorthandStyles = {
10050 border: 1,
10051 borderBottom: 1,
10052 borderColor: 1,
10053 borderLeft: 1,
10054 borderRight: 1,
10055 borderTop: 1,
10056 borderWidth: 1,
10057 margin: 1,
10058 padding: 1
10059 };
10060
10061$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
10062 $.fx.step[ prop ] = function( fx ) {
10063 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
10064 jQuery.style( fx.elem, prop, fx.end );
10065 fx.setAttr = true;
10066 }
10067 };
10068});
10069
10070function getElementStyles( elem ) {
10071 var key, len,
10072 style = elem.ownerDocument.defaultView ?
10073 elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
10074 elem.currentStyle,
10075 styles = {};
10076
10077 if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
10078 len = style.length;
10079 while ( len-- ) {
10080 key = style[ len ];
10081 if ( typeof style[ key ] === "string" ) {
10082 styles[ $.camelCase( key ) ] = style[ key ];
10083 }
10084 }
10085 // support: Opera, IE <9
10086 } else {
10087 for ( key in style ) {
10088 if ( typeof style[ key ] === "string" ) {
10089 styles[ key ] = style[ key ];
10090 }
10091 }
10092 }
10093
10094 return styles;
10095}
10096
10097function styleDifference( oldStyle, newStyle ) {
10098 var diff = {},
10099 name, value;
10100
10101 for ( name in newStyle ) {
10102 value = newStyle[ name ];
10103 if ( oldStyle[ name ] !== value ) {
10104 if ( !shorthandStyles[ name ] ) {
10105 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
10106 diff[ name ] = value;
10107 }
10108 }
10109 }
10110 }
10111
10112 return diff;
10113}
10114
10115// support: jQuery <1.8
10116if ( !$.fn.addBack ) {
10117 $.fn.addBack = function( selector ) {
10118 return this.add( selector == null ?
10119 this.prevObject : this.prevObject.filter( selector )
10120 );
10121 };
10122}
10123
10124$.effects.animateClass = function( value, duration, easing, callback ) {
10125 var o = $.speed( duration, easing, callback );
10126
10127 return this.queue( function() {
10128 var animated = $( this ),
10129 baseClass = animated.attr( "class" ) || "",
10130 applyClassChange,
10131 allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
10132
10133 // map the animated objects to store the original styles.
10134 allAnimations = allAnimations.map(function() {
10135 var el = $( this );
10136 return {
10137 el: el,
10138 start: getElementStyles( this )
10139 };
10140 });
10141
10142 // apply class change
10143 applyClassChange = function() {
10144 $.each( classAnimationActions, function(i, action) {
10145 if ( value[ action ] ) {
10146 animated[ action + "Class" ]( value[ action ] );
10147 }
10148 });
10149 };
10150 applyClassChange();
10151
10152 // map all animated objects again - calculate new styles and diff
10153 allAnimations = allAnimations.map(function() {
10154 this.end = getElementStyles( this.el[ 0 ] );
10155 this.diff = styleDifference( this.start, this.end );
10156 return this;
10157 });
10158
10159 // apply original class
10160 animated.attr( "class", baseClass );
10161
10162 // map all animated objects again - this time collecting a promise
10163 allAnimations = allAnimations.map(function() {
10164 var styleInfo = this,
10165 dfd = $.Deferred(),
10166 opts = $.extend({}, o, {
10167 queue: false,
10168 complete: function() {
10169 dfd.resolve( styleInfo );
10170 }
10171 });
10172
10173 this.el.animate( this.diff, opts );
10174 return dfd.promise();
10175 });
10176
10177 // once all animations have completed:
10178 $.when.apply( $, allAnimations.get() ).done(function() {
10179
10180 // set the final class
10181 applyClassChange();
10182
10183 // for each animated element,
10184 // clear all css properties that were animated
10185 $.each( arguments, function() {
10186 var el = this.el;
10187 $.each( this.diff, function(key) {
10188 el.css( key, "" );
10189 });
10190 });
10191
10192 // this is guarnteed to be there if you use jQuery.speed()
10193 // it also handles dequeuing the next anim...
10194 o.complete.call( animated[ 0 ] );
10195 });
10196 });
10197};
10198
10199$.fn.extend({
10200 addClass: (function( orig ) {
10201 return function( classNames, speed, easing, callback ) {
10202 return speed ?
10203 $.effects.animateClass.call( this,
10204 { add: classNames }, speed, easing, callback ) :
10205 orig.apply( this, arguments );
10206 };
10207 })( $.fn.addClass ),
10208
10209 removeClass: (function( orig ) {
10210 return function( classNames, speed, easing, callback ) {
10211 return arguments.length > 1 ?
10212 $.effects.animateClass.call( this,
10213 { remove: classNames }, speed, easing, callback ) :
10214 orig.apply( this, arguments );
10215 };
10216 })( $.fn.removeClass ),
10217
10218 toggleClass: (function( orig ) {
10219 return function( classNames, force, speed, easing, callback ) {
10220 if ( typeof force === "boolean" || force === undefined ) {
10221 if ( !speed ) {
10222 // without speed parameter
10223 return orig.apply( this, arguments );
10224 } else {
10225 return $.effects.animateClass.call( this,
10226 (force ? { add: classNames } : { remove: classNames }),
10227 speed, easing, callback );
10228 }
10229 } else {
10230 // without force parameter
10231 return $.effects.animateClass.call( this,
10232 { toggle: classNames }, force, speed, easing );
10233 }
10234 };
10235 })( $.fn.toggleClass ),
10236
10237 switchClass: function( remove, add, speed, easing, callback) {
10238 return $.effects.animateClass.call( this, {
10239 add: add,
10240 remove: remove
10241 }, speed, easing, callback );
10242 }
10243});
10244
10245})();
10246
10247/******************************************************************************/
10248/*********************************** EFFECTS **********************************/
10249/******************************************************************************/
10250
10251(function() {
10252
10253$.extend( $.effects, {
10254 version: "1.11.2",
10255
10256 // Saves a set of properties in a data storage
10257 save: function( element, set ) {
10258 for ( var i = 0; i < set.length; i++ ) {
10259 if ( set[ i ] !== null ) {
10260 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
10261 }
10262 }
10263 },
10264
10265 // Restores a set of previously saved properties from a data storage
10266 restore: function( element, set ) {
10267 var val, i;
10268 for ( i = 0; i < set.length; i++ ) {
10269 if ( set[ i ] !== null ) {
10270 val = element.data( dataSpace + set[ i ] );
10271 // support: jQuery 1.6.2
10272 // http://bugs.jquery.com/ticket/9917
10273 // jQuery 1.6.2 incorrectly returns undefined for any falsy value.
10274 // We can't differentiate between "" and 0 here, so we just assume
10275 // empty string since it's likely to be a more common value...
10276 if ( val === undefined ) {
10277 val = "";
10278 }
10279 element.css( set[ i ], val );
10280 }
10281 }
10282 },
10283
10284 setMode: function( el, mode ) {
10285 if (mode === "toggle") {
10286 mode = el.is( ":hidden" ) ? "show" : "hide";
10287 }
10288 return mode;
10289 },
10290
10291 // Translates a [top,left] array into a baseline value
10292 // this should be a little more flexible in the future to handle a string & hash
10293 getBaseline: function( origin, original ) {
10294 var y, x;
10295 switch ( origin[ 0 ] ) {
10296 case "top": y = 0; break;
10297 case "middle": y = 0.5; break;
10298 case "bottom": y = 1; break;
10299 default: y = origin[ 0 ] / original.height;
10300 }
10301 switch ( origin[ 1 ] ) {
10302 case "left": x = 0; break;
10303 case "center": x = 0.5; break;
10304 case "right": x = 1; break;
10305 default: x = origin[ 1 ] / original.width;
10306 }
10307 return {
10308 x: x,
10309 y: y
10310 };
10311 },
10312
10313 // Wraps the element around a wrapper that copies position properties
10314 createWrapper: function( element ) {
10315
10316 // if the element is already wrapped, return it
10317 if ( element.parent().is( ".ui-effects-wrapper" )) {
10318 return element.parent();
10319 }
10320
10321 // wrap the element
10322 var props = {
10323 width: element.outerWidth(true),
10324 height: element.outerHeight(true),
10325 "float": element.css( "float" )
10326 },
10327 wrapper = $( "<div></div>" )
10328 .addClass( "ui-effects-wrapper" )
10329 .css({
10330 fontSize: "100%",
10331 background: "transparent",
10332 border: "none",
10333 margin: 0,
10334 padding: 0
10335 }),
10336 // Store the size in case width/height are defined in % - Fixes #5245
10337 size = {
10338 width: element.width(),
10339 height: element.height()
10340 },
10341 active = document.activeElement;
10342
10343 // support: Firefox
10344 // Firefox incorrectly exposes anonymous content
10345 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
10346 try {
10347 active.id;
10348 } catch ( e ) {
10349 active = document.body;
10350 }
10351
10352 element.wrap( wrapper );
10353
10354 // Fixes #7595 - Elements lose focus when wrapped.
10355 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
10356 $( active ).focus();
10357 }
10358
10359 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
10360
10361 // transfer positioning properties to the wrapper
10362 if ( element.css( "position" ) === "static" ) {
10363 wrapper.css({ position: "relative" });
10364 element.css({ position: "relative" });
10365 } else {
10366 $.extend( props, {
10367 position: element.css( "position" ),
10368 zIndex: element.css( "z-index" )
10369 });
10370 $.each([ "top", "left", "bottom", "right" ], function(i, pos) {
10371 props[ pos ] = element.css( pos );
10372 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
10373 props[ pos ] = "auto";
10374 }
10375 });
10376 element.css({
10377 position: "relative",
10378 top: 0,
10379 left: 0,
10380 right: "auto",
10381 bottom: "auto"
10382 });
10383 }
10384 element.css(size);
10385
10386 return wrapper.css( props ).show();
10387 },
10388
10389 removeWrapper: function( element ) {
10390 var active = document.activeElement;
10391
10392 if ( element.parent().is( ".ui-effects-wrapper" ) ) {
10393 element.parent().replaceWith( element );
10394
10395 // Fixes #7595 - Elements lose focus when wrapped.
10396 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
10397 $( active ).focus();
10398 }
10399 }
10400
10401 return element;
10402 },
10403
10404 setTransition: function( element, list, factor, value ) {
10405 value = value || {};
10406 $.each( list, function( i, x ) {
10407 var unit = element.cssUnit( x );
10408 if ( unit[ 0 ] > 0 ) {
10409 value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
10410 }
10411 });
10412 return value;
10413 }
10414});
10415
10416// return an effect options object for the given parameters:
10417function _normalizeArguments( effect, options, speed, callback ) {
10418
10419 // allow passing all options as the first parameter
10420 if ( $.isPlainObject( effect ) ) {
10421 options = effect;
10422 effect = effect.effect;
10423 }
10424
10425 // convert to an object
10426 effect = { effect: effect };
10427
10428 // catch (effect, null, ...)
10429 if ( options == null ) {
10430 options = {};
10431 }
10432
10433 // catch (effect, callback)
10434 if ( $.isFunction( options ) ) {
10435 callback = options;
10436 speed = null;
10437 options = {};
10438 }
10439
10440 // catch (effect, speed, ?)
10441 if ( typeof options === "number" || $.fx.speeds[ options ] ) {
10442 callback = speed;
10443 speed = options;
10444 options = {};
10445 }
10446
10447 // catch (effect, options, callback)
10448 if ( $.isFunction( speed ) ) {
10449 callback = speed;
10450 speed = null;
10451 }
10452
10453 // add options to effect
10454 if ( options ) {
10455 $.extend( effect, options );
10456 }
10457
10458 speed = speed || options.duration;
10459 effect.duration = $.fx.off ? 0 :
10460 typeof speed === "number" ? speed :
10461 speed in $.fx.speeds ? $.fx.speeds[ speed ] :
10462 $.fx.speeds._default;
10463
10464 effect.complete = callback || options.complete;
10465
10466 return effect;
10467}
10468
10469function standardAnimationOption( option ) {
10470 // Valid standard speeds (nothing, number, named speed)
10471 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
10472 return true;
10473 }
10474
10475 // Invalid strings - treat as "normal" speed
10476 if ( typeof option === "string" && !$.effects.effect[ option ] ) {
10477 return true;
10478 }
10479
10480 // Complete callback
10481 if ( $.isFunction( option ) ) {
10482 return true;
10483 }
10484
10485 // Options hash (but not naming an effect)
10486 if ( typeof option === "object" && !option.effect ) {
10487 return true;
10488 }
10489
10490 // Didn't match any standard API
10491 return false;
10492}
10493
10494$.fn.extend({
10495 effect: function( /* effect, options, speed, callback */ ) {
10496 var args = _normalizeArguments.apply( this, arguments ),
10497 mode = args.mode,
10498 queue = args.queue,
10499 effectMethod = $.effects.effect[ args.effect ];
10500
10501 if ( $.fx.off || !effectMethod ) {
10502 // delegate to the original method (e.g., .show()) if possible
10503 if ( mode ) {
10504 return this[ mode ]( args.duration, args.complete );
10505 } else {
10506 return this.each( function() {
10507 if ( args.complete ) {
10508 args.complete.call( this );
10509 }
10510 });
10511 }
10512 }
10513
10514 function run( next ) {
10515 var elem = $( this ),
10516 complete = args.complete,
10517 mode = args.mode;
10518
10519 function done() {
10520 if ( $.isFunction( complete ) ) {
10521 complete.call( elem[0] );
10522 }
10523 if ( $.isFunction( next ) ) {
10524 next();
10525 }
10526 }
10527
10528 // If the element already has the correct final state, delegate to
10529 // the core methods so the internal tracking of "olddisplay" works.
10530 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
10531 elem[ mode ]();
10532 done();
10533 } else {
10534 effectMethod.call( elem[0], args, done );
10535 }
10536 }
10537
10538 return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
10539 },
10540
10541 show: (function( orig ) {
10542 return function( option ) {
10543 if ( standardAnimationOption( option ) ) {
10544 return orig.apply( this, arguments );
10545 } else {
10546 var args = _normalizeArguments.apply( this, arguments );
10547 args.mode = "show";
10548 return this.effect.call( this, args );
10549 }
10550 };
10551 })( $.fn.show ),
10552
10553 hide: (function( orig ) {
10554 return function( option ) {
10555 if ( standardAnimationOption( option ) ) {
10556 return orig.apply( this, arguments );
10557 } else {
10558 var args = _normalizeArguments.apply( this, arguments );
10559 args.mode = "hide";
10560 return this.effect.call( this, args );
10561 }
10562 };
10563 })( $.fn.hide ),
10564
10565 toggle: (function( orig ) {
10566 return function( option ) {
10567 if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
10568 return orig.apply( this, arguments );
10569 } else {
10570 var args = _normalizeArguments.apply( this, arguments );
10571 args.mode = "toggle";
10572 return this.effect.call( this, args );
10573 }
10574 };
10575 })( $.fn.toggle ),
10576
10577 // helper functions
10578 cssUnit: function(key) {
10579 var style = this.css( key ),
10580 val = [];
10581
10582 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
10583 if ( style.indexOf( unit ) > 0 ) {
10584 val = [ parseFloat( style ), unit ];
10585 }
10586 });
10587 return val;
10588 }
10589});
10590
10591})();
10592
10593/******************************************************************************/
10594/*********************************** EASING ***********************************/
10595/******************************************************************************/
10596
10597(function() {
10598
10599// based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
10600
10601var baseEasings = {};
10602
10603$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
10604 baseEasings[ name ] = function( p ) {
10605 return Math.pow( p, i + 2 );
10606 };
10607});
10608
10609$.extend( baseEasings, {
10610 Sine: function( p ) {
10611 return 1 - Math.cos( p * Math.PI / 2 );
10612 },
10613 Circ: function( p ) {
10614 return 1 - Math.sqrt( 1 - p * p );
10615 },
10616 Elastic: function( p ) {
10617 return p === 0 || p === 1 ? p :
10618 -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
10619 },
10620 Back: function( p ) {
10621 return p * p * ( 3 * p - 2 );
10622 },
10623 Bounce: function( p ) {
10624 var pow2,
10625 bounce = 4;
10626
10627 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
10628 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
10629 }
10630});
10631
10632$.each( baseEasings, function( name, easeIn ) {
10633 $.easing[ "easeIn" + name ] = easeIn;
10634 $.easing[ "easeOut" + name ] = function( p ) {
10635 return 1 - easeIn( 1 - p );
10636 };
10637 $.easing[ "easeInOut" + name ] = function( p ) {
10638 return p < 0.5 ?
10639 easeIn( p * 2 ) / 2 :
10640 1 - easeIn( p * -2 + 2 ) / 2;
10641 };
10642});
10643
10644})();
10645
10646var effect = $.effects;
10647
10648
10649/*!
10650 * jQuery UI Effects Blind 1.11.2
10651 * http://jqueryui.com
10652 *
10653 * Copyright 2014 jQuery Foundation and other contributors
10654 * Released under the MIT license.
10655 * http://jquery.org/license
10656 *
10657 * http://api.jqueryui.com/blind-effect/
10658 */
10659
10660
10661var effectBlind = $.effects.effect.blind = function( o, done ) {
10662 // Create element
10663 var el = $( this ),
10664 rvertical = /up|down|vertical/,
10665 rpositivemotion = /up|left|vertical|horizontal/,
10666 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10667 mode = $.effects.setMode( el, o.mode || "hide" ),
10668 direction = o.direction || "up",
10669 vertical = rvertical.test( direction ),
10670 ref = vertical ? "height" : "width",
10671 ref2 = vertical ? "top" : "left",
10672 motion = rpositivemotion.test( direction ),
10673 animation = {},
10674 show = mode === "show",
10675 wrapper, distance, margin;
10676
10677 // if already wrapped, the wrapper's properties are my property. #6245
10678 if ( el.parent().is( ".ui-effects-wrapper" ) ) {
10679 $.effects.save( el.parent(), props );
10680 } else {
10681 $.effects.save( el, props );
10682 }
10683 el.show();
10684 wrapper = $.effects.createWrapper( el ).css({
10685 overflow: "hidden"
10686 });
10687
10688 distance = wrapper[ ref ]();
10689 margin = parseFloat( wrapper.css( ref2 ) ) || 0;
10690
10691 animation[ ref ] = show ? distance : 0;
10692 if ( !motion ) {
10693 el
10694 .css( vertical ? "bottom" : "right", 0 )
10695 .css( vertical ? "top" : "left", "auto" )
10696 .css({ position: "absolute" });
10697
10698 animation[ ref2 ] = show ? margin : distance + margin;
10699 }
10700
10701 // start at 0 if we are showing
10702 if ( show ) {
10703 wrapper.css( ref, 0 );
10704 if ( !motion ) {
10705 wrapper.css( ref2, margin + distance );
10706 }
10707 }
10708
10709 // Animate
10710 wrapper.animate( animation, {
10711 duration: o.duration,
10712 easing: o.easing,
10713 queue: false,
10714 complete: function() {
10715 if ( mode === "hide" ) {
10716 el.hide();
10717 }
10718 $.effects.restore( el, props );
10719 $.effects.removeWrapper( el );
10720 done();
10721 }
10722 });
10723};
10724
10725
10726/*!
10727 * jQuery UI Effects Bounce 1.11.2
10728 * http://jqueryui.com
10729 *
10730 * Copyright 2014 jQuery Foundation and other contributors
10731 * Released under the MIT license.
10732 * http://jquery.org/license
10733 *
10734 * http://api.jqueryui.com/bounce-effect/
10735 */
10736
10737
10738var effectBounce = $.effects.effect.bounce = function( o, done ) {
10739 var el = $( this ),
10740 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10741
10742 // defaults:
10743 mode = $.effects.setMode( el, o.mode || "effect" ),
10744 hide = mode === "hide",
10745 show = mode === "show",
10746 direction = o.direction || "up",
10747 distance = o.distance,
10748 times = o.times || 5,
10749
10750 // number of internal animations
10751 anims = times * 2 + ( show || hide ? 1 : 0 ),
10752 speed = o.duration / anims,
10753 easing = o.easing,
10754
10755 // utility:
10756 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10757 motion = ( direction === "up" || direction === "left" ),
10758 i,
10759 upAnim,
10760 downAnim,
10761
10762 // we will need to re-assemble the queue to stack our animations in place
10763 queue = el.queue(),
10764 queuelen = queue.length;
10765
10766 // Avoid touching opacity to prevent clearType and PNG issues in IE
10767 if ( show || hide ) {
10768 props.push( "opacity" );
10769 }
10770
10771 $.effects.save( el, props );
10772 el.show();
10773 $.effects.createWrapper( el ); // Create Wrapper
10774
10775 // default distance for the BIGGEST bounce is the outer Distance / 3
10776 if ( !distance ) {
10777 distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
10778 }
10779
10780 if ( show ) {
10781 downAnim = { opacity: 1 };
10782 downAnim[ ref ] = 0;
10783
10784 // if we are showing, force opacity 0 and set the initial position
10785 // then do the "first" animation
10786 el.css( "opacity", 0 )
10787 .css( ref, motion ? -distance * 2 : distance * 2 )
10788 .animate( downAnim, speed, easing );
10789 }
10790
10791 // start at the smallest distance if we are hiding
10792 if ( hide ) {
10793 distance = distance / Math.pow( 2, times - 1 );
10794 }
10795
10796 downAnim = {};
10797 downAnim[ ref ] = 0;
10798 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
10799 for ( i = 0; i < times; i++ ) {
10800 upAnim = {};
10801 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10802
10803 el.animate( upAnim, speed, easing )
10804 .animate( downAnim, speed, easing );
10805
10806 distance = hide ? distance * 2 : distance / 2;
10807 }
10808
10809 // Last Bounce when Hiding
10810 if ( hide ) {
10811 upAnim = { opacity: 0 };
10812 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10813
10814 el.animate( upAnim, speed, easing );
10815 }
10816
10817 el.queue(function() {
10818 if ( hide ) {
10819 el.hide();
10820 }
10821 $.effects.restore( el, props );
10822 $.effects.removeWrapper( el );
10823 done();
10824 });
10825
10826 // inject all the animations we just queued to be first in line (after "inprogress")
10827 if ( queuelen > 1) {
10828 queue.splice.apply( queue,
10829 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
10830 }
10831 el.dequeue();
10832
10833};
10834
10835
10836/*!
10837 * jQuery UI Effects Clip 1.11.2
10838 * http://jqueryui.com
10839 *
10840 * Copyright 2014 jQuery Foundation and other contributors
10841 * Released under the MIT license.
10842 * http://jquery.org/license
10843 *
10844 * http://api.jqueryui.com/clip-effect/
10845 */
10846
10847
10848var effectClip = $.effects.effect.clip = function( o, done ) {
10849 // Create element
10850 var el = $( this ),
10851 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10852 mode = $.effects.setMode( el, o.mode || "hide" ),
10853 show = mode === "show",
10854 direction = o.direction || "vertical",
10855 vert = direction === "vertical",
10856 size = vert ? "height" : "width",
10857 position = vert ? "top" : "left",
10858 animation = {},
10859 wrapper, animate, distance;
10860
10861 // Save & Show
10862 $.effects.save( el, props );
10863 el.show();
10864
10865 // Create Wrapper
10866 wrapper = $.effects.createWrapper( el ).css({
10867 overflow: "hidden"
10868 });
10869 animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
10870 distance = animate[ size ]();
10871
10872 // Shift
10873 if ( show ) {
10874 animate.css( size, 0 );
10875 animate.css( position, distance / 2 );
10876 }
10877
10878 // Create Animation Object:
10879 animation[ size ] = show ? distance : 0;
10880 animation[ position ] = show ? 0 : distance / 2;
10881
10882 // Animate
10883 animate.animate( animation, {
10884 queue: false,
10885 duration: o.duration,
10886 easing: o.easing,
10887 complete: function() {
10888 if ( !show ) {
10889 el.hide();
10890 }
10891 $.effects.restore( el, props );
10892 $.effects.removeWrapper( el );
10893 done();
10894 }
10895 });
10896
10897};
10898
10899
10900/*!
10901 * jQuery UI Effects Drop 1.11.2
10902 * http://jqueryui.com
10903 *
10904 * Copyright 2014 jQuery Foundation and other contributors
10905 * Released under the MIT license.
10906 * http://jquery.org/license
10907 *
10908 * http://api.jqueryui.com/drop-effect/
10909 */
10910
10911
10912var effectDrop = $.effects.effect.drop = function( o, done ) {
10913
10914 var el = $( this ),
10915 props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
10916 mode = $.effects.setMode( el, o.mode || "hide" ),
10917 show = mode === "show",
10918 direction = o.direction || "left",
10919 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10920 motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
10921 animation = {
10922 opacity: show ? 1 : 0
10923 },
10924 distance;
10925
10926 // Adjust
10927 $.effects.save( el, props );
10928 el.show();
10929 $.effects.createWrapper( el );
10930
10931 distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
10932
10933 if ( show ) {
10934 el
10935 .css( "opacity", 0 )
10936 .css( ref, motion === "pos" ? -distance : distance );
10937 }
10938
10939 // Animation
10940 animation[ ref ] = ( show ?
10941 ( motion === "pos" ? "+=" : "-=" ) :
10942 ( motion === "pos" ? "-=" : "+=" ) ) +
10943 distance;
10944
10945 // Animate
10946 el.animate( animation, {
10947 queue: false,
10948 duration: o.duration,
10949 easing: o.easing,
10950 complete: function() {
10951 if ( mode === "hide" ) {
10952 el.hide();
10953 }
10954 $.effects.restore( el, props );
10955 $.effects.removeWrapper( el );
10956 done();
10957 }
10958 });
10959};
10960
10961
10962/*!
10963 * jQuery UI Effects Explode 1.11.2
10964 * http://jqueryui.com
10965 *
10966 * Copyright 2014 jQuery Foundation and other contributors
10967 * Released under the MIT license.
10968 * http://jquery.org/license
10969 *
10970 * http://api.jqueryui.com/explode-effect/
10971 */
10972
10973
10974var effectExplode = $.effects.effect.explode = function( o, done ) {
10975
10976 var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
10977 cells = rows,
10978 el = $( this ),
10979 mode = $.effects.setMode( el, o.mode || "hide" ),
10980 show = mode === "show",
10981
10982 // show and then visibility:hidden the element before calculating offset
10983 offset = el.show().css( "visibility", "hidden" ).offset(),
10984
10985 // width and height of a piece
10986 width = Math.ceil( el.outerWidth() / cells ),
10987 height = Math.ceil( el.outerHeight() / rows ),
10988 pieces = [],
10989
10990 // loop
10991 i, j, left, top, mx, my;
10992
10993 // children animate complete:
10994 function childComplete() {
10995 pieces.push( this );
10996 if ( pieces.length === rows * cells ) {
10997 animComplete();
10998 }
10999 }
11000
11001 // clone the element for each row and cell.
11002 for ( i = 0; i < rows ; i++ ) { // ===>
11003 top = offset.top + i * height;
11004 my = i - ( rows - 1 ) / 2 ;
11005
11006 for ( j = 0; j < cells ; j++ ) { // |||
11007 left = offset.left + j * width;
11008 mx = j - ( cells - 1 ) / 2 ;
11009
11010 // Create a clone of the now hidden main element that will be absolute positioned
11011 // within a wrapper div off the -left and -top equal to size of our pieces
11012 el
11013 .clone()
11014 .appendTo( "body" )
11015 .wrap( "<div></div>" )
11016 .css({
11017 position: "absolute",
11018 visibility: "visible",
11019 left: -j * width,
11020 top: -i * height
11021 })
11022
11023 // select the wrapper - make it overflow: hidden and absolute positioned based on
11024 // where the original was located +left and +top equal to the size of pieces
11025 .parent()
11026 .addClass( "ui-effects-explode" )
11027 .css({
11028 position: "absolute",
11029 overflow: "hidden",
11030 width: width,
11031 height: height,
11032 left: left + ( show ? mx * width : 0 ),
11033 top: top + ( show ? my * height : 0 ),
11034 opacity: show ? 0 : 1
11035 }).animate({
11036 left: left + ( show ? 0 : mx * width ),
11037 top: top + ( show ? 0 : my * height ),
11038 opacity: show ? 1 : 0
11039 }, o.duration || 500, o.easing, childComplete );
11040 }
11041 }
11042
11043 function animComplete() {
11044 el.css({
11045 visibility: "visible"
11046 });
11047 $( pieces ).remove();
11048 if ( !show ) {
11049 el.hide();
11050 }
11051 done();
11052 }
11053};
11054
11055
11056/*!
11057 * jQuery UI Effects Fade 1.11.2
11058 * http://jqueryui.com
11059 *
11060 * Copyright 2014 jQuery Foundation and other contributors
11061 * Released under the MIT license.
11062 * http://jquery.org/license
11063 *
11064 * http://api.jqueryui.com/fade-effect/
11065 */
11066
11067
11068var effectFade = $.effects.effect.fade = function( o, done ) {
11069 var el = $( this ),
11070 mode = $.effects.setMode( el, o.mode || "toggle" );
11071
11072 el.animate({
11073 opacity: mode
11074 }, {
11075 queue: false,
11076 duration: o.duration,
11077 easing: o.easing,
11078 complete: done
11079 });
11080};
11081
11082
11083/*!
11084 * jQuery UI Effects Fold 1.11.2
11085 * http://jqueryui.com
11086 *
11087 * Copyright 2014 jQuery Foundation and other contributors
11088 * Released under the MIT license.
11089 * http://jquery.org/license
11090 *
11091 * http://api.jqueryui.com/fold-effect/
11092 */
11093
11094
11095var effectFold = $.effects.effect.fold = function( o, done ) {
11096
11097 // Create element
11098 var el = $( this ),
11099 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
11100 mode = $.effects.setMode( el, o.mode || "hide" ),
11101 show = mode === "show",
11102 hide = mode === "hide",
11103 size = o.size || 15,
11104 percent = /([0-9]+)%/.exec( size ),
11105 horizFirst = !!o.horizFirst,
11106 widthFirst = show !== horizFirst,
11107 ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
11108 duration = o.duration / 2,
11109 wrapper, distance,
11110 animation1 = {},
11111 animation2 = {};
11112
11113 $.effects.save( el, props );
11114 el.show();
11115
11116 // Create Wrapper
11117 wrapper = $.effects.createWrapper( el ).css({
11118 overflow: "hidden"
11119 });
11120 distance = widthFirst ?
11121 [ wrapper.width(), wrapper.height() ] :
11122 [ wrapper.height(), wrapper.width() ];
11123
11124 if ( percent ) {
11125 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
11126 }
11127 if ( show ) {
11128 wrapper.css( horizFirst ? {
11129 height: 0,
11130 width: size
11131 } : {
11132 height: size,
11133 width: 0
11134 });
11135 }
11136
11137 // Animation
11138 animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
11139 animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
11140
11141 // Animate
11142 wrapper
11143 .animate( animation1, duration, o.easing )
11144 .animate( animation2, duration, o.easing, function() {
11145 if ( hide ) {
11146 el.hide();
11147 }
11148 $.effects.restore( el, props );
11149 $.effects.removeWrapper( el );
11150 done();
11151 });
11152
11153};
11154
11155
11156/*!
11157 * jQuery UI Effects Highlight 1.11.2
11158 * http://jqueryui.com
11159 *
11160 * Copyright 2014 jQuery Foundation and other contributors
11161 * Released under the MIT license.
11162 * http://jquery.org/license
11163 *
11164 * http://api.jqueryui.com/highlight-effect/
11165 */
11166
11167
11168var effectHighlight = $.effects.effect.highlight = function( o, done ) {
11169 var elem = $( this ),
11170 props = [ "backgroundImage", "backgroundColor", "opacity" ],
11171 mode = $.effects.setMode( elem, o.mode || "show" ),
11172 animation = {
11173 backgroundColor: elem.css( "backgroundColor" )
11174 };
11175
11176 if (mode === "hide") {
11177 animation.opacity = 0;
11178 }
11179
11180 $.effects.save( elem, props );
11181
11182 elem
11183 .show()
11184 .css({
11185 backgroundImage: "none",
11186 backgroundColor: o.color || "#ffff99"
11187 })
11188 .animate( animation, {
11189 queue: false,
11190 duration: o.duration,
11191 easing: o.easing,
11192 complete: function() {
11193 if ( mode === "hide" ) {
11194 elem.hide();
11195 }
11196 $.effects.restore( elem, props );
11197 done();
11198 }
11199 });
11200};
11201
11202
11203/*!
11204 * jQuery UI Effects Size 1.11.2
11205 * http://jqueryui.com
11206 *
11207 * Copyright 2014 jQuery Foundation and other contributors
11208 * Released under the MIT license.
11209 * http://jquery.org/license
11210 *
11211 * http://api.jqueryui.com/size-effect/
11212 */
11213
11214
11215var effectSize = $.effects.effect.size = function( o, done ) {
11216
11217 // Create element
11218 var original, baseline, factor,
11219 el = $( this ),
11220 props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
11221
11222 // Always restore
11223 props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
11224
11225 // Copy for children
11226 props2 = [ "width", "height", "overflow" ],
11227 cProps = [ "fontSize" ],
11228 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
11229 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
11230
11231 // Set options
11232 mode = $.effects.setMode( el, o.mode || "effect" ),
11233 restore = o.restore || mode !== "effect",
11234 scale = o.scale || "both",
11235 origin = o.origin || [ "middle", "center" ],
11236 position = el.css( "position" ),
11237 props = restore ? props0 : props1,
11238 zero = {
11239 height: 0,
11240 width: 0,
11241 outerHeight: 0,
11242 outerWidth: 0
11243 };
11244
11245 if ( mode === "show" ) {
11246 el.show();
11247 }
11248 original = {
11249 height: el.height(),
11250 width: el.width(),
11251 outerHeight: el.outerHeight(),
11252 outerWidth: el.outerWidth()
11253 };
11254
11255 if ( o.mode === "toggle" && mode === "show" ) {
11256 el.from = o.to || zero;
11257 el.to = o.from || original;
11258 } else {
11259 el.from = o.from || ( mode === "show" ? zero : original );
11260 el.to = o.to || ( mode === "hide" ? zero : original );
11261 }
11262
11263 // Set scaling factor
11264 factor = {
11265 from: {
11266 y: el.from.height / original.height,
11267 x: el.from.width / original.width
11268 },
11269 to: {
11270 y: el.to.height / original.height,
11271 x: el.to.width / original.width
11272 }
11273 };
11274
11275 // Scale the css box
11276 if ( scale === "box" || scale === "both" ) {
11277
11278 // Vertical props scaling
11279 if ( factor.from.y !== factor.to.y ) {
11280 props = props.concat( vProps );
11281 el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
11282 el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
11283 }
11284
11285 // Horizontal props scaling
11286 if ( factor.from.x !== factor.to.x ) {
11287 props = props.concat( hProps );
11288 el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
11289 el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
11290 }
11291 }
11292
11293 // Scale the content
11294 if ( scale === "content" || scale === "both" ) {
11295
11296 // Vertical props scaling
11297 if ( factor.from.y !== factor.to.y ) {
11298 props = props.concat( cProps ).concat( props2 );
11299 el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
11300 el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
11301 }
11302 }
11303
11304 $.effects.save( el, props );
11305 el.show();
11306 $.effects.createWrapper( el );
11307 el.css( "overflow", "hidden" ).css( el.from );
11308
11309 // Adjust
11310 if (origin) { // Calculate baseline shifts
11311 baseline = $.effects.getBaseline( origin, original );
11312 el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
11313 el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
11314 el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
11315 el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
11316 }
11317 el.css( el.from ); // set top & left
11318
11319 // Animate
11320 if ( scale === "content" || scale === "both" ) { // Scale the children
11321
11322 // Add margins/font-size
11323 vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
11324 hProps = hProps.concat([ "marginLeft", "marginRight" ]);
11325 props2 = props0.concat(vProps).concat(hProps);
11326
11327 el.find( "*[width]" ).each( function() {
11328 var child = $( this ),
11329 c_original = {
11330 height: child.height(),
11331 width: child.width(),
11332 outerHeight: child.outerHeight(),
11333 outerWidth: child.outerWidth()
11334 };
11335 if (restore) {
11336 $.effects.save(child, props2);
11337 }
11338
11339 child.from = {
11340 height: c_original.height * factor.from.y,
11341 width: c_original.width * factor.from.x,
11342 outerHeight: c_original.outerHeight * factor.from.y,
11343 outerWidth: c_original.outerWidth * factor.from.x
11344 };
11345 child.to = {
11346 height: c_original.height * factor.to.y,
11347 width: c_original.width * factor.to.x,
11348 outerHeight: c_original.height * factor.to.y,
11349 outerWidth: c_original.width * factor.to.x
11350 };
11351
11352 // Vertical props scaling
11353 if ( factor.from.y !== factor.to.y ) {
11354 child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
11355 child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
11356 }
11357
11358 // Horizontal props scaling
11359 if ( factor.from.x !== factor.to.x ) {
11360 child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
11361 child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
11362 }
11363
11364 // Animate children
11365 child.css( child.from );
11366 child.animate( child.to, o.duration, o.easing, function() {
11367
11368 // Restore children
11369 if ( restore ) {
11370 $.effects.restore( child, props2 );
11371 }
11372 });
11373 });
11374 }
11375
11376 // Animate
11377 el.animate( el.to, {
11378 queue: false,
11379 duration: o.duration,
11380 easing: o.easing,
11381 complete: function() {
11382 if ( el.to.opacity === 0 ) {
11383 el.css( "opacity", el.from.opacity );
11384 }
11385 if ( mode === "hide" ) {
11386 el.hide();
11387 }
11388 $.effects.restore( el, props );
11389 if ( !restore ) {
11390
11391 // we need to calculate our new positioning based on the scaling
11392 if ( position === "static" ) {
11393 el.css({
11394 position: "relative",
11395 top: el.to.top,
11396 left: el.to.left
11397 });
11398 } else {
11399 $.each([ "top", "left" ], function( idx, pos ) {
11400 el.css( pos, function( _, str ) {
11401 var val = parseInt( str, 10 ),
11402 toRef = idx ? el.to.left : el.to.top;
11403
11404 // if original was "auto", recalculate the new value from wrapper
11405 if ( str === "auto" ) {
11406 return toRef + "px";
11407 }
11408
11409 return val + toRef + "px";
11410 });
11411 });
11412 }
11413 }
11414
11415 $.effects.removeWrapper( el );
11416 done();
11417 }
11418 });
11419
11420};
11421
11422
11423/*!
11424 * jQuery UI Effects Scale 1.11.2
11425 * http://jqueryui.com
11426 *
11427 * Copyright 2014 jQuery Foundation and other contributors
11428 * Released under the MIT license.
11429 * http://jquery.org/license
11430 *
11431 * http://api.jqueryui.com/scale-effect/
11432 */
11433
11434
11435var effectScale = $.effects.effect.scale = function( o, done ) {
11436
11437 // Create element
11438 var el = $( this ),
11439 options = $.extend( true, {}, o ),
11440 mode = $.effects.setMode( el, o.mode || "effect" ),
11441 percent = parseInt( o.percent, 10 ) ||
11442 ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
11443 direction = o.direction || "both",
11444 origin = o.origin,
11445 original = {
11446 height: el.height(),
11447 width: el.width(),
11448 outerHeight: el.outerHeight(),
11449 outerWidth: el.outerWidth()
11450 },
11451 factor = {
11452 y: direction !== "horizontal" ? (percent / 100) : 1,
11453 x: direction !== "vertical" ? (percent / 100) : 1
11454 };
11455
11456 // We are going to pass this effect to the size effect:
11457 options.effect = "size";
11458 options.queue = false;
11459 options.complete = done;
11460
11461 // Set default origin and restore for show/hide
11462 if ( mode !== "effect" ) {
11463 options.origin = origin || [ "middle", "center" ];
11464 options.restore = true;
11465 }
11466
11467 options.from = o.from || ( mode === "show" ? {
11468 height: 0,
11469 width: 0,
11470 outerHeight: 0,
11471 outerWidth: 0
11472 } : original );
11473 options.to = {
11474 height: original.height * factor.y,
11475 width: original.width * factor.x,
11476 outerHeight: original.outerHeight * factor.y,
11477 outerWidth: original.outerWidth * factor.x
11478 };
11479
11480 // Fade option to support puff
11481 if ( options.fade ) {
11482 if ( mode === "show" ) {
11483 options.from.opacity = 0;
11484 options.to.opacity = 1;
11485 }
11486 if ( mode === "hide" ) {
11487 options.from.opacity = 1;
11488 options.to.opacity = 0;
11489 }
11490 }
11491
11492 // Animate
11493 el.effect( options );
11494
11495};
11496
11497
11498/*!
11499 * jQuery UI Effects Puff 1.11.2
11500 * http://jqueryui.com
11501 *
11502 * Copyright 2014 jQuery Foundation and other contributors
11503 * Released under the MIT license.
11504 * http://jquery.org/license
11505 *
11506 * http://api.jqueryui.com/puff-effect/
11507 */
11508
11509
11510var effectPuff = $.effects.effect.puff = function( o, done ) {
11511 var elem = $( this ),
11512 mode = $.effects.setMode( elem, o.mode || "hide" ),
11513 hide = mode === "hide",
11514 percent = parseInt( o.percent, 10 ) || 150,
11515 factor = percent / 100,
11516 original = {
11517 height: elem.height(),
11518 width: elem.width(),
11519 outerHeight: elem.outerHeight(),
11520 outerWidth: elem.outerWidth()
11521 };
11522
11523 $.extend( o, {
11524 effect: "scale",
11525 queue: false,
11526 fade: true,
11527 mode: mode,
11528 complete: done,
11529 percent: hide ? percent : 100,
11530 from: hide ?
11531 original :
11532 {
11533 height: original.height * factor,
11534 width: original.width * factor,
11535 outerHeight: original.outerHeight * factor,
11536 outerWidth: original.outerWidth * factor
11537 }
11538 });
11539
11540 elem.effect( o );
11541};
11542
11543
11544/*!
11545 * jQuery UI Effects Pulsate 1.11.2
11546 * http://jqueryui.com
11547 *
11548 * Copyright 2014 jQuery Foundation and other contributors
11549 * Released under the MIT license.
11550 * http://jquery.org/license
11551 *
11552 * http://api.jqueryui.com/pulsate-effect/
11553 */
11554
11555
11556var effectPulsate = $.effects.effect.pulsate = function( o, done ) {
11557 var elem = $( this ),
11558 mode = $.effects.setMode( elem, o.mode || "show" ),
11559 show = mode === "show",
11560 hide = mode === "hide",
11561 showhide = ( show || mode === "hide" ),
11562
11563 // showing or hiding leaves of the "last" animation
11564 anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
11565 duration = o.duration / anims,
11566 animateTo = 0,
11567 queue = elem.queue(),
11568 queuelen = queue.length,
11569 i;
11570
11571 if ( show || !elem.is(":visible")) {
11572 elem.css( "opacity", 0 ).show();
11573 animateTo = 1;
11574 }
11575
11576 // anims - 1 opacity "toggles"
11577 for ( i = 1; i < anims; i++ ) {
11578 elem.animate({
11579 opacity: animateTo
11580 }, duration, o.easing );
11581 animateTo = 1 - animateTo;
11582 }
11583
11584 elem.animate({
11585 opacity: animateTo
11586 }, duration, o.easing);
11587
11588 elem.queue(function() {
11589 if ( hide ) {
11590 elem.hide();
11591 }
11592 done();
11593 });
11594
11595 // We just queued up "anims" animations, we need to put them next in the queue
11596 if ( queuelen > 1 ) {
11597 queue.splice.apply( queue,
11598 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
11599 }
11600 elem.dequeue();
11601};
11602
11603
11604/*!
11605 * jQuery UI Effects Shake 1.11.2
11606 * http://jqueryui.com
11607 *
11608 * Copyright 2014 jQuery Foundation and other contributors
11609 * Released under the MIT license.
11610 * http://jquery.org/license
11611 *
11612 * http://api.jqueryui.com/shake-effect/
11613 */
11614
11615
11616var effectShake = $.effects.effect.shake = function( o, done ) {
11617
11618 var el = $( this ),
11619 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
11620 mode = $.effects.setMode( el, o.mode || "effect" ),
11621 direction = o.direction || "left",
11622 distance = o.distance || 20,
11623 times = o.times || 3,
11624 anims = times * 2 + 1,
11625 speed = Math.round( o.duration / anims ),
11626 ref = (direction === "up" || direction === "down") ? "top" : "left",
11627 positiveMotion = (direction === "up" || direction === "left"),
11628 animation = {},
11629 animation1 = {},
11630 animation2 = {},
11631 i,
11632
11633 // we will need to re-assemble the queue to stack our animations in place
11634 queue = el.queue(),
11635 queuelen = queue.length;
11636
11637 $.effects.save( el, props );
11638 el.show();
11639 $.effects.createWrapper( el );
11640
11641 // Animation
11642 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
11643 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
11644 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
11645
11646 // Animate
11647 el.animate( animation, speed, o.easing );
11648
11649 // Shakes
11650 for ( i = 1; i < times; i++ ) {
11651 el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
11652 }
11653 el
11654 .animate( animation1, speed, o.easing )
11655 .animate( animation, speed / 2, o.easing )
11656 .queue(function() {
11657 if ( mode === "hide" ) {
11658 el.hide();
11659 }
11660 $.effects.restore( el, props );
11661 $.effects.removeWrapper( el );
11662 done();
11663 });
11664
11665 // inject all the animations we just queued to be first in line (after "inprogress")
11666 if ( queuelen > 1) {
11667 queue.splice.apply( queue,
11668 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
11669 }
11670 el.dequeue();
11671
11672};
11673
11674
11675/*!
11676 * jQuery UI Effects Slide 1.11.2
11677 * http://jqueryui.com
11678 *
11679 * Copyright 2014 jQuery Foundation and other contributors
11680 * Released under the MIT license.
11681 * http://jquery.org/license
11682 *
11683 * http://api.jqueryui.com/slide-effect/
11684 */
11685
11686
11687var effectSlide = $.effects.effect.slide = function( o, done ) {
11688
11689 // Create element
11690 var el = $( this ),
11691 props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
11692 mode = $.effects.setMode( el, o.mode || "show" ),
11693 show = mode === "show",
11694 direction = o.direction || "left",
11695 ref = (direction === "up" || direction === "down") ? "top" : "left",
11696 positiveMotion = (direction === "up" || direction === "left"),
11697 distance,
11698 animation = {};
11699
11700 // Adjust
11701 $.effects.save( el, props );
11702 el.show();
11703 distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
11704
11705 $.effects.createWrapper( el ).css({
11706 overflow: "hidden"
11707 });
11708
11709 if ( show ) {
11710 el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
11711 }
11712
11713 // Animation
11714 animation[ ref ] = ( show ?
11715 ( positiveMotion ? "+=" : "-=") :
11716 ( positiveMotion ? "-=" : "+=")) +
11717 distance;
11718
11719 // Animate
11720 el.animate( animation, {
11721 queue: false,
11722 duration: o.duration,
11723 easing: o.easing,
11724 complete: function() {
11725 if ( mode === "hide" ) {
11726 el.hide();
11727 }
11728 $.effects.restore( el, props );
11729 $.effects.removeWrapper( el );
11730 done();
11731 }
11732 });
11733};
11734
11735
11736/*!
11737 * jQuery UI Effects Transfer 1.11.2
11738 * http://jqueryui.com
11739 *
11740 * Copyright 2014 jQuery Foundation and other contributors
11741 * Released under the MIT license.
11742 * http://jquery.org/license
11743 *
11744 * http://api.jqueryui.com/transfer-effect/
11745 */
11746
11747
11748var effectTransfer = $.effects.effect.transfer = function( o, done ) {
11749 var elem = $( this ),
11750 target = $( o.to ),
11751 targetFixed = target.css( "position" ) === "fixed",
11752 body = $("body"),
11753 fixTop = targetFixed ? body.scrollTop() : 0,
11754 fixLeft = targetFixed ? body.scrollLeft() : 0,
11755 endPosition = target.offset(),
11756 animation = {
11757 top: endPosition.top - fixTop,
11758 left: endPosition.left - fixLeft,
11759 height: target.innerHeight(),
11760 width: target.innerWidth()
11761 },
11762 startPosition = elem.offset(),
11763 transfer = $( "<div class='ui-effects-transfer'></div>" )
11764 .appendTo( document.body )
11765 .addClass( o.className )
11766 .css({
11767 top: startPosition.top - fixTop,
11768 left: startPosition.left - fixLeft,
11769 height: elem.innerHeight(),
11770 width: elem.innerWidth(),
11771 position: targetFixed ? "fixed" : "absolute"
11772 })
11773 .animate( animation, o.duration, o.easing, function() {
11774 transfer.remove();
11775 done();
11776 });
11777};
11778
11779
11780/*!
11781 * jQuery UI Progressbar 1.11.2
11782 * http://jqueryui.com
11783 *
11784 * Copyright 2014 jQuery Foundation and other contributors
11785 * Released under the MIT license.
11786 * http://jquery.org/license
11787 *
11788 * http://api.jqueryui.com/progressbar/
11789 */
11790
11791
11792var progressbar = $.widget( "ui.progressbar", {
11793 version: "1.11.2",
11794 options: {
11795 max: 100,
11796 value: 0,
11797
11798 change: null,
11799 complete: null
11800 },
11801
11802 min: 0,
11803
11804 _create: function() {
11805 // Constrain initial value
11806 this.oldValue = this.options.value = this._constrainedValue();
11807
11808 this.element
11809 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
11810 .attr({
11811 // Only set static values, aria-valuenow and aria-valuemax are
11812 // set inside _refreshValue()
11813 role: "progressbar",
11814 "aria-valuemin": this.min
11815 });
11816
11817 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
11818 .appendTo( this.element );
11819
11820 this._refreshValue();
11821 },
11822
11823 _destroy: function() {
11824 this.element
11825 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
11826 .removeAttr( "role" )
11827 .removeAttr( "aria-valuemin" )
11828 .removeAttr( "aria-valuemax" )
11829 .removeAttr( "aria-valuenow" );
11830
11831 this.valueDiv.remove();
11832 },
11833
11834 value: function( newValue ) {
11835 if ( newValue === undefined ) {
11836 return this.options.value;
11837 }
11838
11839 this.options.value = this._constrainedValue( newValue );
11840 this._refreshValue();
11841 },
11842
11843 _constrainedValue: function( newValue ) {
11844 if ( newValue === undefined ) {
11845 newValue = this.options.value;
11846 }
11847
11848 this.indeterminate = newValue === false;
11849
11850 // sanitize value
11851 if ( typeof newValue !== "number" ) {
11852 newValue = 0;
11853 }
11854
11855 return this.indeterminate ? false :
11856 Math.min( this.options.max, Math.max( this.min, newValue ) );
11857 },
11858
11859 _setOptions: function( options ) {
11860 // Ensure "value" option is set after other values (like max)
11861 var value = options.value;
11862 delete options.value;
11863
11864 this._super( options );
11865
11866 this.options.value = this._constrainedValue( value );
11867 this._refreshValue();
11868 },
11869
11870 _setOption: function( key, value ) {
11871 if ( key === "max" ) {
11872 // Don't allow a max less than min
11873 value = Math.max( this.min, value );
11874 }
11875 if ( key === "disabled" ) {
11876 this.element
11877 .toggleClass( "ui-state-disabled", !!value )
11878 .attr( "aria-disabled", value );
11879 }
11880 this._super( key, value );
11881 },
11882
11883 _percentage: function() {
11884 return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
11885 },
11886
11887 _refreshValue: function() {
11888 var value = this.options.value,
11889 percentage = this._percentage();
11890
11891 this.valueDiv
11892 .toggle( this.indeterminate || value > this.min )
11893 .toggleClass( "ui-corner-right", value === this.options.max )
11894 .width( percentage.toFixed(0) + "%" );
11895
11896 this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate );
11897
11898 if ( this.indeterminate ) {
11899 this.element.removeAttr( "aria-valuenow" );
11900 if ( !this.overlayDiv ) {
11901 this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv );
11902 }
11903 } else {
11904 this.element.attr({
11905 "aria-valuemax": this.options.max,
11906 "aria-valuenow": value
11907 });
11908 if ( this.overlayDiv ) {
11909 this.overlayDiv.remove();
11910 this.overlayDiv = null;
11911 }
11912 }
11913
11914 if ( this.oldValue !== value ) {
11915 this.oldValue = value;
11916 this._trigger( "change" );
11917 }
11918 if ( value === this.options.max ) {
11919 this._trigger( "complete" );
11920 }
11921 }
11922});
11923
11924
11925/*!
11926 * jQuery UI Selectable 1.11.2
11927 * http://jqueryui.com
11928 *
11929 * Copyright 2014 jQuery Foundation and other contributors
11930 * Released under the MIT license.
11931 * http://jquery.org/license
11932 *
11933 * http://api.jqueryui.com/selectable/
11934 */
11935
11936
11937var selectable = $.widget("ui.selectable", $.ui.mouse, {
11938 version: "1.11.2",
11939 options: {
11940 appendTo: "body",
11941 autoRefresh: true,
11942 distance: 0,
11943 filter: "*",
11944 tolerance: "touch",
11945
11946 // callbacks
11947 selected: null,
11948 selecting: null,
11949 start: null,
11950 stop: null,
11951 unselected: null,
11952 unselecting: null
11953 },
11954 _create: function() {
11955 var selectees,
11956 that = this;
11957
11958 this.element.addClass("ui-selectable");
11959
11960 this.dragged = false;
11961
11962 // cache selectee children based on filter
11963 this.refresh = function() {
11964 selectees = $(that.options.filter, that.element[0]);
11965 selectees.addClass("ui-selectee");
11966 selectees.each(function() {
11967 var $this = $(this),
11968 pos = $this.offset();
11969 $.data(this, "selectable-item", {
11970 element: this,
11971 $element: $this,
11972 left: pos.left,
11973 top: pos.top,
11974 right: pos.left + $this.outerWidth(),
11975 bottom: pos.top + $this.outerHeight(),
11976 startselected: false,
11977 selected: $this.hasClass("ui-selected"),
11978 selecting: $this.hasClass("ui-selecting"),
11979 unselecting: $this.hasClass("ui-unselecting")
11980 });
11981 });
11982 };
11983 this.refresh();
11984
11985 this.selectees = selectees.addClass("ui-selectee");
11986
11987 this._mouseInit();
11988
11989 this.helper = $("<div class='ui-selectable-helper'></div>");
11990 },
11991
11992 _destroy: function() {
11993 this.selectees
11994 .removeClass("ui-selectee")
11995 .removeData("selectable-item");
11996 this.element
11997 .removeClass("ui-selectable ui-selectable-disabled");
11998 this._mouseDestroy();
11999 },
12000
12001 _mouseStart: function(event) {
12002 var that = this,
12003 options = this.options;
12004
12005 this.opos = [ event.pageX, event.pageY ];
12006
12007 if (this.options.disabled) {
12008 return;
12009 }
12010
12011 this.selectees = $(options.filter, this.element[0]);
12012
12013 this._trigger("start", event);
12014
12015 $(options.appendTo).append(this.helper);
12016 // position helper (lasso)
12017 this.helper.css({
12018 "left": event.pageX,
12019 "top": event.pageY,
12020 "width": 0,
12021 "height": 0
12022 });
12023
12024 if (options.autoRefresh) {
12025 this.refresh();
12026 }
12027
12028 this.selectees.filter(".ui-selected").each(function() {
12029 var selectee = $.data(this, "selectable-item");
12030 selectee.startselected = true;
12031 if (!event.metaKey && !event.ctrlKey) {
12032 selectee.$element.removeClass("ui-selected");
12033 selectee.selected = false;
12034 selectee.$element.addClass("ui-unselecting");
12035 selectee.unselecting = true;
12036 // selectable UNSELECTING callback
12037 that._trigger("unselecting", event, {
12038 unselecting: selectee.element
12039 });
12040 }
12041 });
12042
12043 $(event.target).parents().addBack().each(function() {
12044 var doSelect,
12045 selectee = $.data(this, "selectable-item");
12046 if (selectee) {
12047 doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");
12048 selectee.$element
12049 .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
12050 .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
12051 selectee.unselecting = !doSelect;
12052 selectee.selecting = doSelect;
12053 selectee.selected = doSelect;
12054 // selectable (UN)SELECTING callback
12055 if (doSelect) {
12056 that._trigger("selecting", event, {
12057 selecting: selectee.element
12058 });
12059 } else {
12060 that._trigger("unselecting", event, {
12061 unselecting: selectee.element
12062 });
12063 }
12064 return false;
12065 }
12066 });
12067
12068 },
12069
12070 _mouseDrag: function(event) {
12071
12072 this.dragged = true;
12073
12074 if (this.options.disabled) {
12075 return;
12076 }
12077
12078 var tmp,
12079 that = this,
12080 options = this.options,
12081 x1 = this.opos[0],
12082 y1 = this.opos[1],
12083 x2 = event.pageX,
12084 y2 = event.pageY;
12085
12086 if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
12087 if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
12088 this.helper.css({ left: x1, top: y1, width: x2 - x1, height: y2 - y1 });
12089
12090 this.selectees.each(function() {
12091 var selectee = $.data(this, "selectable-item"),
12092 hit = false;
12093
12094 //prevent helper from being selected if appendTo: selectable
12095 if (!selectee || selectee.element === that.element[0]) {
12096 return;
12097 }
12098
12099 if (options.tolerance === "touch") {
12100 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
12101 } else if (options.tolerance === "fit") {
12102 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
12103 }
12104
12105 if (hit) {
12106 // SELECT
12107 if (selectee.selected) {
12108 selectee.$element.removeClass("ui-selected");
12109 selectee.selected = false;
12110 }
12111 if (selectee.unselecting) {
12112 selectee.$element.removeClass("ui-unselecting");
12113 selectee.unselecting = false;
12114 }
12115 if (!selectee.selecting) {
12116 selectee.$element.addClass("ui-selecting");
12117 selectee.selecting = true;
12118 // selectable SELECTING callback
12119 that._trigger("selecting", event, {
12120 selecting: selectee.element
12121 });
12122 }
12123 } else {
12124 // UNSELECT
12125 if (selectee.selecting) {
12126 if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
12127 selectee.$element.removeClass("ui-selecting");
12128 selectee.selecting = false;
12129 selectee.$element.addClass("ui-selected");
12130 selectee.selected = true;
12131 } else {
12132 selectee.$element.removeClass("ui-selecting");
12133 selectee.selecting = false;
12134 if (selectee.startselected) {
12135 selectee.$element.addClass("ui-unselecting");
12136 selectee.unselecting = true;
12137 }
12138 // selectable UNSELECTING callback
12139 that._trigger("unselecting", event, {
12140 unselecting: selectee.element
12141 });
12142 }
12143 }
12144 if (selectee.selected) {
12145 if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
12146 selectee.$element.removeClass("ui-selected");
12147 selectee.selected = false;
12148
12149 selectee.$element.addClass("ui-unselecting");
12150 selectee.unselecting = true;
12151 // selectable UNSELECTING callback
12152 that._trigger("unselecting", event, {
12153 unselecting: selectee.element
12154 });
12155 }
12156 }
12157 }
12158 });
12159
12160 return false;
12161 },
12162
12163 _mouseStop: function(event) {
12164 var that = this;
12165
12166 this.dragged = false;
12167
12168 $(".ui-unselecting", this.element[0]).each(function() {
12169 var selectee = $.data(this, "selectable-item");
12170 selectee.$element.removeClass("ui-unselecting");
12171 selectee.unselecting = false;
12172 selectee.startselected = false;
12173 that._trigger("unselected", event, {
12174 unselected: selectee.element
12175 });
12176 });
12177 $(".ui-selecting", this.element[0]).each(function() {
12178 var selectee = $.data(this, "selectable-item");
12179 selectee.$element.removeClass("ui-selecting").addClass("ui-selected");
12180 selectee.selecting = false;
12181 selectee.selected = true;
12182 selectee.startselected = true;
12183 that._trigger("selected", event, {
12184 selected: selectee.element
12185 });
12186 });
12187 this._trigger("stop", event);
12188
12189 this.helper.remove();
12190
12191 return false;
12192 }
12193
12194});
12195
12196
12197/*!
12198 * jQuery UI Selectmenu 1.11.2
12199 * http://jqueryui.com
12200 *
12201 * Copyright 2014 jQuery Foundation and other contributors
12202 * Released under the MIT license.
12203 * http://jquery.org/license
12204 *
12205 * http://api.jqueryui.com/selectmenu
12206 */
12207
12208
12209var selectmenu = $.widget( "ui.selectmenu", {
12210 version: "1.11.2",
12211 defaultElement: "<select>",
12212 options: {
12213 appendTo: null,
12214 disabled: null,
12215 icons: {
12216 button: "ui-icon-triangle-1-s"
12217 },
12218 position: {
12219 my: "left top",
12220 at: "left bottom",
12221 collision: "none"
12222 },
12223 width: null,
12224
12225 // callbacks
12226 change: null,
12227 close: null,
12228 focus: null,
12229 open: null,
12230 select: null
12231 },
12232
12233 _create: function() {
12234 var selectmenuId = this.element.uniqueId().attr( "id" );
12235 this.ids = {
12236 element: selectmenuId,
12237 button: selectmenuId + "-button",
12238 menu: selectmenuId + "-menu"
12239 };
12240
12241 this._drawButton();
12242 this._drawMenu();
12243
12244 if ( this.options.disabled ) {
12245 this.disable();
12246 }
12247 },
12248
12249 _drawButton: function() {
12250 var that = this,
12251 tabindex = this.element.attr( "tabindex" );
12252
12253 // Associate existing label with the new button
12254 this.label = $( "label[for='" + this.ids.element + "']" ).attr( "for", this.ids.button );
12255 this._on( this.label, {
12256 click: function( event ) {
12257 this.button.focus();
12258 event.preventDefault();
12259 }
12260 });
12261
12262 // Hide original select element
12263 this.element.hide();
12264
12265 // Create button
12266 this.button = $( "<span>", {
12267 "class": "ui-selectmenu-button ui-widget ui-state-default ui-corner-all",
12268 tabindex: tabindex || this.options.disabled ? -1 : 0,
12269 id: this.ids.button,
12270 role: "combobox",
12271 "aria-expanded": "false",
12272 "aria-autocomplete": "list",
12273 "aria-owns": this.ids.menu,
12274 "aria-haspopup": "true"
12275 })
12276 .insertAfter( this.element );
12277
12278 $( "<span>", {
12279 "class": "ui-icon " + this.options.icons.button
12280 })
12281 .prependTo( this.button );
12282
12283 this.buttonText = $( "<span>", {
12284 "class": "ui-selectmenu-text"
12285 })
12286 .appendTo( this.button );
12287
12288 this._setText( this.buttonText, this.element.find( "option:selected" ).text() );
12289 this._resizeButton();
12290
12291 this._on( this.button, this._buttonEvents );
12292 this.button.one( "focusin", function() {
12293
12294 // Delay rendering the menu items until the button receives focus.
12295 // The menu may have already been rendered via a programmatic open.
12296 if ( !that.menuItems ) {
12297 that._refreshMenu();
12298 }
12299 });
12300 this._hoverable( this.button );
12301 this._focusable( this.button );
12302 },
12303
12304 _drawMenu: function() {
12305 var that = this;
12306
12307 // Create menu
12308 this.menu = $( "<ul>", {
12309 "aria-hidden": "true",
12310 "aria-labelledby": this.ids.button,
12311 id: this.ids.menu
12312 });
12313
12314 // Wrap menu
12315 this.menuWrap = $( "<div>", {
12316 "class": "ui-selectmenu-menu ui-front"
12317 })
12318 .append( this.menu )
12319 .appendTo( this._appendTo() );
12320
12321 // Initialize menu widget
12322 this.menuInstance = this.menu
12323 .menu({
12324 role: "listbox",
12325 select: function( event, ui ) {
12326 event.preventDefault();
12327
12328 // support: IE8
12329 // If the item was selected via a click, the text selection
12330 // will be destroyed in IE
12331 that._setSelection();
12332
12333 that._select( ui.item.data( "ui-selectmenu-item" ), event );
12334 },
12335 focus: function( event, ui ) {
12336 var item = ui.item.data( "ui-selectmenu-item" );
12337
12338 // Prevent inital focus from firing and check if its a newly focused item
12339 if ( that.focusIndex != null && item.index !== that.focusIndex ) {
12340 that._trigger( "focus", event, { item: item } );
12341 if ( !that.isOpen ) {
12342 that._select( item, event );
12343 }
12344 }
12345 that.focusIndex = item.index;
12346
12347 that.button.attr( "aria-activedescendant",
12348 that.menuItems.eq( item.index ).attr( "id" ) );
12349 }
12350 })
12351 .menu( "instance" );
12352
12353 // Adjust menu styles to dropdown
12354 this.menu
12355 .addClass( "ui-corner-bottom" )
12356 .removeClass( "ui-corner-all" );
12357
12358 // Don't close the menu on mouseleave
12359 this.menuInstance._off( this.menu, "mouseleave" );
12360
12361 // Cancel the menu's collapseAll on document click
12362 this.menuInstance._closeOnDocumentClick = function() {
12363 return false;
12364 };
12365
12366 // Selects often contain empty items, but never contain dividers
12367 this.menuInstance._isDivider = function() {
12368 return false;
12369 };
12370 },
12371
12372 refresh: function() {
12373 this._refreshMenu();
12374 this._setText( this.buttonText, this._getSelectedItem().text() );
12375 if ( !this.options.width ) {
12376 this._resizeButton();
12377 }
12378 },
12379
12380 _refreshMenu: function() {
12381 this.menu.empty();
12382
12383 var item,
12384 options = this.element.find( "option" );
12385
12386 if ( !options.length ) {
12387 return;
12388 }
12389
12390 this._parseOptions( options );
12391 this._renderMenu( this.menu, this.items );
12392
12393 this.menuInstance.refresh();
12394 this.menuItems = this.menu.find( "li" ).not( ".ui-selectmenu-optgroup" );
12395
12396 item = this._getSelectedItem();
12397
12398 // Update the menu to have the correct item focused
12399 this.menuInstance.focus( null, item );
12400 this._setAria( item.data( "ui-selectmenu-item" ) );
12401
12402 // Set disabled state
12403 this._setOption( "disabled", this.element.prop( "disabled" ) );
12404 },
12405
12406 open: function( event ) {
12407 if ( this.options.disabled ) {
12408 return;
12409 }
12410
12411 // If this is the first time the menu is being opened, render the items
12412 if ( !this.menuItems ) {
12413 this._refreshMenu();
12414 } else {
12415
12416 // Menu clears focus on close, reset focus to selected item
12417 this.menu.find( ".ui-state-focus" ).removeClass( "ui-state-focus" );
12418 this.menuInstance.focus( null, this._getSelectedItem() );
12419 }
12420
12421 this.isOpen = true;
12422 this._toggleAttr();
12423 this._resizeMenu();
12424 this._position();
12425
12426 this._on( this.document, this._documentClick );
12427
12428 this._trigger( "open", event );
12429 },
12430
12431 _position: function() {
12432 this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
12433 },
12434
12435 close: function( event ) {
12436 if ( !this.isOpen ) {
12437 return;
12438 }
12439
12440 this.isOpen = false;
12441 this._toggleAttr();
12442
12443 this.range = null;
12444 this._off( this.document );
12445
12446 this._trigger( "close", event );
12447 },
12448
12449 widget: function() {
12450 return this.button;
12451 },
12452
12453 menuWidget: function() {
12454 return this.menu;
12455 },
12456
12457 _renderMenu: function( ul, items ) {
12458 var that = this,
12459 currentOptgroup = "";
12460
12461 $.each( items, function( index, item ) {
12462 if ( item.optgroup !== currentOptgroup ) {
12463 $( "<li>", {
12464 "class": "ui-selectmenu-optgroup ui-menu-divider" +
12465 ( item.element.parent( "optgroup" ).prop( "disabled" ) ?
12466 " ui-state-disabled" :
12467 "" ),
12468 text: item.optgroup
12469 })
12470 .appendTo( ul );
12471
12472 currentOptgroup = item.optgroup;
12473 }
12474
12475 that._renderItemData( ul, item );
12476 });
12477 },
12478
12479 _renderItemData: function( ul, item ) {
12480 return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
12481 },
12482
12483 _renderItem: function( ul, item ) {
12484 var li = $( "<li>" );
12485
12486 if ( item.disabled ) {
12487 li.addClass( "ui-state-disabled" );
12488 }
12489 this._setText( li, item.label );
12490
12491 return li.appendTo( ul );
12492 },
12493
12494 _setText: function( element, value ) {
12495 if ( value ) {
12496 element.text( value );
12497 } else {
12498 element.html( "&#160;" );
12499 }
12500 },
12501
12502 _move: function( direction, event ) {
12503 var item, next,
12504 filter = ".ui-menu-item";
12505
12506 if ( this.isOpen ) {
12507 item = this.menuItems.eq( this.focusIndex );
12508 } else {
12509 item = this.menuItems.eq( this.element[ 0 ].selectedIndex );
12510 filter += ":not(.ui-state-disabled)";
12511 }
12512
12513 if ( direction === "first" || direction === "last" ) {
12514 next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
12515 } else {
12516 next = item[ direction + "All" ]( filter ).eq( 0 );
12517 }
12518
12519 if ( next.length ) {
12520 this.menuInstance.focus( event, next );
12521 }
12522 },
12523
12524 _getSelectedItem: function() {
12525 return this.menuItems.eq( this.element[ 0 ].selectedIndex );
12526 },
12527
12528 _toggle: function( event ) {
12529 this[ this.isOpen ? "close" : "open" ]( event );
12530 },
12531
12532 _setSelection: function() {
12533 var selection;
12534
12535 if ( !this.range ) {
12536 return;
12537 }
12538
12539 if ( window.getSelection ) {
12540 selection = window.getSelection();
12541 selection.removeAllRanges();
12542 selection.addRange( this.range );
12543
12544 // support: IE8
12545 } else {
12546 this.range.select();
12547 }
12548
12549 // support: IE
12550 // Setting the text selection kills the button focus in IE, but
12551 // restoring the focus doesn't kill the selection.
12552 this.button.focus();
12553 },
12554
12555 _documentClick: {
12556 mousedown: function( event ) {
12557 if ( !this.isOpen ) {
12558 return;
12559 }
12560
12561 if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + this.ids.button ).length ) {
12562 this.close( event );
12563 }
12564 }
12565 },
12566
12567 _buttonEvents: {
12568
12569 // Prevent text selection from being reset when interacting with the selectmenu (#10144)
12570 mousedown: function() {
12571 var selection;
12572
12573 if ( window.getSelection ) {
12574 selection = window.getSelection();
12575 if ( selection.rangeCount ) {
12576 this.range = selection.getRangeAt( 0 );
12577 }
12578
12579 // support: IE8
12580 } else {
12581 this.range = document.selection.createRange();
12582 }
12583 },
12584
12585 click: function( event ) {
12586 this._setSelection();
12587 this._toggle( event );
12588 },
12589
12590 keydown: function( event ) {
12591 var preventDefault = true;
12592 switch ( event.keyCode ) {
12593 case $.ui.keyCode.TAB:
12594 case $.ui.keyCode.ESCAPE:
12595 this.close( event );
12596 preventDefault = false;
12597 break;
12598 case $.ui.keyCode.ENTER:
12599 if ( this.isOpen ) {
12600 this._selectFocusedItem( event );
12601 }
12602 break;
12603 case $.ui.keyCode.UP:
12604 if ( event.altKey ) {
12605 this._toggle( event );
12606 } else {
12607 this._move( "prev", event );
12608 }
12609 break;
12610 case $.ui.keyCode.DOWN:
12611 if ( event.altKey ) {
12612 this._toggle( event );
12613 } else {
12614 this._move( "next", event );
12615 }
12616 break;
12617 case $.ui.keyCode.SPACE:
12618 if ( this.isOpen ) {
12619 this._selectFocusedItem( event );
12620 } else {
12621 this._toggle( event );
12622 }
12623 break;
12624 case $.ui.keyCode.LEFT:
12625 this._move( "prev", event );
12626 break;
12627 case $.ui.keyCode.RIGHT:
12628 this._move( "next", event );
12629 break;
12630 case $.ui.keyCode.HOME:
12631 case $.ui.keyCode.PAGE_UP:
12632 this._move( "first", event );
12633 break;
12634 case $.ui.keyCode.END:
12635 case $.ui.keyCode.PAGE_DOWN:
12636 this._move( "last", event );
12637 break;
12638 default:
12639 this.menu.trigger( event );
12640 preventDefault = false;
12641 }
12642
12643 if ( preventDefault ) {
12644 event.preventDefault();
12645 }
12646 }
12647 },
12648
12649 _selectFocusedItem: function( event ) {
12650 var item = this.menuItems.eq( this.focusIndex );
12651 if ( !item.hasClass( "ui-state-disabled" ) ) {
12652 this._select( item.data( "ui-selectmenu-item" ), event );
12653 }
12654 },
12655
12656 _select: function( item, event ) {
12657 var oldIndex = this.element[ 0 ].selectedIndex;
12658
12659 // Change native select element
12660 this.element[ 0 ].selectedIndex = item.index;
12661 this._setText( this.buttonText, item.label );
12662 this._setAria( item );
12663 this._trigger( "select", event, { item: item } );
12664
12665 if ( item.index !== oldIndex ) {
12666 this._trigger( "change", event, { item: item } );
12667 }
12668
12669 this.close( event );
12670 },
12671
12672 _setAria: function( item ) {
12673 var id = this.menuItems.eq( item.index ).attr( "id" );
12674
12675 this.button.attr({
12676 "aria-labelledby": id,
12677 "aria-activedescendant": id
12678 });
12679 this.menu.attr( "aria-activedescendant", id );
12680 },
12681
12682 _setOption: function( key, value ) {
12683 if ( key === "icons" ) {
12684 this.button.find( "span.ui-icon" )
12685 .removeClass( this.options.icons.button )
12686 .addClass( value.button );
12687 }
12688
12689 this._super( key, value );
12690
12691 if ( key === "appendTo" ) {
12692 this.menuWrap.appendTo( this._appendTo() );
12693 }
12694
12695 if ( key === "disabled" ) {
12696 this.menuInstance.option( "disabled", value );
12697 this.button
12698 .toggleClass( "ui-state-disabled", value )
12699 .attr( "aria-disabled", value );
12700
12701 this.element.prop( "disabled", value );
12702 if ( value ) {
12703 this.button.attr( "tabindex", -1 );
12704 this.close();
12705 } else {
12706 this.button.attr( "tabindex", 0 );
12707 }
12708 }
12709
12710 if ( key === "width" ) {
12711 this._resizeButton();
12712 }
12713 },
12714
12715 _appendTo: function() {
12716 var element = this.options.appendTo;
12717
12718 if ( element ) {
12719 element = element.jquery || element.nodeType ?
12720 $( element ) :
12721 this.document.find( element ).eq( 0 );
12722 }
12723
12724 if ( !element || !element[ 0 ] ) {
12725 element = this.element.closest( ".ui-front" );
12726 }
12727
12728 if ( !element.length ) {
12729 element = this.document[ 0 ].body;
12730 }
12731
12732 return element;
12733 },
12734
12735 _toggleAttr: function() {
12736 this.button
12737 .toggleClass( "ui-corner-top", this.isOpen )
12738 .toggleClass( "ui-corner-all", !this.isOpen )
12739 .attr( "aria-expanded", this.isOpen );
12740 this.menuWrap.toggleClass( "ui-selectmenu-open", this.isOpen );
12741 this.menu.attr( "aria-hidden", !this.isOpen );
12742 },
12743
12744 _resizeButton: function() {
12745 var width = this.options.width;
12746
12747 if ( !width ) {
12748 width = this.element.show().outerWidth();
12749 this.element.hide();
12750 }
12751
12752 this.button.outerWidth( width );
12753 },
12754
12755 _resizeMenu: function() {
12756 this.menu.outerWidth( Math.max(
12757 this.button.outerWidth(),
12758
12759 // support: IE10
12760 // IE10 wraps long text (possibly a rounding bug)
12761 // so we add 1px to avoid the wrapping
12762 this.menu.width( "" ).outerWidth() + 1
12763 ) );
12764 },
12765
12766 _getCreateOptions: function() {
12767 return { disabled: this.element.prop( "disabled" ) };
12768 },
12769
12770 _parseOptions: function( options ) {
12771 var data = [];
12772 options.each(function( index, item ) {
12773 var option = $( item ),
12774 optgroup = option.parent( "optgroup" );
12775 data.push({
12776 element: option,
12777 index: index,
12778 value: option.attr( "value" ),
12779 label: option.text(),
12780 optgroup: optgroup.attr( "label" ) || "",
12781 disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
12782 });
12783 });
12784 this.items = data;
12785 },
12786
12787 _destroy: function() {
12788 this.menuWrap.remove();
12789 this.button.remove();
12790 this.element.show();
12791 this.element.removeUniqueId();
12792 this.label.attr( "for", this.ids.element );
12793 }
12794});
12795
12796
12797/*!
12798 * jQuery UI Slider 1.11.2
12799 * http://jqueryui.com
12800 *
12801 * Copyright 2014 jQuery Foundation and other contributors
12802 * Released under the MIT license.
12803 * http://jquery.org/license
12804 *
12805 * http://api.jqueryui.com/slider/
12806 */
12807
12808
12809var slider = $.widget( "ui.slider", $.ui.mouse, {
12810 version: "1.11.2",
12811 widgetEventPrefix: "slide",
12812
12813 options: {
12814 animate: false,
12815 distance: 0,
12816 max: 100,
12817 min: 0,
12818 orientation: "horizontal",
12819 range: false,
12820 step: 1,
12821 value: 0,
12822 values: null,
12823
12824 // callbacks
12825 change: null,
12826 slide: null,
12827 start: null,
12828 stop: null
12829 },
12830
12831 // number of pages in a slider
12832 // (how many times can you page up/down to go through the whole range)
12833 numPages: 5,
12834
12835 _create: function() {
12836 this._keySliding = false;
12837 this._mouseSliding = false;
12838 this._animateOff = true;
12839 this._handleIndex = null;
12840 this._detectOrientation();
12841 this._mouseInit();
12842 this._calculateNewMax();
12843
12844 this.element
12845 .addClass( "ui-slider" +
12846 " ui-slider-" + this.orientation +
12847 " ui-widget" +
12848 " ui-widget-content" +
12849 " ui-corner-all");
12850
12851 this._refresh();
12852 this._setOption( "disabled", this.options.disabled );
12853
12854 this._animateOff = false;
12855 },
12856
12857 _refresh: function() {
12858 this._createRange();
12859 this._createHandles();
12860 this._setupEvents();
12861 this._refreshValue();
12862 },
12863
12864 _createHandles: function() {
12865 var i, handleCount,
12866 options = this.options,
12867 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
12868 handle = "<span class='ui-slider-handle ui-state-default ui-corner-all' tabindex='0'></span>",
12869 handles = [];
12870
12871 handleCount = ( options.values && options.values.length ) || 1;
12872
12873 if ( existingHandles.length > handleCount ) {
12874 existingHandles.slice( handleCount ).remove();
12875 existingHandles = existingHandles.slice( 0, handleCount );
12876 }
12877
12878 for ( i = existingHandles.length; i < handleCount; i++ ) {
12879 handles.push( handle );
12880 }
12881
12882 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
12883
12884 this.handle = this.handles.eq( 0 );
12885
12886 this.handles.each(function( i ) {
12887 $( this ).data( "ui-slider-handle-index", i );
12888 });
12889 },
12890
12891 _createRange: function() {
12892 var options = this.options,
12893 classes = "";
12894
12895 if ( options.range ) {
12896 if ( options.range === true ) {
12897 if ( !options.values ) {
12898 options.values = [ this._valueMin(), this._valueMin() ];
12899 } else if ( options.values.length && options.values.length !== 2 ) {
12900 options.values = [ options.values[0], options.values[0] ];
12901 } else if ( $.isArray( options.values ) ) {
12902 options.values = options.values.slice(0);
12903 }
12904 }
12905
12906 if ( !this.range || !this.range.length ) {
12907 this.range = $( "<div></div>" )
12908 .appendTo( this.element );
12909
12910 classes = "ui-slider-range" +
12911 // note: this isn't the most fittingly semantic framework class for this element,
12912 // but worked best visually with a variety of themes
12913 " ui-widget-header ui-corner-all";
12914 } else {
12915 this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
12916 // Handle range switching from true to min/max
12917 .css({
12918 "left": "",
12919 "bottom": ""
12920 });
12921 }
12922
12923 this.range.addClass( classes +
12924 ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
12925 } else {
12926 if ( this.range ) {
12927 this.range.remove();
12928 }
12929 this.range = null;
12930 }
12931 },
12932
12933 _setupEvents: function() {
12934 this._off( this.handles );
12935 this._on( this.handles, this._handleEvents );
12936 this._hoverable( this.handles );
12937 this._focusable( this.handles );
12938 },
12939
12940 _destroy: function() {
12941 this.handles.remove();
12942 if ( this.range ) {
12943 this.range.remove();
12944 }
12945
12946 this.element
12947 .removeClass( "ui-slider" +
12948 " ui-slider-horizontal" +
12949 " ui-slider-vertical" +
12950 " ui-widget" +
12951 " ui-widget-content" +
12952 " ui-corner-all" );
12953
12954 this._mouseDestroy();
12955 },
12956
12957 _mouseCapture: function( event ) {
12958 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
12959 that = this,
12960 o = this.options;
12961
12962 if ( o.disabled ) {
12963 return false;
12964 }
12965
12966 this.elementSize = {
12967 width: this.element.outerWidth(),
12968 height: this.element.outerHeight()
12969 };
12970 this.elementOffset = this.element.offset();
12971
12972 position = { x: event.pageX, y: event.pageY };
12973 normValue = this._normValueFromMouse( position );
12974 distance = this._valueMax() - this._valueMin() + 1;
12975 this.handles.each(function( i ) {
12976 var thisDistance = Math.abs( normValue - that.values(i) );
12977 if (( distance > thisDistance ) ||
12978 ( distance === thisDistance &&
12979 (i === that._lastChangedValue || that.values(i) === o.min ))) {
12980 distance = thisDistance;
12981 closestHandle = $( this );
12982 index = i;
12983 }
12984 });
12985
12986 allowed = this._start( event, index );
12987 if ( allowed === false ) {
12988 return false;
12989 }
12990 this._mouseSliding = true;
12991
12992 this._handleIndex = index;
12993
12994 closestHandle
12995 .addClass( "ui-state-active" )
12996 .focus();
12997
12998 offset = closestHandle.offset();
12999 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
13000 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
13001 left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
13002 top: event.pageY - offset.top -
13003 ( closestHandle.height() / 2 ) -
13004 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
13005 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
13006 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
13007 };
13008
13009 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
13010 this._slide( event, index, normValue );
13011 }
13012 this._animateOff = true;
13013 return true;
13014 },
13015
13016 _mouseStart: function() {
13017 return true;
13018 },
13019
13020 _mouseDrag: function( event ) {
13021 var position = { x: event.pageX, y: event.pageY },
13022 normValue = this._normValueFromMouse( position );
13023
13024 this._slide( event, this._handleIndex, normValue );
13025
13026 return false;
13027 },
13028
13029 _mouseStop: function( event ) {
13030 this.handles.removeClass( "ui-state-active" );
13031 this._mouseSliding = false;
13032
13033 this._stop( event, this._handleIndex );
13034 this._change( event, this._handleIndex );
13035
13036 this._handleIndex = null;
13037 this._clickOffset = null;
13038 this._animateOff = false;
13039
13040 return false;
13041 },
13042
13043 _detectOrientation: function() {
13044 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
13045 },
13046
13047 _normValueFromMouse: function( position ) {
13048 var pixelTotal,
13049 pixelMouse,
13050 percentMouse,
13051 valueTotal,
13052 valueMouse;
13053
13054 if ( this.orientation === "horizontal" ) {
13055 pixelTotal = this.elementSize.width;
13056 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
13057 } else {
13058 pixelTotal = this.elementSize.height;
13059 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
13060 }
13061
13062 percentMouse = ( pixelMouse / pixelTotal );
13063 if ( percentMouse > 1 ) {
13064 percentMouse = 1;
13065 }
13066 if ( percentMouse < 0 ) {
13067 percentMouse = 0;
13068 }
13069 if ( this.orientation === "vertical" ) {
13070 percentMouse = 1 - percentMouse;
13071 }
13072
13073 valueTotal = this._valueMax() - this._valueMin();
13074 valueMouse = this._valueMin() + percentMouse * valueTotal;
13075
13076 return this._trimAlignValue( valueMouse );
13077 },
13078
13079 _start: function( event, index ) {
13080 var uiHash = {
13081 handle: this.handles[ index ],
13082 value: this.value()
13083 };
13084 if ( this.options.values && this.options.values.length ) {
13085 uiHash.value = this.values( index );
13086 uiHash.values = this.values();
13087 }
13088 return this._trigger( "start", event, uiHash );
13089 },
13090
13091 _slide: function( event, index, newVal ) {
13092 var otherVal,
13093 newValues,
13094 allowed;
13095
13096 if ( this.options.values && this.options.values.length ) {
13097 otherVal = this.values( index ? 0 : 1 );
13098
13099 if ( ( this.options.values.length === 2 && this.options.range === true ) &&
13100 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
13101 ) {
13102 newVal = otherVal;
13103 }
13104
13105 if ( newVal !== this.values( index ) ) {
13106 newValues = this.values();
13107 newValues[ index ] = newVal;
13108 // A slide can be canceled by returning false from the slide callback
13109 allowed = this._trigger( "slide", event, {
13110 handle: this.handles[ index ],
13111 value: newVal,
13112 values: newValues
13113 } );
13114 otherVal = this.values( index ? 0 : 1 );
13115 if ( allowed !== false ) {
13116 this.values( index, newVal );
13117 }
13118 }
13119 } else {
13120 if ( newVal !== this.value() ) {
13121 // A slide can be canceled by returning false from the slide callback
13122 allowed = this._trigger( "slide", event, {
13123 handle: this.handles[ index ],
13124 value: newVal
13125 } );
13126 if ( allowed !== false ) {
13127 this.value( newVal );
13128 }
13129 }
13130 }
13131 },
13132
13133 _stop: function( event, index ) {
13134 var uiHash = {
13135 handle: this.handles[ index ],
13136 value: this.value()
13137 };
13138 if ( this.options.values && this.options.values.length ) {
13139 uiHash.value = this.values( index );
13140 uiHash.values = this.values();
13141 }
13142
13143 this._trigger( "stop", event, uiHash );
13144 },
13145
13146 _change: function( event, index ) {
13147 if ( !this._keySliding && !this._mouseSliding ) {
13148 var uiHash = {
13149 handle: this.handles[ index ],
13150 value: this.value()
13151 };
13152 if ( this.options.values && this.options.values.length ) {
13153 uiHash.value = this.values( index );
13154 uiHash.values = this.values();
13155 }
13156
13157 //store the last changed value index for reference when handles overlap
13158 this._lastChangedValue = index;
13159
13160 this._trigger( "change", event, uiHash );
13161 }
13162 },
13163
13164 value: function( newValue ) {
13165 if ( arguments.length ) {
13166 this.options.value = this._trimAlignValue( newValue );
13167 this._refreshValue();
13168 this._change( null, 0 );
13169 return;
13170 }
13171
13172 return this._value();
13173 },
13174
13175 values: function( index, newValue ) {
13176 var vals,
13177 newValues,
13178 i;
13179
13180 if ( arguments.length > 1 ) {
13181 this.options.values[ index ] = this._trimAlignValue( newValue );
13182 this._refreshValue();
13183 this._change( null, index );
13184 return;
13185 }
13186
13187 if ( arguments.length ) {
13188 if ( $.isArray( arguments[ 0 ] ) ) {
13189 vals = this.options.values;
13190 newValues = arguments[ 0 ];
13191 for ( i = 0; i < vals.length; i += 1 ) {
13192 vals[ i ] = this._trimAlignValue( newValues[ i ] );
13193 this._change( null, i );
13194 }
13195 this._refreshValue();
13196 } else {
13197 if ( this.options.values && this.options.values.length ) {
13198 return this._values( index );
13199 } else {
13200 return this.value();
13201 }
13202 }
13203 } else {
13204 return this._values();
13205 }
13206 },
13207
13208 _setOption: function( key, value ) {
13209 var i,
13210 valsLength = 0;
13211
13212 if ( key === "range" && this.options.range === true ) {
13213 if ( value === "min" ) {
13214 this.options.value = this._values( 0 );
13215 this.options.values = null;
13216 } else if ( value === "max" ) {
13217 this.options.value = this._values( this.options.values.length - 1 );
13218 this.options.values = null;
13219 }
13220 }
13221
13222 if ( $.isArray( this.options.values ) ) {
13223 valsLength = this.options.values.length;
13224 }
13225
13226 if ( key === "disabled" ) {
13227 this.element.toggleClass( "ui-state-disabled", !!value );
13228 }
13229
13230 this._super( key, value );
13231
13232 switch ( key ) {
13233 case "orientation":
13234 this._detectOrientation();
13235 this.element
13236 .removeClass( "ui-slider-horizontal ui-slider-vertical" )
13237 .addClass( "ui-slider-" + this.orientation );
13238 this._refreshValue();
13239
13240 // Reset positioning from previous orientation
13241 this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
13242 break;
13243 case "value":
13244 this._animateOff = true;
13245 this._refreshValue();
13246 this._change( null, 0 );
13247 this._animateOff = false;
13248 break;
13249 case "values":
13250 this._animateOff = true;
13251 this._refreshValue();
13252 for ( i = 0; i < valsLength; i += 1 ) {
13253 this._change( null, i );
13254 }
13255 this._animateOff = false;
13256 break;
13257 case "step":
13258 case "min":
13259 case "max":
13260 this._animateOff = true;
13261 this._calculateNewMax();
13262 this._refreshValue();
13263 this._animateOff = false;
13264 break;
13265 case "range":
13266 this._animateOff = true;
13267 this._refresh();
13268 this._animateOff = false;
13269 break;
13270 }
13271 },
13272
13273 //internal value getter
13274 // _value() returns value trimmed by min and max, aligned by step
13275 _value: function() {
13276 var val = this.options.value;
13277 val = this._trimAlignValue( val );
13278
13279 return val;
13280 },
13281
13282 //internal values getter
13283 // _values() returns array of values trimmed by min and max, aligned by step
13284 // _values( index ) returns single value trimmed by min and max, aligned by step
13285 _values: function( index ) {
13286 var val,
13287 vals,
13288 i;
13289
13290 if ( arguments.length ) {
13291 val = this.options.values[ index ];
13292 val = this._trimAlignValue( val );
13293
13294 return val;
13295 } else if ( this.options.values && this.options.values.length ) {
13296 // .slice() creates a copy of the array
13297 // this copy gets trimmed by min and max and then returned
13298 vals = this.options.values.slice();
13299 for ( i = 0; i < vals.length; i += 1) {
13300 vals[ i ] = this._trimAlignValue( vals[ i ] );
13301 }
13302
13303 return vals;
13304 } else {
13305 return [];
13306 }
13307 },
13308
13309 // returns the step-aligned value that val is closest to, between (inclusive) min and max
13310 _trimAlignValue: function( val ) {
13311 if ( val <= this._valueMin() ) {
13312 return this._valueMin();
13313 }
13314 if ( val >= this._valueMax() ) {
13315 return this._valueMax();
13316 }
13317 var step = ( this.options.step > 0 ) ? this.options.step : 1,
13318 valModStep = (val - this._valueMin()) % step,
13319 alignValue = val - valModStep;
13320
13321 if ( Math.abs(valModStep) * 2 >= step ) {
13322 alignValue += ( valModStep > 0 ) ? step : ( -step );
13323 }
13324
13325 // Since JavaScript has problems with large floats, round
13326 // the final value to 5 digits after the decimal point (see #4124)
13327 return parseFloat( alignValue.toFixed(5) );
13328 },
13329
13330 _calculateNewMax: function() {
13331 var remainder = ( this.options.max - this._valueMin() ) % this.options.step;
13332 this.max = this.options.max - remainder;
13333 },
13334
13335 _valueMin: function() {
13336 return this.options.min;
13337 },
13338
13339 _valueMax: function() {
13340 return this.max;
13341 },
13342
13343 _refreshValue: function() {
13344 var lastValPercent, valPercent, value, valueMin, valueMax,
13345 oRange = this.options.range,
13346 o = this.options,
13347 that = this,
13348 animate = ( !this._animateOff ) ? o.animate : false,
13349 _set = {};
13350
13351 if ( this.options.values && this.options.values.length ) {
13352 this.handles.each(function( i ) {
13353 valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
13354 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
13355 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
13356 if ( that.options.range === true ) {
13357 if ( that.orientation === "horizontal" ) {
13358 if ( i === 0 ) {
13359 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
13360 }
13361 if ( i === 1 ) {
13362 that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
13363 }
13364 } else {
13365 if ( i === 0 ) {
13366 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
13367 }
13368 if ( i === 1 ) {
13369 that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
13370 }
13371 }
13372 }
13373 lastValPercent = valPercent;
13374 });
13375 } else {
13376 value = this.value();
13377 valueMin = this._valueMin();
13378 valueMax = this._valueMax();
13379 valPercent = ( valueMax !== valueMin ) ?
13380 ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
13381 0;
13382 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
13383 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
13384
13385 if ( oRange === "min" && this.orientation === "horizontal" ) {
13386 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
13387 }
13388 if ( oRange === "max" && this.orientation === "horizontal" ) {
13389 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
13390 }
13391 if ( oRange === "min" && this.orientation === "vertical" ) {
13392 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
13393 }
13394 if ( oRange === "max" && this.orientation === "vertical" ) {
13395 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
13396 }
13397 }
13398 },
13399
13400 _handleEvents: {
13401 keydown: function( event ) {
13402 var allowed, curVal, newVal, step,
13403 index = $( event.target ).data( "ui-slider-handle-index" );
13404
13405 switch ( event.keyCode ) {
13406 case $.ui.keyCode.HOME:
13407 case $.ui.keyCode.END:
13408 case $.ui.keyCode.PAGE_UP:
13409 case $.ui.keyCode.PAGE_DOWN:
13410 case $.ui.keyCode.UP:
13411 case $.ui.keyCode.RIGHT:
13412 case $.ui.keyCode.DOWN:
13413 case $.ui.keyCode.LEFT:
13414 event.preventDefault();
13415 if ( !this._keySliding ) {
13416 this._keySliding = true;
13417 $( event.target ).addClass( "ui-state-active" );
13418 allowed = this._start( event, index );
13419 if ( allowed === false ) {
13420 return;
13421 }
13422 }
13423 break;
13424 }
13425
13426 step = this.options.step;
13427 if ( this.options.values && this.options.values.length ) {
13428 curVal = newVal = this.values( index );
13429 } else {
13430 curVal = newVal = this.value();
13431 }
13432
13433 switch ( event.keyCode ) {
13434 case $.ui.keyCode.HOME:
13435 newVal = this._valueMin();
13436 break;
13437 case $.ui.keyCode.END:
13438 newVal = this._valueMax();
13439 break;
13440 case $.ui.keyCode.PAGE_UP:
13441 newVal = this._trimAlignValue(
13442 curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
13443 );
13444 break;
13445 case $.ui.keyCode.PAGE_DOWN:
13446 newVal = this._trimAlignValue(
13447 curVal - ( (this._valueMax() - this._valueMin()) / this.numPages ) );
13448 break;
13449 case $.ui.keyCode.UP:
13450 case $.ui.keyCode.RIGHT:
13451 if ( curVal === this._valueMax() ) {
13452 return;
13453 }
13454 newVal = this._trimAlignValue( curVal + step );
13455 break;
13456 case $.ui.keyCode.DOWN:
13457 case $.ui.keyCode.LEFT:
13458 if ( curVal === this._valueMin() ) {
13459 return;
13460 }
13461 newVal = this._trimAlignValue( curVal - step );
13462 break;
13463 }
13464
13465 this._slide( event, index, newVal );
13466 },
13467 keyup: function( event ) {
13468 var index = $( event.target ).data( "ui-slider-handle-index" );
13469
13470 if ( this._keySliding ) {
13471 this._keySliding = false;
13472 this._stop( event, index );
13473 this._change( event, index );
13474 $( event.target ).removeClass( "ui-state-active" );
13475 }
13476 }
13477 }
13478});
13479
13480
13481/*!
13482 * jQuery UI Sortable 1.11.2
13483 * http://jqueryui.com
13484 *
13485 * Copyright 2014 jQuery Foundation and other contributors
13486 * Released under the MIT license.
13487 * http://jquery.org/license
13488 *
13489 * http://api.jqueryui.com/sortable/
13490 */
13491
13492
13493var sortable = $.widget("ui.sortable", $.ui.mouse, {
13494 version: "1.11.2",
13495 widgetEventPrefix: "sort",
13496 ready: false,
13497 options: {
13498 appendTo: "parent",
13499 axis: false,
13500 connectWith: false,
13501 containment: false,
13502 cursor: "auto",
13503 cursorAt: false,
13504 dropOnEmpty: true,
13505 forcePlaceholderSize: false,
13506 forceHelperSize: false,
13507 grid: false,
13508 handle: false,
13509 helper: "original",
13510 items: "> *",
13511 opacity: false,
13512 placeholder: false,
13513 revert: false,
13514 scroll: true,
13515 scrollSensitivity: 20,
13516 scrollSpeed: 20,
13517 scope: "default",
13518 tolerance: "intersect",
13519 zIndex: 1000,
13520
13521 // callbacks
13522 activate: null,
13523 beforeStop: null,
13524 change: null,
13525 deactivate: null,
13526 out: null,
13527 over: null,
13528 receive: null,
13529 remove: null,
13530 sort: null,
13531 start: null,
13532 stop: null,
13533 update: null
13534 },
13535
13536 _isOverAxis: function( x, reference, size ) {
13537 return ( x >= reference ) && ( x < ( reference + size ) );
13538 },
13539
13540 _isFloating: function( item ) {
13541 return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display"));
13542 },
13543
13544 _create: function() {
13545
13546 var o = this.options;
13547 this.containerCache = {};
13548 this.element.addClass("ui-sortable");
13549
13550 //Get the items
13551 this.refresh();
13552
13553 //Let's determine if the items are being displayed horizontally
13554 this.floating = this.items.length ? o.axis === "x" || this._isFloating(this.items[0].item) : false;
13555
13556 //Let's determine the parent's offset
13557 this.offset = this.element.offset();
13558
13559 //Initialize mouse events for interaction
13560 this._mouseInit();
13561
13562 this._setHandleClassName();
13563
13564 //We're ready to go
13565 this.ready = true;
13566
13567 },
13568
13569 _setOption: function( key, value ) {
13570 this._super( key, value );
13571
13572 if ( key === "handle" ) {
13573 this._setHandleClassName();
13574 }
13575 },
13576
13577 _setHandleClassName: function() {
13578 this.element.find( ".ui-sortable-handle" ).removeClass( "ui-sortable-handle" );
13579 $.each( this.items, function() {
13580 ( this.instance.options.handle ?
13581 this.item.find( this.instance.options.handle ) : this.item )
13582 .addClass( "ui-sortable-handle" );
13583 });
13584 },
13585
13586 _destroy: function() {
13587 this.element
13588 .removeClass( "ui-sortable ui-sortable-disabled" )
13589 .find( ".ui-sortable-handle" )
13590 .removeClass( "ui-sortable-handle" );
13591 this._mouseDestroy();
13592
13593 for ( var i = this.items.length - 1; i >= 0; i-- ) {
13594 this.items[i].item.removeData(this.widgetName + "-item");
13595 }
13596
13597 return this;
13598 },
13599
13600 _mouseCapture: function(event, overrideHandle) {
13601 var currentItem = null,
13602 validHandle = false,
13603 that = this;
13604
13605 if (this.reverting) {
13606 return false;
13607 }
13608
13609 if(this.options.disabled || this.options.type === "static") {
13610 return false;
13611 }
13612
13613 //We have to refresh the items data once first
13614 this._refreshItems(event);
13615
13616 //Find out if the clicked node (or one of its parents) is a actual item in this.items
13617 $(event.target).parents().each(function() {
13618 if($.data(this, that.widgetName + "-item") === that) {
13619 currentItem = $(this);
13620 return false;
13621 }
13622 });
13623 if($.data(event.target, that.widgetName + "-item") === that) {
13624 currentItem = $(event.target);
13625 }
13626
13627 if(!currentItem) {
13628 return false;
13629 }
13630 if(this.options.handle && !overrideHandle) {
13631 $(this.options.handle, currentItem).find("*").addBack().each(function() {
13632 if(this === event.target) {
13633 validHandle = true;
13634 }
13635 });
13636 if(!validHandle) {
13637 return false;
13638 }
13639 }
13640
13641 this.currentItem = currentItem;
13642 this._removeCurrentsFromItems();
13643 return true;
13644
13645 },
13646
13647 _mouseStart: function(event, overrideHandle, noActivation) {
13648
13649 var i, body,
13650 o = this.options;
13651
13652 this.currentContainer = this;
13653
13654 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
13655 this.refreshPositions();
13656
13657 //Create and append the visible helper
13658 this.helper = this._createHelper(event);
13659
13660 //Cache the helper size
13661 this._cacheHelperProportions();
13662
13663 /*
13664 * - Position generation -
13665 * This block generates everything position related - it's the core of draggables.
13666 */
13667
13668 //Cache the margins of the original element
13669 this._cacheMargins();
13670
13671 //Get the next scrolling parent
13672 this.scrollParent = this.helper.scrollParent();
13673
13674 //The element's absolute position on the page minus margins
13675 this.offset = this.currentItem.offset();
13676 this.offset = {
13677 top: this.offset.top - this.margins.top,
13678 left: this.offset.left - this.margins.left
13679 };
13680
13681 $.extend(this.offset, {
13682 click: { //Where the click happened, relative to the element
13683 left: event.pageX - this.offset.left,
13684 top: event.pageY - this.offset.top
13685 },
13686 parent: this._getParentOffset(),
13687 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
13688 });
13689
13690 // Only after we got the offset, we can change the helper's position to absolute
13691 // TODO: Still need to figure out a way to make relative sorting possible
13692 this.helper.css("position", "absolute");
13693 this.cssPosition = this.helper.css("position");
13694
13695 //Generate the original position
13696 this.originalPosition = this._generatePosition(event);
13697 this.originalPageX = event.pageX;
13698 this.originalPageY = event.pageY;
13699
13700 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
13701 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
13702
13703 //Cache the former DOM position
13704 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
13705
13706 //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
13707 if(this.helper[0] !== this.currentItem[0]) {
13708 this.currentItem.hide();
13709 }
13710
13711 //Create the placeholder
13712 this._createPlaceholder();
13713
13714 //Set a containment if given in the options
13715 if(o.containment) {
13716 this._setContainment();
13717 }
13718
13719 if( o.cursor && o.cursor !== "auto" ) { // cursor option
13720 body = this.document.find( "body" );
13721
13722 // support: IE
13723 this.storedCursor = body.css( "cursor" );
13724 body.css( "cursor", o.cursor );
13725
13726 this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );
13727 }
13728
13729 if(o.opacity) { // opacity option
13730 if (this.helper.css("opacity")) {
13731 this._storedOpacity = this.helper.css("opacity");
13732 }
13733 this.helper.css("opacity", o.opacity);
13734 }
13735
13736 if(o.zIndex) { // zIndex option
13737 if (this.helper.css("zIndex")) {
13738 this._storedZIndex = this.helper.css("zIndex");
13739 }
13740 this.helper.css("zIndex", o.zIndex);
13741 }
13742
13743 //Prepare scrolling
13744 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
13745 this.overflowOffset = this.scrollParent.offset();
13746 }
13747
13748 //Call callbacks
13749 this._trigger("start", event, this._uiHash());
13750
13751 //Recache the helper size
13752 if(!this._preserveHelperProportions) {
13753 this._cacheHelperProportions();
13754 }
13755
13756
13757 //Post "activate" events to possible containers
13758 if( !noActivation ) {
13759 for ( i = this.containers.length - 1; i >= 0; i-- ) {
13760 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
13761 }
13762 }
13763
13764 //Prepare possible droppables
13765 if($.ui.ddmanager) {
13766 $.ui.ddmanager.current = this;
13767 }
13768
13769 if ($.ui.ddmanager && !o.dropBehaviour) {
13770 $.ui.ddmanager.prepareOffsets(this, event);
13771 }
13772
13773 this.dragging = true;
13774
13775 this.helper.addClass("ui-sortable-helper");
13776 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
13777 return true;
13778
13779 },
13780
13781 _mouseDrag: function(event) {
13782 var i, item, itemElement, intersection,
13783 o = this.options,
13784 scrolled = false;
13785
13786 //Compute the helpers position
13787 this.position = this._generatePosition(event);
13788 this.positionAbs = this._convertPositionTo("absolute");
13789
13790 if (!this.lastPositionAbs) {
13791 this.lastPositionAbs = this.positionAbs;
13792 }
13793
13794 //Do scrolling
13795 if(this.options.scroll) {
13796 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
13797
13798 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
13799 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
13800 } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
13801 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
13802 }
13803
13804 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
13805 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
13806 } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
13807 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
13808 }
13809
13810 } else {
13811
13812 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
13813 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
13814 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
13815 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
13816 }
13817
13818 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
13819 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
13820 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
13821 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
13822 }
13823
13824 }
13825
13826 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
13827 $.ui.ddmanager.prepareOffsets(this, event);
13828 }
13829 }
13830
13831 //Regenerate the absolute position used for position checks
13832 this.positionAbs = this._convertPositionTo("absolute");
13833
13834 //Set the helper position
13835 if(!this.options.axis || this.options.axis !== "y") {
13836 this.helper[0].style.left = this.position.left+"px";
13837 }
13838 if(!this.options.axis || this.options.axis !== "x") {
13839 this.helper[0].style.top = this.position.top+"px";
13840 }
13841
13842 //Rearrange
13843 for (i = this.items.length - 1; i >= 0; i--) {
13844
13845 //Cache variables and intersection, continue if no intersection
13846 item = this.items[i];
13847 itemElement = item.item[0];
13848 intersection = this._intersectsWithPointer(item);
13849 if (!intersection) {
13850 continue;
13851 }
13852
13853 // Only put the placeholder inside the current Container, skip all
13854 // items from other containers. This works because when moving
13855 // an item from one container to another the
13856 // currentContainer is switched before the placeholder is moved.
13857 //
13858 // Without this, moving items in "sub-sortables" can cause
13859 // the placeholder to jitter between the outer and inner container.
13860 if (item.instance !== this.currentContainer) {
13861 continue;
13862 }
13863
13864 // cannot intersect with itself
13865 // no useless actions that have been done before
13866 // no action if the item moved is the parent of the item checked
13867 if (itemElement !== this.currentItem[0] &&
13868 this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
13869 !$.contains(this.placeholder[0], itemElement) &&
13870 (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
13871 ) {
13872
13873 this.direction = intersection === 1 ? "down" : "up";
13874
13875 if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
13876 this._rearrange(event, item);
13877 } else {
13878 break;
13879 }
13880
13881 this._trigger("change", event, this._uiHash());
13882 break;
13883 }
13884 }
13885
13886 //Post events to containers
13887 this._contactContainers(event);
13888
13889 //Interconnect with droppables
13890 if($.ui.ddmanager) {
13891 $.ui.ddmanager.drag(this, event);
13892 }
13893
13894 //Call callbacks
13895 this._trigger("sort", event, this._uiHash());
13896
13897 this.lastPositionAbs = this.positionAbs;
13898 return false;
13899
13900 },
13901
13902 _mouseStop: function(event, noPropagation) {
13903
13904 if(!event) {
13905 return;
13906 }
13907
13908 //If we are using droppables, inform the manager about the drop
13909 if ($.ui.ddmanager && !this.options.dropBehaviour) {
13910 $.ui.ddmanager.drop(this, event);
13911 }
13912
13913 if(this.options.revert) {
13914 var that = this,
13915 cur = this.placeholder.offset(),
13916 axis = this.options.axis,
13917 animation = {};
13918
13919 if ( !axis || axis === "x" ) {
13920 animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft);
13921 }
13922 if ( !axis || axis === "y" ) {
13923 animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop);
13924 }
13925 this.reverting = true;
13926 $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {
13927 that._clear(event);
13928 });
13929 } else {
13930 this._clear(event, noPropagation);
13931 }
13932
13933 return false;
13934
13935 },
13936
13937 cancel: function() {
13938
13939 if(this.dragging) {
13940
13941 this._mouseUp({ target: null });
13942
13943 if(this.options.helper === "original") {
13944 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
13945 } else {
13946 this.currentItem.show();
13947 }
13948
13949 //Post deactivating events to containers
13950 for (var i = this.containers.length - 1; i >= 0; i--){
13951 this.containers[i]._trigger("deactivate", null, this._uiHash(this));
13952 if(this.containers[i].containerCache.over) {
13953 this.containers[i]._trigger("out", null, this._uiHash(this));
13954 this.containers[i].containerCache.over = 0;
13955 }
13956 }
13957
13958 }
13959
13960 if (this.placeholder) {
13961 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
13962 if(this.placeholder[0].parentNode) {
13963 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
13964 }
13965 if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
13966 this.helper.remove();
13967 }
13968
13969 $.extend(this, {
13970 helper: null,
13971 dragging: false,
13972 reverting: false,
13973 _noFinalSort: null
13974 });
13975
13976 if(this.domPosition.prev) {
13977 $(this.domPosition.prev).after(this.currentItem);
13978 } else {
13979 $(this.domPosition.parent).prepend(this.currentItem);
13980 }
13981 }
13982
13983 return this;
13984
13985 },
13986
13987 serialize: function(o) {
13988
13989 var items = this._getItemsAsjQuery(o && o.connected),
13990 str = [];
13991 o = o || {};
13992
13993 $(items).each(function() {
13994 var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/));
13995 if (res) {
13996 str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));
13997 }
13998 });
13999
14000 if(!str.length && o.key) {
14001 str.push(o.key + "=");
14002 }
14003
14004 return str.join("&");
14005
14006 },
14007
14008 toArray: function(o) {
14009
14010 var items = this._getItemsAsjQuery(o && o.connected),
14011 ret = [];
14012
14013 o = o || {};
14014
14015 items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
14016 return ret;
14017
14018 },
14019
14020 /* Be careful with the following core functions */
14021 _intersectsWith: function(item) {
14022
14023 var x1 = this.positionAbs.left,
14024 x2 = x1 + this.helperProportions.width,
14025 y1 = this.positionAbs.top,
14026 y2 = y1 + this.helperProportions.height,
14027 l = item.left,
14028 r = l + item.width,
14029 t = item.top,
14030 b = t + item.height,
14031 dyClick = this.offset.click.top,
14032 dxClick = this.offset.click.left,
14033 isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),
14034 isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),
14035 isOverElement = isOverElementHeight && isOverElementWidth;
14036
14037 if ( this.options.tolerance === "pointer" ||
14038 this.options.forcePointerForContainers ||
14039 (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])
14040 ) {
14041 return isOverElement;
14042 } else {
14043
14044 return (l < x1 + (this.helperProportions.width / 2) && // Right Half
14045 x2 - (this.helperProportions.width / 2) < r && // Left Half
14046 t < y1 + (this.helperProportions.height / 2) && // Bottom Half
14047 y2 - (this.helperProportions.height / 2) < b ); // Top Half
14048
14049 }
14050 },
14051
14052 _intersectsWithPointer: function(item) {
14053
14054 var isOverElementHeight = (this.options.axis === "x") || this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
14055 isOverElementWidth = (this.options.axis === "y") || this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
14056 isOverElement = isOverElementHeight && isOverElementWidth,
14057 verticalDirection = this._getDragVerticalDirection(),
14058 horizontalDirection = this._getDragHorizontalDirection();
14059
14060 if (!isOverElement) {
14061 return false;
14062 }
14063
14064 return this.floating ?
14065 ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )
14066 : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );
14067
14068 },
14069
14070 _intersectsWithSides: function(item) {
14071
14072 var isOverBottomHalf = this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
14073 isOverRightHalf = this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
14074 verticalDirection = this._getDragVerticalDirection(),
14075 horizontalDirection = this._getDragHorizontalDirection();
14076
14077 if (this.floating && horizontalDirection) {
14078 return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
14079 } else {
14080 return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
14081 }
14082
14083 },
14084
14085 _getDragVerticalDirection: function() {
14086 var delta = this.positionAbs.top - this.lastPositionAbs.top;
14087 return delta !== 0 && (delta > 0 ? "down" : "up");
14088 },
14089
14090 _getDragHorizontalDirection: function() {
14091 var delta = this.positionAbs.left - this.lastPositionAbs.left;
14092 return delta !== 0 && (delta > 0 ? "right" : "left");
14093 },
14094
14095 refresh: function(event) {
14096 this._refreshItems(event);
14097 this._setHandleClassName();
14098 this.refreshPositions();
14099 return this;
14100 },
14101
14102 _connectWith: function() {
14103 var options = this.options;
14104 return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
14105 },
14106
14107 _getItemsAsjQuery: function(connected) {
14108
14109 var i, j, cur, inst,
14110 items = [],
14111 queries = [],
14112 connectWith = this._connectWith();
14113
14114 if(connectWith && connected) {
14115 for (i = connectWith.length - 1; i >= 0; i--){
14116 cur = $(connectWith[i]);
14117 for ( j = cur.length - 1; j >= 0; j--){
14118 inst = $.data(cur[j], this.widgetFullName);
14119 if(inst && inst !== this && !inst.options.disabled) {
14120 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), inst]);
14121 }
14122 }
14123 }
14124 }
14125
14126 queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]);
14127
14128 function addItems() {
14129 items.push( this );
14130 }
14131 for (i = queries.length - 1; i >= 0; i--){
14132 queries[i][0].each( addItems );
14133 }
14134
14135 return $(items);
14136
14137 },
14138
14139 _removeCurrentsFromItems: function() {
14140
14141 var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
14142
14143 this.items = $.grep(this.items, function (item) {
14144 for (var j=0; j < list.length; j++) {
14145 if(list[j] === item.item[0]) {
14146 return false;
14147 }
14148 }
14149 return true;
14150 });
14151
14152 },
14153
14154 _refreshItems: function(event) {
14155
14156 this.items = [];
14157 this.containers = [this];
14158
14159 var i, j, cur, inst, targetData, _queries, item, queriesLength,
14160 items = this.items,
14161 queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],
14162 connectWith = this._connectWith();
14163
14164 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
14165 for (i = connectWith.length - 1; i >= 0; i--){
14166 cur = $(connectWith[i]);
14167 for (j = cur.length - 1; j >= 0; j--){
14168 inst = $.data(cur[j], this.widgetFullName);
14169 if(inst && inst !== this && !inst.options.disabled) {
14170 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
14171 this.containers.push(inst);
14172 }
14173 }
14174 }
14175 }
14176
14177 for (i = queries.length - 1; i >= 0; i--) {
14178 targetData = queries[i][1];
14179 _queries = queries[i][0];
14180
14181 for (j=0, queriesLength = _queries.length; j < queriesLength; j++) {
14182 item = $(_queries[j]);
14183
14184 item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)
14185
14186 items.push({
14187 item: item,
14188 instance: targetData,
14189 width: 0, height: 0,
14190 left: 0, top: 0
14191 });
14192 }
14193 }
14194
14195 },
14196
14197 refreshPositions: function(fast) {
14198
14199 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
14200 if(this.offsetParent && this.helper) {
14201 this.offset.parent = this._getParentOffset();
14202 }
14203
14204 var i, item, t, p;
14205
14206 for (i = this.items.length - 1; i >= 0; i--){
14207 item = this.items[i];
14208
14209 //We ignore calculating positions of all connected containers when we're not over them
14210 if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
14211 continue;
14212 }
14213
14214 t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
14215
14216 if (!fast) {
14217 item.width = t.outerWidth();
14218 item.height = t.outerHeight();
14219 }
14220
14221 p = t.offset();
14222 item.left = p.left;
14223 item.top = p.top;
14224 }
14225
14226 if(this.options.custom && this.options.custom.refreshContainers) {
14227 this.options.custom.refreshContainers.call(this);
14228 } else {
14229 for (i = this.containers.length - 1; i >= 0; i--){
14230 p = this.containers[i].element.offset();
14231 this.containers[i].containerCache.left = p.left;
14232 this.containers[i].containerCache.top = p.top;
14233 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
14234 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
14235 }
14236 }
14237
14238 return this;
14239 },
14240
14241 _createPlaceholder: function(that) {
14242 that = that || this;
14243 var className,
14244 o = that.options;
14245
14246 if(!o.placeholder || o.placeholder.constructor === String) {
14247 className = o.placeholder;
14248 o.placeholder = {
14249 element: function() {
14250
14251 var nodeName = that.currentItem[0].nodeName.toLowerCase(),
14252 element = $( "<" + nodeName + ">", that.document[0] )
14253 .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
14254 .removeClass("ui-sortable-helper");
14255
14256 if ( nodeName === "tr" ) {
14257 that.currentItem.children().each(function() {
14258 $( "<td>&#160;</td>", that.document[0] )
14259 .attr( "colspan", $( this ).attr( "colspan" ) || 1 )
14260 .appendTo( element );
14261 });
14262 } else if ( nodeName === "img" ) {
14263 element.attr( "src", that.currentItem.attr( "src" ) );
14264 }
14265
14266 if ( !className ) {
14267 element.css( "visibility", "hidden" );
14268 }
14269
14270 return element;
14271 },
14272 update: function(container, p) {
14273
14274 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
14275 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
14276 if(className && !o.forcePlaceholderSize) {
14277 return;
14278 }
14279
14280 //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
14281 if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }
14282 if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }
14283 }
14284 };
14285 }
14286
14287 //Create the placeholder
14288 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
14289
14290 //Append it after the actual current item
14291 that.currentItem.after(that.placeholder);
14292
14293 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
14294 o.placeholder.update(that, that.placeholder);
14295
14296 },
14297
14298 _contactContainers: function(event) {
14299 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, floating, axis,
14300 innermostContainer = null,
14301 innermostIndex = null;
14302
14303 // get innermost container that intersects with item
14304 for (i = this.containers.length - 1; i >= 0; i--) {
14305
14306 // never consider a container that's located within the item itself
14307 if($.contains(this.currentItem[0], this.containers[i].element[0])) {
14308 continue;
14309 }
14310
14311 if(this._intersectsWith(this.containers[i].containerCache)) {
14312
14313 // if we've already found a container and it's more "inner" than this, then continue
14314 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
14315 continue;
14316 }
14317
14318 innermostContainer = this.containers[i];
14319 innermostIndex = i;
14320
14321 } else {
14322 // container doesn't intersect. trigger "out" event if necessary
14323 if(this.containers[i].containerCache.over) {
14324 this.containers[i]._trigger("out", event, this._uiHash(this));
14325 this.containers[i].containerCache.over = 0;
14326 }
14327 }
14328
14329 }
14330
14331 // if no intersecting containers found, return
14332 if(!innermostContainer) {
14333 return;
14334 }
14335
14336 // move the item into the container if it's not there already
14337 if(this.containers.length === 1) {
14338 if (!this.containers[innermostIndex].containerCache.over) {
14339 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
14340 this.containers[innermostIndex].containerCache.over = 1;
14341 }
14342 } else {
14343
14344 //When entering a new container, we will find the item with the least distance and append our item near it
14345 dist = 10000;
14346 itemWithLeastDistance = null;
14347 floating = innermostContainer.floating || this._isFloating(this.currentItem);
14348 posProperty = floating ? "left" : "top";
14349 sizeProperty = floating ? "width" : "height";
14350 axis = floating ? "clientX" : "clientY";
14351
14352 for (j = this.items.length - 1; j >= 0; j--) {
14353 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
14354 continue;
14355 }
14356 if(this.items[j].item[0] === this.currentItem[0]) {
14357 continue;
14358 }
14359
14360 cur = this.items[j].item.offset()[posProperty];
14361 nearBottom = false;
14362 if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
14363 nearBottom = true;
14364 }
14365
14366 if ( Math.abs( event[ axis ] - cur ) < dist ) {
14367 dist = Math.abs( event[ axis ] - cur );
14368 itemWithLeastDistance = this.items[ j ];
14369 this.direction = nearBottom ? "up": "down";
14370 }
14371 }
14372
14373 //Check if dropOnEmpty is enabled
14374 if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
14375 return;
14376 }
14377
14378 if(this.currentContainer === this.containers[innermostIndex]) {
14379 if ( !this.currentContainer.containerCache.over ) {
14380 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
14381 this.currentContainer.containerCache.over = 1;
14382 }
14383 return;
14384 }
14385
14386 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
14387 this._trigger("change", event, this._uiHash());
14388 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
14389 this.currentContainer = this.containers[innermostIndex];
14390
14391 //Update the placeholder
14392 this.options.placeholder.update(this.currentContainer, this.placeholder);
14393
14394 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
14395 this.containers[innermostIndex].containerCache.over = 1;
14396 }
14397
14398
14399 },
14400
14401 _createHelper: function(event) {
14402
14403 var o = this.options,
14404 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);
14405
14406 //Add the helper to the DOM if that didn't happen already
14407 if(!helper.parents("body").length) {
14408 $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
14409 }
14410
14411 if(helper[0] === this.currentItem[0]) {
14412 this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
14413 }
14414
14415 if(!helper[0].style.width || o.forceHelperSize) {
14416 helper.width(this.currentItem.width());
14417 }
14418 if(!helper[0].style.height || o.forceHelperSize) {
14419 helper.height(this.currentItem.height());
14420 }
14421
14422 return helper;
14423
14424 },
14425
14426 _adjustOffsetFromHelper: function(obj) {
14427 if (typeof obj === "string") {
14428 obj = obj.split(" ");
14429 }
14430 if ($.isArray(obj)) {
14431 obj = {left: +obj[0], top: +obj[1] || 0};
14432 }
14433 if ("left" in obj) {
14434 this.offset.click.left = obj.left + this.margins.left;
14435 }
14436 if ("right" in obj) {
14437 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
14438 }
14439 if ("top" in obj) {
14440 this.offset.click.top = obj.top + this.margins.top;
14441 }
14442 if ("bottom" in obj) {
14443 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
14444 }
14445 },
14446
14447 _getParentOffset: function() {
14448
14449
14450 //Get the offsetParent and cache its position
14451 this.offsetParent = this.helper.offsetParent();
14452 var po = this.offsetParent.offset();
14453
14454 // This is a special case where we need to modify a offset calculated on start, since the following happened:
14455 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
14456 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
14457 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
14458 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
14459 po.left += this.scrollParent.scrollLeft();
14460 po.top += this.scrollParent.scrollTop();
14461 }
14462
14463 // This needs to be actually done for all browsers, since pageX/pageY includes this information
14464 // with an ugly IE fix
14465 if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
14466 po = { top: 0, left: 0 };
14467 }
14468
14469 return {
14470 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
14471 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
14472 };
14473
14474 },
14475
14476 _getRelativeOffset: function() {
14477
14478 if(this.cssPosition === "relative") {
14479 var p = this.currentItem.position();
14480 return {
14481 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
14482 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
14483 };
14484 } else {
14485 return { top: 0, left: 0 };
14486 }
14487
14488 },
14489
14490 _cacheMargins: function() {
14491 this.margins = {
14492 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
14493 top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
14494 };
14495 },
14496
14497 _cacheHelperProportions: function() {
14498 this.helperProportions = {
14499 width: this.helper.outerWidth(),
14500 height: this.helper.outerHeight()
14501 };
14502 },
14503
14504 _setContainment: function() {
14505
14506 var ce, co, over,
14507 o = this.options;
14508 if(o.containment === "parent") {
14509 o.containment = this.helper[0].parentNode;
14510 }
14511 if(o.containment === "document" || o.containment === "window") {
14512 this.containment = [
14513 0 - this.offset.relative.left - this.offset.parent.left,
14514 0 - this.offset.relative.top - this.offset.parent.top,
14515 $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left,
14516 ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
14517 ];
14518 }
14519
14520 if(!(/^(document|window|parent)$/).test(o.containment)) {
14521 ce = $(o.containment)[0];
14522 co = $(o.containment).offset();
14523 over = ($(ce).css("overflow") !== "hidden");
14524
14525 this.containment = [
14526 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
14527 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
14528 co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
14529 co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
14530 ];
14531 }
14532
14533 },
14534
14535 _convertPositionTo: function(d, pos) {
14536
14537 if(!pos) {
14538 pos = this.position;
14539 }
14540 var mod = d === "absolute" ? 1 : -1,
14541 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
14542 scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
14543
14544 return {
14545 top: (
14546 pos.top + // The absolute mouse position
14547 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
14548 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
14549 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
14550 ),
14551 left: (
14552 pos.left + // The absolute mouse position
14553 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
14554 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
14555 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
14556 )
14557 };
14558
14559 },
14560
14561 _generatePosition: function(event) {
14562
14563 var top, left,
14564 o = this.options,
14565 pageX = event.pageX,
14566 pageY = event.pageY,
14567 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
14568
14569 // This is another very weird special case that only happens for relative elements:
14570 // 1. If the css position is relative
14571 // 2. and the scroll parent is the document or similar to the offset parent
14572 // we have to refresh the relative offset during the scroll so there are no jumps
14573 if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) {
14574 this.offset.relative = this._getRelativeOffset();
14575 }
14576
14577 /*
14578 * - Position constraining -
14579 * Constrain the position to a mix of grid, containment.
14580 */
14581
14582 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
14583
14584 if(this.containment) {
14585 if(event.pageX - this.offset.click.left < this.containment[0]) {
14586 pageX = this.containment[0] + this.offset.click.left;
14587 }
14588 if(event.pageY - this.offset.click.top < this.containment[1]) {
14589 pageY = this.containment[1] + this.offset.click.top;
14590 }
14591 if(event.pageX - this.offset.click.left > this.containment[2]) {
14592 pageX = this.containment[2] + this.offset.click.left;
14593 }
14594 if(event.pageY - this.offset.click.top > this.containment[3]) {
14595 pageY = this.containment[3] + this.offset.click.top;
14596 }
14597 }
14598
14599 if(o.grid) {
14600 top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
14601 pageY = this.containment ? ( (top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3]) ? top : ((top - this.offset.click.top >= this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
14602
14603 left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
14604 pageX = this.containment ? ( (left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2]) ? left : ((left - this.offset.click.left >= this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
14605 }
14606
14607 }
14608
14609 return {
14610 top: (
14611 pageY - // The absolute mouse position
14612 this.offset.click.top - // Click offset (relative to the element)
14613 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
14614 this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
14615 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
14616 ),
14617 left: (
14618 pageX - // The absolute mouse position
14619 this.offset.click.left - // Click offset (relative to the element)
14620 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
14621 this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
14622 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
14623 )
14624 };
14625
14626 },
14627
14628 _rearrange: function(event, i, a, hardRefresh) {
14629
14630 a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling));
14631
14632 //Various things done here to improve the performance:
14633 // 1. we create a setTimeout, that calls refreshPositions
14634 // 2. on the instance, we have a counter variable, that get's higher after every append
14635 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
14636 // 4. this lets only the last addition to the timeout stack through
14637 this.counter = this.counter ? ++this.counter : 1;
14638 var counter = this.counter;
14639
14640 this._delay(function() {
14641 if(counter === this.counter) {
14642 this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
14643 }
14644 });
14645
14646 },
14647
14648 _clear: function(event, noPropagation) {
14649
14650 this.reverting = false;
14651 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
14652 // everything else normalized again
14653 var i,
14654 delayedTriggers = [];
14655
14656 // We first have to update the dom position of the actual currentItem
14657 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
14658 if(!this._noFinalSort && this.currentItem.parent().length) {
14659 this.placeholder.before(this.currentItem);
14660 }
14661 this._noFinalSort = null;
14662
14663 if(this.helper[0] === this.currentItem[0]) {
14664 for(i in this._storedCSS) {
14665 if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
14666 this._storedCSS[i] = "";
14667 }
14668 }
14669 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
14670 } else {
14671 this.currentItem.show();
14672 }
14673
14674 if(this.fromOutside && !noPropagation) {
14675 delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
14676 }
14677 if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
14678 delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
14679 }
14680
14681 // Check if the items Container has Changed and trigger appropriate
14682 // events.
14683 if (this !== this.currentContainer) {
14684 if(!noPropagation) {
14685 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
14686 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
14687 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
14688 }
14689 }
14690
14691
14692 //Post events to containers
14693 function delayEvent( type, instance, container ) {
14694 return function( event ) {
14695 container._trigger( type, event, instance._uiHash( instance ) );
14696 };
14697 }
14698 for (i = this.containers.length - 1; i >= 0; i--){
14699 if (!noPropagation) {
14700 delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
14701 }
14702 if(this.containers[i].containerCache.over) {
14703 delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
14704 this.containers[i].containerCache.over = 0;
14705 }
14706 }
14707
14708 //Do what was originally in plugins
14709 if ( this.storedCursor ) {
14710 this.document.find( "body" ).css( "cursor", this.storedCursor );
14711 this.storedStylesheet.remove();
14712 }
14713 if(this._storedOpacity) {
14714 this.helper.css("opacity", this._storedOpacity);
14715 }
14716 if(this._storedZIndex) {
14717 this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
14718 }
14719
14720 this.dragging = false;
14721
14722 if(!noPropagation) {
14723 this._trigger("beforeStop", event, this._uiHash());
14724 }
14725
14726 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
14727 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
14728
14729 if ( !this.cancelHelperRemoval ) {
14730 if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
14731 this.helper.remove();
14732 }
14733 this.helper = null;
14734 }
14735
14736 if(!noPropagation) {
14737 for (i=0; i < delayedTriggers.length; i++) {
14738 delayedTriggers[i].call(this, event);
14739 } //Trigger all delayed events
14740 this._trigger("stop", event, this._uiHash());
14741 }
14742
14743 this.fromOutside = false;
14744 return !this.cancelHelperRemoval;
14745
14746 },
14747
14748 _trigger: function() {
14749 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
14750 this.cancel();
14751 }
14752 },
14753
14754 _uiHash: function(_inst) {
14755 var inst = _inst || this;
14756 return {
14757 helper: inst.helper,
14758 placeholder: inst.placeholder || $([]),
14759 position: inst.position,
14760 originalPosition: inst.originalPosition,
14761 offset: inst.positionAbs,
14762 item: inst.currentItem,
14763 sender: _inst ? _inst.element : null
14764 };
14765 }
14766
14767});
14768
14769
14770/*!
14771 * jQuery UI Spinner 1.11.2
14772 * http://jqueryui.com
14773 *
14774 * Copyright 2014 jQuery Foundation and other contributors
14775 * Released under the MIT license.
14776 * http://jquery.org/license
14777 *
14778 * http://api.jqueryui.com/spinner/
14779 */
14780
14781
14782function spinner_modifier( fn ) {
14783 return function() {
14784 var previous = this.element.val();
14785 fn.apply( this, arguments );
14786 this._refresh();
14787 if ( previous !== this.element.val() ) {
14788 this._trigger( "change" );
14789 }
14790 };
14791}
14792
14793var spinner = $.widget( "ui.spinner", {
14794 version: "1.11.2",
14795 defaultElement: "<input>",
14796 widgetEventPrefix: "spin",
14797 options: {
14798 culture: null,
14799 icons: {
14800 down: "ui-icon-triangle-1-s",
14801 up: "ui-icon-triangle-1-n"
14802 },
14803 incremental: true,
14804 max: null,
14805 min: null,
14806 numberFormat: null,
14807 page: 10,
14808 step: 1,
14809
14810 change: null,
14811 spin: null,
14812 start: null,
14813 stop: null
14814 },
14815
14816 _create: function() {
14817 // handle string values that need to be parsed
14818 this._setOption( "max", this.options.max );
14819 this._setOption( "min", this.options.min );
14820 this._setOption( "step", this.options.step );
14821
14822 // Only format if there is a value, prevents the field from being marked
14823 // as invalid in Firefox, see #9573.
14824 if ( this.value() !== "" ) {
14825 // Format the value, but don't constrain.
14826 this._value( this.element.val(), true );
14827 }
14828
14829 this._draw();
14830 this._on( this._events );
14831 this._refresh();
14832
14833 // turning off autocomplete prevents the browser from remembering the
14834 // value when navigating through history, so we re-enable autocomplete
14835 // if the page is unloaded before the widget is destroyed. #7790
14836 this._on( this.window, {
14837 beforeunload: function() {
14838 this.element.removeAttr( "autocomplete" );
14839 }
14840 });
14841 },
14842
14843 _getCreateOptions: function() {
14844 var options = {},
14845 element = this.element;
14846
14847 $.each( [ "min", "max", "step" ], function( i, option ) {
14848 var value = element.attr( option );
14849 if ( value !== undefined && value.length ) {
14850 options[ option ] = value;
14851 }
14852 });
14853
14854 return options;
14855 },
14856
14857 _events: {
14858 keydown: function( event ) {
14859 if ( this._start( event ) && this._keydown( event ) ) {
14860 event.preventDefault();
14861 }
14862 },
14863 keyup: "_stop",
14864 focus: function() {
14865 this.previous = this.element.val();
14866 },
14867 blur: function( event ) {
14868 if ( this.cancelBlur ) {
14869 delete this.cancelBlur;
14870 return;
14871 }
14872
14873 this._stop();
14874 this._refresh();
14875 if ( this.previous !== this.element.val() ) {
14876 this._trigger( "change", event );
14877 }
14878 },
14879 mousewheel: function( event, delta ) {
14880 if ( !delta ) {
14881 return;
14882 }
14883 if ( !this.spinning && !this._start( event ) ) {
14884 return false;
14885 }
14886
14887 this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
14888 clearTimeout( this.mousewheelTimer );
14889 this.mousewheelTimer = this._delay(function() {
14890 if ( this.spinning ) {
14891 this._stop( event );
14892 }
14893 }, 100 );
14894 event.preventDefault();
14895 },
14896 "mousedown .ui-spinner-button": function( event ) {
14897 var previous;
14898
14899 // We never want the buttons to have focus; whenever the user is
14900 // interacting with the spinner, the focus should be on the input.
14901 // If the input is focused then this.previous is properly set from
14902 // when the input first received focus. If the input is not focused
14903 // then we need to set this.previous based on the value before spinning.
14904 previous = this.element[0] === this.document[0].activeElement ?
14905 this.previous : this.element.val();
14906 function checkFocus() {
14907 var isActive = this.element[0] === this.document[0].activeElement;
14908 if ( !isActive ) {
14909 this.element.focus();
14910 this.previous = previous;
14911 // support: IE
14912 // IE sets focus asynchronously, so we need to check if focus
14913 // moved off of the input because the user clicked on the button.
14914 this._delay(function() {
14915 this.previous = previous;
14916 });
14917 }
14918 }
14919
14920 // ensure focus is on (or stays on) the text field
14921 event.preventDefault();
14922 checkFocus.call( this );
14923
14924 // support: IE
14925 // IE doesn't prevent moving focus even with event.preventDefault()
14926 // so we set a flag to know when we should ignore the blur event
14927 // and check (again) if focus moved off of the input.
14928 this.cancelBlur = true;
14929 this._delay(function() {
14930 delete this.cancelBlur;
14931 checkFocus.call( this );
14932 });
14933
14934 if ( this._start( event ) === false ) {
14935 return;
14936 }
14937
14938 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
14939 },
14940 "mouseup .ui-spinner-button": "_stop",
14941 "mouseenter .ui-spinner-button": function( event ) {
14942 // button will add ui-state-active if mouse was down while mouseleave and kept down
14943 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
14944 return;
14945 }
14946
14947 if ( this._start( event ) === false ) {
14948 return false;
14949 }
14950 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
14951 },
14952 // TODO: do we really want to consider this a stop?
14953 // shouldn't we just stop the repeater and wait until mouseup before
14954 // we trigger the stop event?
14955 "mouseleave .ui-spinner-button": "_stop"
14956 },
14957
14958 _draw: function() {
14959 var uiSpinner = this.uiSpinner = this.element
14960 .addClass( "ui-spinner-input" )
14961 .attr( "autocomplete", "off" )
14962 .wrap( this._uiSpinnerHtml() )
14963 .parent()
14964 // add buttons
14965 .append( this._buttonHtml() );
14966
14967 this.element.attr( "role", "spinbutton" );
14968
14969 // button bindings
14970 this.buttons = uiSpinner.find( ".ui-spinner-button" )
14971 .attr( "tabIndex", -1 )
14972 .button()
14973 .removeClass( "ui-corner-all" );
14974
14975 // IE 6 doesn't understand height: 50% for the buttons
14976 // unless the wrapper has an explicit height
14977 if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
14978 uiSpinner.height() > 0 ) {
14979 uiSpinner.height( uiSpinner.height() );
14980 }
14981
14982 // disable spinner if element was already disabled
14983 if ( this.options.disabled ) {
14984 this.disable();
14985 }
14986 },
14987
14988 _keydown: function( event ) {
14989 var options = this.options,
14990 keyCode = $.ui.keyCode;
14991
14992 switch ( event.keyCode ) {
14993 case keyCode.UP:
14994 this._repeat( null, 1, event );
14995 return true;
14996 case keyCode.DOWN:
14997 this._repeat( null, -1, event );
14998 return true;
14999 case keyCode.PAGE_UP:
15000 this._repeat( null, options.page, event );
15001 return true;
15002 case keyCode.PAGE_DOWN:
15003 this._repeat( null, -options.page, event );
15004 return true;
15005 }
15006
15007 return false;
15008 },
15009
15010 _uiSpinnerHtml: function() {
15011 return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
15012 },
15013
15014 _buttonHtml: function() {
15015 return "" +
15016 "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
15017 "<span class='ui-icon " + this.options.icons.up + "'>&#9650;</span>" +
15018 "</a>" +
15019 "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
15020 "<span class='ui-icon " + this.options.icons.down + "'>&#9660;</span>" +
15021 "</a>";
15022 },
15023
15024 _start: function( event ) {
15025 if ( !this.spinning && this._trigger( "start", event ) === false ) {
15026 return false;
15027 }
15028
15029 if ( !this.counter ) {
15030 this.counter = 1;
15031 }
15032 this.spinning = true;
15033 return true;
15034 },
15035
15036 _repeat: function( i, steps, event ) {
15037 i = i || 500;
15038
15039 clearTimeout( this.timer );
15040 this.timer = this._delay(function() {
15041 this._repeat( 40, steps, event );
15042 }, i );
15043
15044 this._spin( steps * this.options.step, event );
15045 },
15046
15047 _spin: function( step, event ) {
15048 var value = this.value() || 0;
15049
15050 if ( !this.counter ) {
15051 this.counter = 1;
15052 }
15053
15054 value = this._adjustValue( value + step * this._increment( this.counter ) );
15055
15056 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
15057 this._value( value );
15058 this.counter++;
15059 }
15060 },
15061
15062 _increment: function( i ) {
15063 var incremental = this.options.incremental;
15064
15065 if ( incremental ) {
15066 return $.isFunction( incremental ) ?
15067 incremental( i ) :
15068 Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
15069 }
15070
15071 return 1;
15072 },
15073
15074 _precision: function() {
15075 var precision = this._precisionOf( this.options.step );
15076 if ( this.options.min !== null ) {
15077 precision = Math.max( precision, this._precisionOf( this.options.min ) );
15078 }
15079 return precision;
15080 },
15081
15082 _precisionOf: function( num ) {
15083 var str = num.toString(),
15084 decimal = str.indexOf( "." );
15085 return decimal === -1 ? 0 : str.length - decimal - 1;
15086 },
15087
15088 _adjustValue: function( value ) {
15089 var base, aboveMin,
15090 options = this.options;
15091
15092 // make sure we're at a valid step
15093 // - find out where we are relative to the base (min or 0)
15094 base = options.min !== null ? options.min : 0;
15095 aboveMin = value - base;
15096 // - round to the nearest step
15097 aboveMin = Math.round(aboveMin / options.step) * options.step;
15098 // - rounding is based on 0, so adjust back to our base
15099 value = base + aboveMin;
15100
15101 // fix precision from bad JS floating point math
15102 value = parseFloat( value.toFixed( this._precision() ) );
15103
15104 // clamp the value
15105 if ( options.max !== null && value > options.max) {
15106 return options.max;
15107 }
15108 if ( options.min !== null && value < options.min ) {
15109 return options.min;
15110 }
15111
15112 return value;
15113 },
15114
15115 _stop: function( event ) {
15116 if ( !this.spinning ) {
15117 return;
15118 }
15119
15120 clearTimeout( this.timer );
15121 clearTimeout( this.mousewheelTimer );
15122 this.counter = 0;
15123 this.spinning = false;
15124 this._trigger( "stop", event );
15125 },
15126
15127 _setOption: function( key, value ) {
15128 if ( key === "culture" || key === "numberFormat" ) {
15129 var prevValue = this._parse( this.element.val() );
15130 this.options[ key ] = value;
15131 this.element.val( this._format( prevValue ) );
15132 return;
15133 }
15134
15135 if ( key === "max" || key === "min" || key === "step" ) {
15136 if ( typeof value === "string" ) {
15137 value = this._parse( value );
15138 }
15139 }
15140 if ( key === "icons" ) {
15141 this.buttons.first().find( ".ui-icon" )
15142 .removeClass( this.options.icons.up )
15143 .addClass( value.up );
15144 this.buttons.last().find( ".ui-icon" )
15145 .removeClass( this.options.icons.down )
15146 .addClass( value.down );
15147 }
15148
15149 this._super( key, value );
15150
15151 if ( key === "disabled" ) {
15152 this.widget().toggleClass( "ui-state-disabled", !!value );
15153 this.element.prop( "disabled", !!value );
15154 this.buttons.button( value ? "disable" : "enable" );
15155 }
15156 },
15157
15158 _setOptions: spinner_modifier(function( options ) {
15159 this._super( options );
15160 }),
15161
15162 _parse: function( val ) {
15163 if ( typeof val === "string" && val !== "" ) {
15164 val = window.Globalize && this.options.numberFormat ?
15165 Globalize.parseFloat( val, 10, this.options.culture ) : +val;
15166 }
15167 return val === "" || isNaN( val ) ? null : val;
15168 },
15169
15170 _format: function( value ) {
15171 if ( value === "" ) {
15172 return "";
15173 }
15174 return window.Globalize && this.options.numberFormat ?
15175 Globalize.format( value, this.options.numberFormat, this.options.culture ) :
15176 value;
15177 },
15178
15179 _refresh: function() {
15180 this.element.attr({
15181 "aria-valuemin": this.options.min,
15182 "aria-valuemax": this.options.max,
15183 // TODO: what should we do with values that can't be parsed?
15184 "aria-valuenow": this._parse( this.element.val() )
15185 });
15186 },
15187
15188 isValid: function() {
15189 var value = this.value();
15190
15191 // null is invalid
15192 if ( value === null ) {
15193 return false;
15194 }
15195
15196 // if value gets adjusted, it's invalid
15197 return value === this._adjustValue( value );
15198 },
15199
15200 // update the value without triggering change
15201 _value: function( value, allowAny ) {
15202 var parsed;
15203 if ( value !== "" ) {
15204 parsed = this._parse( value );
15205 if ( parsed !== null ) {
15206 if ( !allowAny ) {
15207 parsed = this._adjustValue( parsed );
15208 }
15209 value = this._format( parsed );
15210 }
15211 }
15212 this.element.val( value );
15213 this._refresh();
15214 },
15215
15216 _destroy: function() {
15217 this.element
15218 .removeClass( "ui-spinner-input" )
15219 .prop( "disabled", false )
15220 .removeAttr( "autocomplete" )
15221 .removeAttr( "role" )
15222 .removeAttr( "aria-valuemin" )
15223 .removeAttr( "aria-valuemax" )
15224 .removeAttr( "aria-valuenow" );
15225 this.uiSpinner.replaceWith( this.element );
15226 },
15227
15228 stepUp: spinner_modifier(function( steps ) {
15229 this._stepUp( steps );
15230 }),
15231 _stepUp: function( steps ) {
15232 if ( this._start() ) {
15233 this._spin( (steps || 1) * this.options.step );
15234 this._stop();
15235 }
15236 },
15237
15238 stepDown: spinner_modifier(function( steps ) {
15239 this._stepDown( steps );
15240 }),
15241 _stepDown: function( steps ) {
15242 if ( this._start() ) {
15243 this._spin( (steps || 1) * -this.options.step );
15244 this._stop();
15245 }
15246 },
15247
15248 pageUp: spinner_modifier(function( pages ) {
15249 this._stepUp( (pages || 1) * this.options.page );
15250 }),
15251
15252 pageDown: spinner_modifier(function( pages ) {
15253 this._stepDown( (pages || 1) * this.options.page );
15254 }),
15255
15256 value: function( newVal ) {
15257 if ( !arguments.length ) {
15258 return this._parse( this.element.val() );
15259 }
15260 spinner_modifier( this._value ).call( this, newVal );
15261 },
15262
15263 widget: function() {
15264 return this.uiSpinner;
15265 }
15266});
15267
15268
15269/*!
15270 * jQuery UI Tabs 1.11.2
15271 * http://jqueryui.com
15272 *
15273 * Copyright 2014 jQuery Foundation and other contributors
15274 * Released under the MIT license.
15275 * http://jquery.org/license
15276 *
15277 * http://api.jqueryui.com/tabs/
15278 */
15279
15280
15281var tabs = $.widget( "ui.tabs", {
15282 version: "1.11.2",
15283 delay: 300,
15284 options: {
15285 active: null,
15286 collapsible: false,
15287 event: "click",
15288 heightStyle: "content",
15289 hide: null,
15290 show: null,
15291
15292 // callbacks
15293 activate: null,
15294 beforeActivate: null,
15295 beforeLoad: null,
15296 load: null
15297 },
15298
15299 _isLocal: (function() {
15300 var rhash = /#.*$/;
15301
15302 return function( anchor ) {
15303 var anchorUrl, locationUrl;
15304
15305 // support: IE7
15306 // IE7 doesn't normalize the href property when set via script (#9317)
15307 anchor = anchor.cloneNode( false );
15308
15309 anchorUrl = anchor.href.replace( rhash, "" );
15310 locationUrl = location.href.replace( rhash, "" );
15311
15312 // decoding may throw an error if the URL isn't UTF-8 (#9518)
15313 try {
15314 anchorUrl = decodeURIComponent( anchorUrl );
15315 } catch ( error ) {}
15316 try {
15317 locationUrl = decodeURIComponent( locationUrl );
15318 } catch ( error ) {}
15319
15320 return anchor.hash.length > 1 && anchorUrl === locationUrl;
15321 };
15322 })(),
15323
15324 _create: function() {
15325 var that = this,
15326 options = this.options;
15327
15328 this.running = false;
15329
15330 this.element
15331 .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
15332 .toggleClass( "ui-tabs-collapsible", options.collapsible );
15333
15334 this._processTabs();
15335 options.active = this._initialActive();
15336
15337 // Take disabling tabs via class attribute from HTML
15338 // into account and update option properly.
15339 if ( $.isArray( options.disabled ) ) {
15340 options.disabled = $.unique( options.disabled.concat(
15341 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
15342 return that.tabs.index( li );
15343 })
15344 ) ).sort();
15345 }
15346
15347 // check for length avoids error when initializing empty list
15348 if ( this.options.active !== false && this.anchors.length ) {
15349 this.active = this._findActive( options.active );
15350 } else {
15351 this.active = $();
15352 }
15353
15354 this._refresh();
15355
15356 if ( this.active.length ) {
15357 this.load( options.active );
15358 }
15359 },
15360
15361 _initialActive: function() {
15362 var active = this.options.active,
15363 collapsible = this.options.collapsible,
15364 locationHash = location.hash.substring( 1 );
15365
15366 if ( active === null ) {
15367 // check the fragment identifier in the URL
15368 if ( locationHash ) {
15369 this.tabs.each(function( i, tab ) {
15370 if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
15371 active = i;
15372 return false;
15373 }
15374 });
15375 }
15376
15377 // check for a tab marked active via a class
15378 if ( active === null ) {
15379 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
15380 }
15381
15382 // no active tab, set to false
15383 if ( active === null || active === -1 ) {
15384 active = this.tabs.length ? 0 : false;
15385 }
15386 }
15387
15388 // handle numbers: negative, out of range
15389 if ( active !== false ) {
15390 active = this.tabs.index( this.tabs.eq( active ) );
15391 if ( active === -1 ) {
15392 active = collapsible ? false : 0;
15393 }
15394 }
15395
15396 // don't allow collapsible: false and active: false
15397 if ( !collapsible && active === false && this.anchors.length ) {
15398 active = 0;
15399 }
15400
15401 return active;
15402 },
15403
15404 _getCreateEventData: function() {
15405 return {
15406 tab: this.active,
15407 panel: !this.active.length ? $() : this._getPanelForTab( this.active )
15408 };
15409 },
15410
15411 _tabKeydown: function( event ) {
15412 var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
15413 selectedIndex = this.tabs.index( focusedTab ),
15414 goingForward = true;
15415
15416 if ( this._handlePageNav( event ) ) {
15417 return;
15418 }
15419
15420 switch ( event.keyCode ) {
15421 case $.ui.keyCode.RIGHT:
15422 case $.ui.keyCode.DOWN:
15423 selectedIndex++;
15424 break;
15425 case $.ui.keyCode.UP:
15426 case $.ui.keyCode.LEFT:
15427 goingForward = false;
15428 selectedIndex--;
15429 break;
15430 case $.ui.keyCode.END:
15431 selectedIndex = this.anchors.length - 1;
15432 break;
15433 case $.ui.keyCode.HOME:
15434 selectedIndex = 0;
15435 break;
15436 case $.ui.keyCode.SPACE:
15437 // Activate only, no collapsing
15438 event.preventDefault();
15439 clearTimeout( this.activating );
15440 this._activate( selectedIndex );
15441 return;
15442 case $.ui.keyCode.ENTER:
15443 // Toggle (cancel delayed activation, allow collapsing)
15444 event.preventDefault();
15445 clearTimeout( this.activating );
15446 // Determine if we should collapse or activate
15447 this._activate( selectedIndex === this.options.active ? false : selectedIndex );
15448 return;
15449 default:
15450 return;
15451 }
15452
15453 // Focus the appropriate tab, based on which key was pressed
15454 event.preventDefault();
15455 clearTimeout( this.activating );
15456 selectedIndex = this._focusNextTab( selectedIndex, goingForward );
15457
15458 // Navigating with control key will prevent automatic activation
15459 if ( !event.ctrlKey ) {
15460 // Update aria-selected immediately so that AT think the tab is already selected.
15461 // Otherwise AT may confuse the user by stating that they need to activate the tab,
15462 // but the tab will already be activated by the time the announcement finishes.
15463 focusedTab.attr( "aria-selected", "false" );
15464 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
15465
15466 this.activating = this._delay(function() {
15467 this.option( "active", selectedIndex );
15468 }, this.delay );
15469 }
15470 },
15471
15472 _panelKeydown: function( event ) {
15473 if ( this._handlePageNav( event ) ) {
15474 return;
15475 }
15476
15477 // Ctrl+up moves focus to the current tab
15478 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
15479 event.preventDefault();
15480 this.active.focus();
15481 }
15482 },
15483
15484 // Alt+page up/down moves focus to the previous/next tab (and activates)
15485 _handlePageNav: function( event ) {
15486 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
15487 this._activate( this._focusNextTab( this.options.active - 1, false ) );
15488 return true;
15489 }
15490 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
15491 this._activate( this._focusNextTab( this.options.active + 1, true ) );
15492 return true;
15493 }
15494 },
15495
15496 _findNextTab: function( index, goingForward ) {
15497 var lastTabIndex = this.tabs.length - 1;
15498
15499 function constrain() {
15500 if ( index > lastTabIndex ) {
15501 index = 0;
15502 }
15503 if ( index < 0 ) {
15504 index = lastTabIndex;
15505 }
15506 return index;
15507 }
15508
15509 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
15510 index = goingForward ? index + 1 : index - 1;
15511 }
15512
15513 return index;
15514 },
15515
15516 _focusNextTab: function( index, goingForward ) {
15517 index = this._findNextTab( index, goingForward );
15518 this.tabs.eq( index ).focus();
15519 return index;
15520 },
15521
15522 _setOption: function( key, value ) {
15523 if ( key === "active" ) {
15524 // _activate() will handle invalid values and update this.options
15525 this._activate( value );
15526 return;
15527 }
15528
15529 if ( key === "disabled" ) {
15530 // don't use the widget factory's disabled handling
15531 this._setupDisabled( value );
15532 return;
15533 }
15534
15535 this._super( key, value);
15536
15537 if ( key === "collapsible" ) {
15538 this.element.toggleClass( "ui-tabs-collapsible", value );
15539 // Setting collapsible: false while collapsed; open first panel
15540 if ( !value && this.options.active === false ) {
15541 this._activate( 0 );
15542 }
15543 }
15544
15545 if ( key === "event" ) {
15546 this._setupEvents( value );
15547 }
15548
15549 if ( key === "heightStyle" ) {
15550 this._setupHeightStyle( value );
15551 }
15552 },
15553
15554 _sanitizeSelector: function( hash ) {
15555 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
15556 },
15557
15558 refresh: function() {
15559 var options = this.options,
15560 lis = this.tablist.children( ":has(a[href])" );
15561
15562 // get disabled tabs from class attribute from HTML
15563 // this will get converted to a boolean if needed in _refresh()
15564 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
15565 return lis.index( tab );
15566 });
15567
15568 this._processTabs();
15569
15570 // was collapsed or no tabs
15571 if ( options.active === false || !this.anchors.length ) {
15572 options.active = false;
15573 this.active = $();
15574 // was active, but active tab is gone
15575 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
15576 // all remaining tabs are disabled
15577 if ( this.tabs.length === options.disabled.length ) {
15578 options.active = false;
15579 this.active = $();
15580 // activate previous tab
15581 } else {
15582 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
15583 }
15584 // was active, active tab still exists
15585 } else {
15586 // make sure active index is correct
15587 options.active = this.tabs.index( this.active );
15588 }
15589
15590 this._refresh();
15591 },
15592
15593 _refresh: function() {
15594 this._setupDisabled( this.options.disabled );
15595 this._setupEvents( this.options.event );
15596 this._setupHeightStyle( this.options.heightStyle );
15597
15598 this.tabs.not( this.active ).attr({
15599 "aria-selected": "false",
15600 "aria-expanded": "false",
15601 tabIndex: -1
15602 });
15603 this.panels.not( this._getPanelForTab( this.active ) )
15604 .hide()
15605 .attr({
15606 "aria-hidden": "true"
15607 });
15608
15609 // Make sure one tab is in the tab order
15610 if ( !this.active.length ) {
15611 this.tabs.eq( 0 ).attr( "tabIndex", 0 );
15612 } else {
15613 this.active
15614 .addClass( "ui-tabs-active ui-state-active" )
15615 .attr({
15616 "aria-selected": "true",
15617 "aria-expanded": "true",
15618 tabIndex: 0
15619 });
15620 this._getPanelForTab( this.active )
15621 .show()
15622 .attr({
15623 "aria-hidden": "false"
15624 });
15625 }
15626 },
15627
15628 _processTabs: function() {
15629 var that = this,
15630 prevTabs = this.tabs,
15631 prevAnchors = this.anchors,
15632 prevPanels = this.panels;
15633
15634 this.tablist = this._getList()
15635 .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
15636 .attr( "role", "tablist" )
15637
15638 // Prevent users from focusing disabled tabs via click
15639 .delegate( "> li", "mousedown" + this.eventNamespace, function( event ) {
15640 if ( $( this ).is( ".ui-state-disabled" ) ) {
15641 event.preventDefault();
15642 }
15643 })
15644
15645 // support: IE <9
15646 // Preventing the default action in mousedown doesn't prevent IE
15647 // from focusing the element, so if the anchor gets focused, blur.
15648 // We don't have to worry about focusing the previously focused
15649 // element since clicking on a non-focusable element should focus
15650 // the body anyway.
15651 .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
15652 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
15653 this.blur();
15654 }
15655 });
15656
15657 this.tabs = this.tablist.find( "> li:has(a[href])" )
15658 .addClass( "ui-state-default ui-corner-top" )
15659 .attr({
15660 role: "tab",
15661 tabIndex: -1
15662 });
15663
15664 this.anchors = this.tabs.map(function() {
15665 return $( "a", this )[ 0 ];
15666 })
15667 .addClass( "ui-tabs-anchor" )
15668 .attr({
15669 role: "presentation",
15670 tabIndex: -1
15671 });
15672
15673 this.panels = $();
15674
15675 this.anchors.each(function( i, anchor ) {
15676 var selector, panel, panelId,
15677 anchorId = $( anchor ).uniqueId().attr( "id" ),
15678 tab = $( anchor ).closest( "li" ),
15679 originalAriaControls = tab.attr( "aria-controls" );
15680
15681 // inline tab
15682 if ( that._isLocal( anchor ) ) {
15683 selector = anchor.hash;
15684 panelId = selector.substring( 1 );
15685 panel = that.element.find( that._sanitizeSelector( selector ) );
15686 // remote tab
15687 } else {
15688 // If the tab doesn't already have aria-controls,
15689 // generate an id by using a throw-away element
15690 panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
15691 selector = "#" + panelId;
15692 panel = that.element.find( selector );
15693 if ( !panel.length ) {
15694 panel = that._createPanel( panelId );
15695 panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
15696 }
15697 panel.attr( "aria-live", "polite" );
15698 }
15699
15700 if ( panel.length) {
15701 that.panels = that.panels.add( panel );
15702 }
15703 if ( originalAriaControls ) {
15704 tab.data( "ui-tabs-aria-controls", originalAriaControls );
15705 }
15706 tab.attr({
15707 "aria-controls": panelId,
15708 "aria-labelledby": anchorId
15709 });
15710 panel.attr( "aria-labelledby", anchorId );
15711 });
15712
15713 this.panels
15714 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
15715 .attr( "role", "tabpanel" );
15716
15717 // Avoid memory leaks (#10056)
15718 if ( prevTabs ) {
15719 this._off( prevTabs.not( this.tabs ) );
15720 this._off( prevAnchors.not( this.anchors ) );
15721 this._off( prevPanels.not( this.panels ) );
15722 }
15723 },
15724
15725 // allow overriding how to find the list for rare usage scenarios (#7715)
15726 _getList: function() {
15727 return this.tablist || this.element.find( "ol,ul" ).eq( 0 );
15728 },
15729
15730 _createPanel: function( id ) {
15731 return $( "<div>" )
15732 .attr( "id", id )
15733 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
15734 .data( "ui-tabs-destroy", true );
15735 },
15736
15737 _setupDisabled: function( disabled ) {
15738 if ( $.isArray( disabled ) ) {
15739 if ( !disabled.length ) {
15740 disabled = false;
15741 } else if ( disabled.length === this.anchors.length ) {
15742 disabled = true;
15743 }
15744 }
15745
15746 // disable tabs
15747 for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
15748 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
15749 $( li )
15750 .addClass( "ui-state-disabled" )
15751 .attr( "aria-disabled", "true" );
15752 } else {
15753 $( li )
15754 .removeClass( "ui-state-disabled" )
15755 .removeAttr( "aria-disabled" );
15756 }
15757 }
15758
15759 this.options.disabled = disabled;
15760 },
15761
15762 _setupEvents: function( event ) {
15763 var events = {};
15764 if ( event ) {
15765 $.each( event.split(" "), function( index, eventName ) {
15766 events[ eventName ] = "_eventHandler";
15767 });
15768 }
15769
15770 this._off( this.anchors.add( this.tabs ).add( this.panels ) );
15771 // Always prevent the default action, even when disabled
15772 this._on( true, this.anchors, {
15773 click: function( event ) {
15774 event.preventDefault();
15775 }
15776 });
15777 this._on( this.anchors, events );
15778 this._on( this.tabs, { keydown: "_tabKeydown" } );
15779 this._on( this.panels, { keydown: "_panelKeydown" } );
15780
15781 this._focusable( this.tabs );
15782 this._hoverable( this.tabs );
15783 },
15784
15785 _setupHeightStyle: function( heightStyle ) {
15786 var maxHeight,
15787 parent = this.element.parent();
15788
15789 if ( heightStyle === "fill" ) {
15790 maxHeight = parent.height();
15791 maxHeight -= this.element.outerHeight() - this.element.height();
15792
15793 this.element.siblings( ":visible" ).each(function() {
15794 var elem = $( this ),
15795 position = elem.css( "position" );
15796
15797 if ( position === "absolute" || position === "fixed" ) {
15798 return;
15799 }
15800 maxHeight -= elem.outerHeight( true );
15801 });
15802
15803 this.element.children().not( this.panels ).each(function() {
15804 maxHeight -= $( this ).outerHeight( true );
15805 });
15806
15807 this.panels.each(function() {
15808 $( this ).height( Math.max( 0, maxHeight -
15809 $( this ).innerHeight() + $( this ).height() ) );
15810 })
15811 .css( "overflow", "auto" );
15812 } else if ( heightStyle === "auto" ) {
15813 maxHeight = 0;
15814 this.panels.each(function() {
15815 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
15816 }).height( maxHeight );
15817 }
15818 },
15819
15820 _eventHandler: function( event ) {
15821 var options = this.options,
15822 active = this.active,
15823 anchor = $( event.currentTarget ),
15824 tab = anchor.closest( "li" ),
15825 clickedIsActive = tab[ 0 ] === active[ 0 ],
15826 collapsing = clickedIsActive && options.collapsible,
15827 toShow = collapsing ? $() : this._getPanelForTab( tab ),
15828 toHide = !active.length ? $() : this._getPanelForTab( active ),
15829 eventData = {
15830 oldTab: active,
15831 oldPanel: toHide,
15832 newTab: collapsing ? $() : tab,
15833 newPanel: toShow
15834 };
15835
15836 event.preventDefault();
15837
15838 if ( tab.hasClass( "ui-state-disabled" ) ||
15839 // tab is already loading
15840 tab.hasClass( "ui-tabs-loading" ) ||
15841 // can't switch durning an animation
15842 this.running ||
15843 // click on active header, but not collapsible
15844 ( clickedIsActive && !options.collapsible ) ||
15845 // allow canceling activation
15846 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
15847 return;
15848 }
15849
15850 options.active = collapsing ? false : this.tabs.index( tab );
15851
15852 this.active = clickedIsActive ? $() : tab;
15853 if ( this.xhr ) {
15854 this.xhr.abort();
15855 }
15856
15857 if ( !toHide.length && !toShow.length ) {
15858 $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
15859 }
15860
15861 if ( toShow.length ) {
15862 this.load( this.tabs.index( tab ), event );
15863 }
15864 this._toggle( event, eventData );
15865 },
15866
15867 // handles show/hide for selecting tabs
15868 _toggle: function( event, eventData ) {
15869 var that = this,
15870 toShow = eventData.newPanel,
15871 toHide = eventData.oldPanel;
15872
15873 this.running = true;
15874
15875 function complete() {
15876 that.running = false;
15877 that._trigger( "activate", event, eventData );
15878 }
15879
15880 function show() {
15881 eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
15882
15883 if ( toShow.length && that.options.show ) {
15884 that._show( toShow, that.options.show, complete );
15885 } else {
15886 toShow.show();
15887 complete();
15888 }
15889 }
15890
15891 // start out by hiding, then showing, then completing
15892 if ( toHide.length && this.options.hide ) {
15893 this._hide( toHide, this.options.hide, function() {
15894 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
15895 show();
15896 });
15897 } else {
15898 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
15899 toHide.hide();
15900 show();
15901 }
15902
15903 toHide.attr( "aria-hidden", "true" );
15904 eventData.oldTab.attr({
15905 "aria-selected": "false",
15906 "aria-expanded": "false"
15907 });
15908 // If we're switching tabs, remove the old tab from the tab order.
15909 // If we're opening from collapsed state, remove the previous tab from the tab order.
15910 // If we're collapsing, then keep the collapsing tab in the tab order.
15911 if ( toShow.length && toHide.length ) {
15912 eventData.oldTab.attr( "tabIndex", -1 );
15913 } else if ( toShow.length ) {
15914 this.tabs.filter(function() {
15915 return $( this ).attr( "tabIndex" ) === 0;
15916 })
15917 .attr( "tabIndex", -1 );
15918 }
15919
15920 toShow.attr( "aria-hidden", "false" );
15921 eventData.newTab.attr({
15922 "aria-selected": "true",
15923 "aria-expanded": "true",
15924 tabIndex: 0
15925 });
15926 },
15927
15928 _activate: function( index ) {
15929 var anchor,
15930 active = this._findActive( index );
15931
15932 // trying to activate the already active panel
15933 if ( active[ 0 ] === this.active[ 0 ] ) {
15934 return;
15935 }
15936
15937 // trying to collapse, simulate a click on the current active header
15938 if ( !active.length ) {
15939 active = this.active;
15940 }
15941
15942 anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
15943 this._eventHandler({
15944 target: anchor,
15945 currentTarget: anchor,
15946 preventDefault: $.noop
15947 });
15948 },
15949
15950 _findActive: function( index ) {
15951 return index === false ? $() : this.tabs.eq( index );
15952 },
15953
15954 _getIndex: function( index ) {
15955 // meta-function to give users option to provide a href string instead of a numerical index.
15956 if ( typeof index === "string" ) {
15957 index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
15958 }
15959
15960 return index;
15961 },
15962
15963 _destroy: function() {
15964 if ( this.xhr ) {
15965 this.xhr.abort();
15966 }
15967
15968 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
15969
15970 this.tablist
15971 .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
15972 .removeAttr( "role" );
15973
15974 this.anchors
15975 .removeClass( "ui-tabs-anchor" )
15976 .removeAttr( "role" )
15977 .removeAttr( "tabIndex" )
15978 .removeUniqueId();
15979
15980 this.tablist.unbind( this.eventNamespace );
15981
15982 this.tabs.add( this.panels ).each(function() {
15983 if ( $.data( this, "ui-tabs-destroy" ) ) {
15984 $( this ).remove();
15985 } else {
15986 $( this )
15987 .removeClass( "ui-state-default ui-state-active ui-state-disabled " +
15988 "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
15989 .removeAttr( "tabIndex" )
15990 .removeAttr( "aria-live" )
15991 .removeAttr( "aria-busy" )
15992 .removeAttr( "aria-selected" )
15993 .removeAttr( "aria-labelledby" )
15994 .removeAttr( "aria-hidden" )
15995 .removeAttr( "aria-expanded" )
15996 .removeAttr( "role" );
15997 }
15998 });
15999
16000 this.tabs.each(function() {
16001 var li = $( this ),
16002 prev = li.data( "ui-tabs-aria-controls" );
16003 if ( prev ) {
16004 li
16005 .attr( "aria-controls", prev )
16006 .removeData( "ui-tabs-aria-controls" );
16007 } else {
16008 li.removeAttr( "aria-controls" );
16009 }
16010 });
16011
16012 this.panels.show();
16013
16014 if ( this.options.heightStyle !== "content" ) {
16015 this.panels.css( "height", "" );
16016 }
16017 },
16018
16019 enable: function( index ) {
16020 var disabled = this.options.disabled;
16021 if ( disabled === false ) {
16022 return;
16023 }
16024
16025 if ( index === undefined ) {
16026 disabled = false;
16027 } else {
16028 index = this._getIndex( index );
16029 if ( $.isArray( disabled ) ) {
16030 disabled = $.map( disabled, function( num ) {
16031 return num !== index ? num : null;
16032 });
16033 } else {
16034 disabled = $.map( this.tabs, function( li, num ) {
16035 return num !== index ? num : null;
16036 });
16037 }
16038 }
16039 this._setupDisabled( disabled );
16040 },
16041
16042 disable: function( index ) {
16043 var disabled = this.options.disabled;
16044 if ( disabled === true ) {
16045 return;
16046 }
16047
16048 if ( index === undefined ) {
16049 disabled = true;
16050 } else {
16051 index = this._getIndex( index );
16052 if ( $.inArray( index, disabled ) !== -1 ) {
16053 return;
16054 }
16055 if ( $.isArray( disabled ) ) {
16056 disabled = $.merge( [ index ], disabled ).sort();
16057 } else {
16058 disabled = [ index ];
16059 }
16060 }
16061 this._setupDisabled( disabled );
16062 },
16063
16064 load: function( index, event ) {
16065 index = this._getIndex( index );
16066 var that = this,
16067 tab = this.tabs.eq( index ),
16068 anchor = tab.find( ".ui-tabs-anchor" ),
16069 panel = this._getPanelForTab( tab ),
16070 eventData = {
16071 tab: tab,
16072 panel: panel
16073 };
16074
16075 // not remote
16076 if ( this._isLocal( anchor[ 0 ] ) ) {
16077 return;
16078 }
16079
16080 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
16081
16082 // support: jQuery <1.8
16083 // jQuery <1.8 returns false if the request is canceled in beforeSend,
16084 // but as of 1.8, $.ajax() always returns a jqXHR object.
16085 if ( this.xhr && this.xhr.statusText !== "canceled" ) {
16086 tab.addClass( "ui-tabs-loading" );
16087 panel.attr( "aria-busy", "true" );
16088
16089 this.xhr
16090 .success(function( response ) {
16091 // support: jQuery <1.8
16092 // http://bugs.jquery.com/ticket/11778
16093 setTimeout(function() {
16094 panel.html( response );
16095 that._trigger( "load", event, eventData );
16096 }, 1 );
16097 })
16098 .complete(function( jqXHR, status ) {
16099 // support: jQuery <1.8
16100 // http://bugs.jquery.com/ticket/11778
16101 setTimeout(function() {
16102 if ( status === "abort" ) {
16103 that.panels.stop( false, true );
16104 }
16105
16106 tab.removeClass( "ui-tabs-loading" );
16107 panel.removeAttr( "aria-busy" );
16108
16109 if ( jqXHR === that.xhr ) {
16110 delete that.xhr;
16111 }
16112 }, 1 );
16113 });
16114 }
16115 },
16116
16117 _ajaxSettings: function( anchor, event, eventData ) {
16118 var that = this;
16119 return {
16120 url: anchor.attr( "href" ),
16121 beforeSend: function( jqXHR, settings ) {
16122 return that._trigger( "beforeLoad", event,
16123 $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
16124 }
16125 };
16126 },
16127
16128 _getPanelForTab: function( tab ) {
16129 var id = $( tab ).attr( "aria-controls" );
16130 return this.element.find( this._sanitizeSelector( "#" + id ) );
16131 }
16132});
16133
16134
16135/*!
16136 * jQuery UI Tooltip 1.11.2
16137 * http://jqueryui.com
16138 *
16139 * Copyright 2014 jQuery Foundation and other contributors
16140 * Released under the MIT license.
16141 * http://jquery.org/license
16142 *
16143 * http://api.jqueryui.com/tooltip/
16144 */
16145
16146
16147var tooltip = $.widget( "ui.tooltip", {
16148 version: "1.11.2",
16149 options: {
16150 content: function() {
16151 // support: IE<9, Opera in jQuery <1.7
16152 // .text() can't accept undefined, so coerce to a string
16153 var title = $( this ).attr( "title" ) || "";
16154 // Escape title, since we're going from an attribute to raw HTML
16155 return $( "<a>" ).text( title ).html();
16156 },
16157 hide: true,
16158 // Disabled elements have inconsistent behavior across browsers (#8661)
16159 items: "[title]:not([disabled])",
16160 position: {
16161 my: "left top+15",
16162 at: "left bottom",
16163 collision: "flipfit flip"
16164 },
16165 show: true,
16166 tooltipClass: null,
16167 track: false,
16168
16169 // callbacks
16170 close: null,
16171 open: null
16172 },
16173
16174 _addDescribedBy: function( elem, id ) {
16175 var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
16176 describedby.push( id );
16177 elem
16178 .data( "ui-tooltip-id", id )
16179 .attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
16180 },
16181
16182 _removeDescribedBy: function( elem ) {
16183 var id = elem.data( "ui-tooltip-id" ),
16184 describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
16185 index = $.inArray( id, describedby );
16186
16187 if ( index !== -1 ) {
16188 describedby.splice( index, 1 );
16189 }
16190
16191 elem.removeData( "ui-tooltip-id" );
16192 describedby = $.trim( describedby.join( " " ) );
16193 if ( describedby ) {
16194 elem.attr( "aria-describedby", describedby );
16195 } else {
16196 elem.removeAttr( "aria-describedby" );
16197 }
16198 },
16199
16200 _create: function() {
16201 this._on({
16202 mouseover: "open",
16203 focusin: "open"
16204 });
16205
16206 // IDs of generated tooltips, needed for destroy
16207 this.tooltips = {};
16208
16209 // IDs of parent tooltips where we removed the title attribute
16210 this.parents = {};
16211
16212 if ( this.options.disabled ) {
16213 this._disable();
16214 }
16215
16216 // Append the aria-live region so tooltips announce correctly
16217 this.liveRegion = $( "<div>" )
16218 .attr({
16219 role: "log",
16220 "aria-live": "assertive",
16221 "aria-relevant": "additions"
16222 })
16223 .addClass( "ui-helper-hidden-accessible" )
16224 .appendTo( this.document[ 0 ].body );
16225 },
16226
16227 _setOption: function( key, value ) {
16228 var that = this;
16229
16230 if ( key === "disabled" ) {
16231 this[ value ? "_disable" : "_enable" ]();
16232 this.options[ key ] = value;
16233 // disable element style changes
16234 return;
16235 }
16236
16237 this._super( key, value );
16238
16239 if ( key === "content" ) {
16240 $.each( this.tooltips, function( id, tooltipData ) {
16241 that._updateContent( tooltipData.element );
16242 });
16243 }
16244 },
16245
16246 _disable: function() {
16247 var that = this;
16248
16249 // close open tooltips
16250 $.each( this.tooltips, function( id, tooltipData ) {
16251 var event = $.Event( "blur" );
16252 event.target = event.currentTarget = tooltipData.element[ 0 ];
16253 that.close( event, true );
16254 });
16255
16256 // remove title attributes to prevent native tooltips
16257 this.element.find( this.options.items ).addBack().each(function() {
16258 var element = $( this );
16259 if ( element.is( "[title]" ) ) {
16260 element
16261 .data( "ui-tooltip-title", element.attr( "title" ) )
16262 .removeAttr( "title" );
16263 }
16264 });
16265 },
16266
16267 _enable: function() {
16268 // restore title attributes
16269 this.element.find( this.options.items ).addBack().each(function() {
16270 var element = $( this );
16271 if ( element.data( "ui-tooltip-title" ) ) {
16272 element.attr( "title", element.data( "ui-tooltip-title" ) );
16273 }
16274 });
16275 },
16276
16277 open: function( event ) {
16278 var that = this,
16279 target = $( event ? event.target : this.element )
16280 // we need closest here due to mouseover bubbling,
16281 // but always pointing at the same event target
16282 .closest( this.options.items );
16283
16284 // No element to show a tooltip for or the tooltip is already open
16285 if ( !target.length || target.data( "ui-tooltip-id" ) ) {
16286 return;
16287 }
16288
16289 if ( target.attr( "title" ) ) {
16290 target.data( "ui-tooltip-title", target.attr( "title" ) );
16291 }
16292
16293 target.data( "ui-tooltip-open", true );
16294
16295 // kill parent tooltips, custom or native, for hover
16296 if ( event && event.type === "mouseover" ) {
16297 target.parents().each(function() {
16298 var parent = $( this ),
16299 blurEvent;
16300 if ( parent.data( "ui-tooltip-open" ) ) {
16301 blurEvent = $.Event( "blur" );
16302 blurEvent.target = blurEvent.currentTarget = this;
16303 that.close( blurEvent, true );
16304 }
16305 if ( parent.attr( "title" ) ) {
16306 parent.uniqueId();
16307 that.parents[ this.id ] = {
16308 element: this,
16309 title: parent.attr( "title" )
16310 };
16311 parent.attr( "title", "" );
16312 }
16313 });
16314 }
16315
16316 this._updateContent( target, event );
16317 },
16318
16319 _updateContent: function( target, event ) {
16320 var content,
16321 contentOption = this.options.content,
16322 that = this,
16323 eventType = event ? event.type : null;
16324
16325 if ( typeof contentOption === "string" ) {
16326 return this._open( event, target, contentOption );
16327 }
16328
16329 content = contentOption.call( target[0], function( response ) {
16330 // ignore async response if tooltip was closed already
16331 if ( !target.data( "ui-tooltip-open" ) ) {
16332 return;
16333 }
16334 // IE may instantly serve a cached response for ajax requests
16335 // delay this call to _open so the other call to _open runs first
16336 that._delay(function() {
16337 // jQuery creates a special event for focusin when it doesn't
16338 // exist natively. To improve performance, the native event
16339 // object is reused and the type is changed. Therefore, we can't
16340 // rely on the type being correct after the event finished
16341 // bubbling, so we set it back to the previous value. (#8740)
16342 if ( event ) {
16343 event.type = eventType;
16344 }
16345 this._open( event, target, response );
16346 });
16347 });
16348 if ( content ) {
16349 this._open( event, target, content );
16350 }
16351 },
16352
16353 _open: function( event, target, content ) {
16354 var tooltipData, tooltip, events, delayedShow, a11yContent,
16355 positionOption = $.extend( {}, this.options.position );
16356
16357 if ( !content ) {
16358 return;
16359 }
16360
16361 // Content can be updated multiple times. If the tooltip already
16362 // exists, then just update the content and bail.
16363 tooltipData = this._find( target );
16364 if ( tooltipData ) {
16365 tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
16366 return;
16367 }
16368
16369 // if we have a title, clear it to prevent the native tooltip
16370 // we have to check first to avoid defining a title if none exists
16371 // (we don't want to cause an element to start matching [title])
16372 //
16373 // We use removeAttr only for key events, to allow IE to export the correct
16374 // accessible attributes. For mouse events, set to empty string to avoid
16375 // native tooltip showing up (happens only when removing inside mouseover).
16376 if ( target.is( "[title]" ) ) {
16377 if ( event && event.type === "mouseover" ) {
16378 target.attr( "title", "" );
16379 } else {
16380 target.removeAttr( "title" );
16381 }
16382 }
16383
16384 tooltipData = this._tooltip( target );
16385 tooltip = tooltipData.tooltip;
16386 this._addDescribedBy( target, tooltip.attr( "id" ) );
16387 tooltip.find( ".ui-tooltip-content" ).html( content );
16388
16389 // Support: Voiceover on OS X, JAWS on IE <= 9
16390 // JAWS announces deletions even when aria-relevant="additions"
16391 // Voiceover will sometimes re-read the entire log region's contents from the beginning
16392 this.liveRegion.children().hide();
16393 if ( content.clone ) {
16394 a11yContent = content.clone();
16395 a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
16396 } else {
16397 a11yContent = content;
16398 }
16399 $( "<div>" ).html( a11yContent ).appendTo( this.liveRegion );
16400
16401 function position( event ) {
16402 positionOption.of = event;
16403 if ( tooltip.is( ":hidden" ) ) {
16404 return;
16405 }
16406 tooltip.position( positionOption );
16407 }
16408 if ( this.options.track && event && /^mouse/.test( event.type ) ) {
16409 this._on( this.document, {
16410 mousemove: position
16411 });
16412 // trigger once to override element-relative positioning
16413 position( event );
16414 } else {
16415 tooltip.position( $.extend({
16416 of: target
16417 }, this.options.position ) );
16418 }
16419
16420 tooltip.hide();
16421
16422 this._show( tooltip, this.options.show );
16423 // Handle tracking tooltips that are shown with a delay (#8644). As soon
16424 // as the tooltip is visible, position the tooltip using the most recent
16425 // event.
16426 if ( this.options.show && this.options.show.delay ) {
16427 delayedShow = this.delayedShow = setInterval(function() {
16428 if ( tooltip.is( ":visible" ) ) {
16429 position( positionOption.of );
16430 clearInterval( delayedShow );
16431 }
16432 }, $.fx.interval );
16433 }
16434
16435 this._trigger( "open", event, { tooltip: tooltip } );
16436
16437 events = {
16438 keyup: function( event ) {
16439 if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
16440 var fakeEvent = $.Event(event);
16441 fakeEvent.currentTarget = target[0];
16442 this.close( fakeEvent, true );
16443 }
16444 }
16445 };
16446
16447 // Only bind remove handler for delegated targets. Non-delegated
16448 // tooltips will handle this in destroy.
16449 if ( target[ 0 ] !== this.element[ 0 ] ) {
16450 events.remove = function() {
16451 this._removeTooltip( tooltip );
16452 };
16453 }
16454
16455 if ( !event || event.type === "mouseover" ) {
16456 events.mouseleave = "close";
16457 }
16458 if ( !event || event.type === "focusin" ) {
16459 events.focusout = "close";
16460 }
16461 this._on( true, target, events );
16462 },
16463
16464 close: function( event ) {
16465 var tooltip,
16466 that = this,
16467 target = $( event ? event.currentTarget : this.element ),
16468 tooltipData = this._find( target );
16469
16470 // The tooltip may already be closed
16471 if ( !tooltipData ) {
16472 return;
16473 }
16474
16475 tooltip = tooltipData.tooltip;
16476
16477 // disabling closes the tooltip, so we need to track when we're closing
16478 // to avoid an infinite loop in case the tooltip becomes disabled on close
16479 if ( tooltipData.closing ) {
16480 return;
16481 }
16482
16483 // Clear the interval for delayed tracking tooltips
16484 clearInterval( this.delayedShow );
16485
16486 // only set title if we had one before (see comment in _open())
16487 // If the title attribute has changed since open(), don't restore
16488 if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
16489 target.attr( "title", target.data( "ui-tooltip-title" ) );
16490 }
16491
16492 this._removeDescribedBy( target );
16493
16494 tooltipData.hiding = true;
16495 tooltip.stop( true );
16496 this._hide( tooltip, this.options.hide, function() {
16497 that._removeTooltip( $( this ) );
16498 });
16499
16500 target.removeData( "ui-tooltip-open" );
16501 this._off( target, "mouseleave focusout keyup" );
16502
16503 // Remove 'remove' binding only on delegated targets
16504 if ( target[ 0 ] !== this.element[ 0 ] ) {
16505 this._off( target, "remove" );
16506 }
16507 this._off( this.document, "mousemove" );
16508
16509 if ( event && event.type === "mouseleave" ) {
16510 $.each( this.parents, function( id, parent ) {
16511 $( parent.element ).attr( "title", parent.title );
16512 delete that.parents[ id ];
16513 });
16514 }
16515
16516 tooltipData.closing = true;
16517 this._trigger( "close", event, { tooltip: tooltip } );
16518 if ( !tooltipData.hiding ) {
16519 tooltipData.closing = false;
16520 }
16521 },
16522
16523 _tooltip: function( element ) {
16524 var tooltip = $( "<div>" )
16525 .attr( "role", "tooltip" )
16526 .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
16527 ( this.options.tooltipClass || "" ) ),
16528 id = tooltip.uniqueId().attr( "id" );
16529
16530 $( "<div>" )
16531 .addClass( "ui-tooltip-content" )
16532 .appendTo( tooltip );
16533
16534 tooltip.appendTo( this.document[0].body );
16535
16536 return this.tooltips[ id ] = {
16537 element: element,
16538 tooltip: tooltip
16539 };
16540 },
16541
16542 _find: function( target ) {
16543 var id = target.data( "ui-tooltip-id" );
16544 return id ? this.tooltips[ id ] : null;
16545 },
16546
16547 _removeTooltip: function( tooltip ) {
16548 tooltip.remove();
16549 delete this.tooltips[ tooltip.attr( "id" ) ];
16550 },
16551
16552 _destroy: function() {
16553 var that = this;
16554
16555 // close open tooltips
16556 $.each( this.tooltips, function( id, tooltipData ) {
16557 // Delegate to close method to handle common cleanup
16558 var event = $.Event( "blur" ),
16559 element = tooltipData.element;
16560 event.target = event.currentTarget = element[ 0 ];
16561 that.close( event, true );
16562
16563 // Remove immediately; destroying an open tooltip doesn't use the
16564 // hide animation
16565 $( "#" + id ).remove();
16566
16567 // Restore the title
16568 if ( element.data( "ui-tooltip-title" ) ) {
16569 // If the title attribute has changed since open(), don't restore
16570 if ( !element.attr( "title" ) ) {
16571 element.attr( "title", element.data( "ui-tooltip-title" ) );
16572 }
16573 element.removeData( "ui-tooltip-title" );
16574 }
16575 });
16576 this.liveRegion.remove();
16577 }
16578});
16579
16580
16581
16582}));