summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/toastergui/static/js/jquery-ui.js
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/toaster/toastergui/static/js/jquery-ui.js')
-rw-r--r--bitbake/lib/toaster/toastergui/static/js/jquery-ui.js15003
1 files changed, 15003 insertions, 0 deletions
diff --git a/bitbake/lib/toaster/toastergui/static/js/jquery-ui.js b/bitbake/lib/toaster/toastergui/static/js/jquery-ui.js
new file mode 100644
index 0000000000..7b727e7435
--- /dev/null
+++ b/bitbake/lib/toaster/toastergui/static/js/jquery-ui.js
@@ -0,0 +1,15003 @@
1/*! jQuery UI - v1.10.3 - 2013-05-03
2* http://jqueryui.com
3* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.effect.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js, jquery.ui.menu.js, jquery.ui.position.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js
4* Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
5(function( $, undefined ) {
6
7var uuid = 0,
8 runiqueId = /^ui-id-\d+$/;
9
10// $.ui might exist from components with no dependencies, e.g., $.ui.position
11$.ui = $.ui || {};
12
13$.extend( $.ui, {
14 version: "1.10.3",
15
16 keyCode: {
17 BACKSPACE: 8,
18 COMMA: 188,
19 DELETE: 46,
20 DOWN: 40,
21 END: 35,
22 ENTER: 13,
23 ESCAPE: 27,
24 HOME: 36,
25 LEFT: 37,
26 NUMPAD_ADD: 107,
27 NUMPAD_DECIMAL: 110,
28 NUMPAD_DIVIDE: 111,
29 NUMPAD_ENTER: 108,
30 NUMPAD_MULTIPLY: 106,
31 NUMPAD_SUBTRACT: 109,
32 PAGE_DOWN: 34,
33 PAGE_UP: 33,
34 PERIOD: 190,
35 RIGHT: 39,
36 SPACE: 32,
37 TAB: 9,
38 UP: 38
39 }
40});
41
42// plugins
43$.fn.extend({
44 focus: (function( orig ) {
45 return function( delay, fn ) {
46 return typeof delay === "number" ?
47 this.each(function() {
48 var elem = this;
49 setTimeout(function() {
50 $( elem ).focus();
51 if ( fn ) {
52 fn.call( elem );
53 }
54 }, delay );
55 }) :
56 orig.apply( this, arguments );
57 };
58 })( $.fn.focus ),
59
60 scrollParent: function() {
61 var scrollParent;
62 if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {
63 scrollParent = this.parents().filter(function() {
64 return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
65 }).eq(0);
66 } else {
67 scrollParent = this.parents().filter(function() {
68 return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
69 }).eq(0);
70 }
71
72 return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent;
73 },
74
75 zIndex: function( zIndex ) {
76 if ( zIndex !== undefined ) {
77 return this.css( "zIndex", zIndex );
78 }
79
80 if ( this.length ) {
81 var elem = $( this[ 0 ] ), position, value;
82 while ( elem.length && elem[ 0 ] !== document ) {
83 // Ignore z-index if position is set to a value where z-index is ignored by the browser
84 // This makes behavior of this function consistent across browsers
85 // WebKit always returns auto if the element is positioned
86 position = elem.css( "position" );
87 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
88 // IE returns 0 when zIndex is not specified
89 // other browsers return a string
90 // we ignore the case of nested elements with an explicit value of 0
91 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
92 value = parseInt( elem.css( "zIndex" ), 10 );
93 if ( !isNaN( value ) && value !== 0 ) {
94 return value;
95 }
96 }
97 elem = elem.parent();
98 }
99 }
100
101 return 0;
102 },
103
104 uniqueId: function() {
105 return this.each(function() {
106 if ( !this.id ) {
107 this.id = "ui-id-" + (++uuid);
108 }
109 });
110 },
111
112 removeUniqueId: function() {
113 return this.each(function() {
114 if ( runiqueId.test( this.id ) ) {
115 $( this ).removeAttr( "id" );
116 }
117 });
118 }
119});
120
121// selectors
122function focusable( element, isTabIndexNotNaN ) {
123 var map, mapName, img,
124 nodeName = element.nodeName.toLowerCase();
125 if ( "area" === nodeName ) {
126 map = element.parentNode;
127 mapName = map.name;
128 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
129 return false;
130 }
131 img = $( "img[usemap=#" + mapName + "]" )[0];
132 return !!img && visible( img );
133 }
134 return ( /input|select|textarea|button|object/.test( nodeName ) ?
135 !element.disabled :
136 "a" === nodeName ?
137 element.href || isTabIndexNotNaN :
138 isTabIndexNotNaN) &&
139 // the element and all of its ancestors must be visible
140 visible( element );
141}
142
143function visible( element ) {
144 return $.expr.filters.visible( element ) &&
145 !$( element ).parents().addBack().filter(function() {
146 return $.css( this, "visibility" ) === "hidden";
147 }).length;
148}
149
150$.extend( $.expr[ ":" ], {
151 data: $.expr.createPseudo ?
152 $.expr.createPseudo(function( dataName ) {
153 return function( elem ) {
154 return !!$.data( elem, dataName );
155 };
156 }) :
157 // support: jQuery <1.8
158 function( elem, i, match ) {
159 return !!$.data( elem, match[ 3 ] );
160 },
161
162 focusable: function( element ) {
163 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
164 },
165
166 tabbable: function( element ) {
167 var tabIndex = $.attr( element, "tabindex" ),
168 isTabIndexNaN = isNaN( tabIndex );
169 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
170 }
171});
172
173// support: jQuery <1.8
174if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
175 $.each( [ "Width", "Height" ], function( i, name ) {
176 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
177 type = name.toLowerCase(),
178 orig = {
179 innerWidth: $.fn.innerWidth,
180 innerHeight: $.fn.innerHeight,
181 outerWidth: $.fn.outerWidth,
182 outerHeight: $.fn.outerHeight
183 };
184
185 function reduce( elem, size, border, margin ) {
186 $.each( side, function() {
187 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
188 if ( border ) {
189 size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
190 }
191 if ( margin ) {
192 size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
193 }
194 });
195 return size;
196 }
197
198 $.fn[ "inner" + name ] = function( size ) {
199 if ( size === undefined ) {
200 return orig[ "inner" + name ].call( this );
201 }
202
203 return this.each(function() {
204 $( this ).css( type, reduce( this, size ) + "px" );
205 });
206 };
207
208 $.fn[ "outer" + name] = function( size, margin ) {
209 if ( typeof size !== "number" ) {
210 return orig[ "outer" + name ].call( this, size );
211 }
212
213 return this.each(function() {
214 $( this).css( type, reduce( this, size, true, margin ) + "px" );
215 });
216 };
217 });
218}
219
220// support: jQuery <1.8
221if ( !$.fn.addBack ) {
222 $.fn.addBack = function( selector ) {
223 return this.add( selector == null ?
224 this.prevObject : this.prevObject.filter( selector )
225 );
226 };
227}
228
229// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
230if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
231 $.fn.removeData = (function( removeData ) {
232 return function( key ) {
233 if ( arguments.length ) {
234 return removeData.call( this, $.camelCase( key ) );
235 } else {
236 return removeData.call( this );
237 }
238 };
239 })( $.fn.removeData );
240}
241
242
243
244
245
246// deprecated
247$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
248
249$.support.selectstart = "onselectstart" in document.createElement( "div" );
250$.fn.extend({
251 disableSelection: function() {
252 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
253 ".ui-disableSelection", function( event ) {
254 event.preventDefault();
255 });
256 },
257
258 enableSelection: function() {
259 return this.unbind( ".ui-disableSelection" );
260 }
261});
262
263$.extend( $.ui, {
264 // $.ui.plugin is deprecated. Use $.widget() extensions instead.
265 plugin: {
266 add: function( module, option, set ) {
267 var i,
268 proto = $.ui[ module ].prototype;
269 for ( i in set ) {
270 proto.plugins[ i ] = proto.plugins[ i ] || [];
271 proto.plugins[ i ].push( [ option, set[ i ] ] );
272 }
273 },
274 call: function( instance, name, args ) {
275 var i,
276 set = instance.plugins[ name ];
277 if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
278 return;
279 }
280
281 for ( i = 0; i < set.length; i++ ) {
282 if ( instance.options[ set[ i ][ 0 ] ] ) {
283 set[ i ][ 1 ].apply( instance.element, args );
284 }
285 }
286 }
287 },
288
289 // only used by resizable
290 hasScroll: function( el, a ) {
291
292 //If overflow is hidden, the element might have extra content, but the user wants to hide it
293 if ( $( el ).css( "overflow" ) === "hidden") {
294 return false;
295 }
296
297 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
298 has = false;
299
300 if ( el[ scroll ] > 0 ) {
301 return true;
302 }
303
304 // TODO: determine which cases actually cause this to happen
305 // if the element doesn't have the scroll set, see if it's possible to
306 // set the scroll
307 el[ scroll ] = 1;
308 has = ( el[ scroll ] > 0 );
309 el[ scroll ] = 0;
310 return has;
311 }
312});
313
314})( jQuery );
315
316(function( $, undefined ) {
317
318var uuid = 0,
319 slice = Array.prototype.slice,
320 _cleanData = $.cleanData;
321$.cleanData = function( elems ) {
322 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
323 try {
324 $( elem ).triggerHandler( "remove" );
325 // http://bugs.jquery.com/ticket/8235
326 } catch( e ) {}
327 }
328 _cleanData( elems );
329};
330
331$.widget = function( name, base, prototype ) {
332 var fullName, existingConstructor, constructor, basePrototype,
333 // proxiedPrototype allows the provided prototype to remain unmodified
334 // so that it can be used as a mixin for multiple widgets (#8876)
335 proxiedPrototype = {},
336 namespace = name.split( "." )[ 0 ];
337
338 name = name.split( "." )[ 1 ];
339 fullName = namespace + "-" + name;
340
341 if ( !prototype ) {
342 prototype = base;
343 base = $.Widget;
344 }
345
346 // create selector for plugin
347 $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
348 return !!$.data( elem, fullName );
349 };
350
351 $[ namespace ] = $[ namespace ] || {};
352 existingConstructor = $[ namespace ][ name ];
353 constructor = $[ namespace ][ name ] = function( options, element ) {
354 // allow instantiation without "new" keyword
355 if ( !this._createWidget ) {
356 return new constructor( options, element );
357 }
358
359 // allow instantiation without initializing for simple inheritance
360 // must use "new" keyword (the code above always passes args)
361 if ( arguments.length ) {
362 this._createWidget( options, element );
363 }
364 };
365 // extend with the existing constructor to carry over any static properties
366 $.extend( constructor, existingConstructor, {
367 version: prototype.version,
368 // copy the object used to create the prototype in case we need to
369 // redefine the widget later
370 _proto: $.extend( {}, prototype ),
371 // track widgets that inherit from this widget in case this widget is
372 // redefined after a widget inherits from it
373 _childConstructors: []
374 });
375
376 basePrototype = new base();
377 // we need to make the options hash a property directly on the new instance
378 // otherwise we'll modify the options hash on the prototype that we're
379 // inheriting from
380 basePrototype.options = $.widget.extend( {}, basePrototype.options );
381 $.each( prototype, function( prop, value ) {
382 if ( !$.isFunction( value ) ) {
383 proxiedPrototype[ prop ] = value;
384 return;
385 }
386 proxiedPrototype[ prop ] = (function() {
387 var _super = function() {
388 return base.prototype[ prop ].apply( this, arguments );
389 },
390 _superApply = function( args ) {
391 return base.prototype[ prop ].apply( this, args );
392 };
393 return function() {
394 var __super = this._super,
395 __superApply = this._superApply,
396 returnValue;
397
398 this._super = _super;
399 this._superApply = _superApply;
400
401 returnValue = value.apply( this, arguments );
402
403 this._super = __super;
404 this._superApply = __superApply;
405
406 return returnValue;
407 };
408 })();
409 });
410 constructor.prototype = $.widget.extend( basePrototype, {
411 // TODO: remove support for widgetEventPrefix
412 // always use the name + a colon as the prefix, e.g., draggable:start
413 // don't prefix for widgets that aren't DOM-based
414 widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
415 }, proxiedPrototype, {
416 constructor: constructor,
417 namespace: namespace,
418 widgetName: name,
419 widgetFullName: fullName
420 });
421
422 // If this widget is being redefined then we need to find all widgets that
423 // are inheriting from it and redefine all of them so that they inherit from
424 // the new version of this widget. We're essentially trying to replace one
425 // level in the prototype chain.
426 if ( existingConstructor ) {
427 $.each( existingConstructor._childConstructors, function( i, child ) {
428 var childPrototype = child.prototype;
429
430 // redefine the child widget using the same prototype that was
431 // originally used, but inherit from the new version of the base
432 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
433 });
434 // remove the list of existing child constructors from the old constructor
435 // so the old child constructors can be garbage collected
436 delete existingConstructor._childConstructors;
437 } else {
438 base._childConstructors.push( constructor );
439 }
440
441 $.widget.bridge( name, constructor );
442};
443
444$.widget.extend = function( target ) {
445 var input = slice.call( arguments, 1 ),
446 inputIndex = 0,
447 inputLength = input.length,
448 key,
449 value;
450 for ( ; inputIndex < inputLength; inputIndex++ ) {
451 for ( key in input[ inputIndex ] ) {
452 value = input[ inputIndex ][ key ];
453 if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
454 // Clone objects
455 if ( $.isPlainObject( value ) ) {
456 target[ key ] = $.isPlainObject( target[ key ] ) ?
457 $.widget.extend( {}, target[ key ], value ) :
458 // Don't extend strings, arrays, etc. with objects
459 $.widget.extend( {}, value );
460 // Copy everything else by reference
461 } else {
462 target[ key ] = value;
463 }
464 }
465 }
466 }
467 return target;
468};
469
470$.widget.bridge = function( name, object ) {
471 var fullName = object.prototype.widgetFullName || name;
472 $.fn[ name ] = function( options ) {
473 var isMethodCall = typeof options === "string",
474 args = slice.call( arguments, 1 ),
475 returnValue = this;
476
477 // allow multiple hashes to be passed on init
478 options = !isMethodCall && args.length ?
479 $.widget.extend.apply( null, [ options ].concat(args) ) :
480 options;
481
482 if ( isMethodCall ) {
483 this.each(function() {
484 var methodValue,
485 instance = $.data( this, fullName );
486 if ( !instance ) {
487 return $.error( "cannot call methods on " + name + " prior to initialization; " +
488 "attempted to call method '" + options + "'" );
489 }
490 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
491 return $.error( "no such method '" + options + "' for " + name + " widget instance" );
492 }
493 methodValue = instance[ options ].apply( instance, args );
494 if ( methodValue !== instance && methodValue !== undefined ) {
495 returnValue = methodValue && methodValue.jquery ?
496 returnValue.pushStack( methodValue.get() ) :
497 methodValue;
498 return false;
499 }
500 });
501 } else {
502 this.each(function() {
503 var instance = $.data( this, fullName );
504 if ( instance ) {
505 instance.option( options || {} )._init();
506 } else {
507 $.data( this, fullName, new object( options, this ) );
508 }
509 });
510 }
511
512 return returnValue;
513 };
514};
515
516$.Widget = function( /* options, element */ ) {};
517$.Widget._childConstructors = [];
518
519$.Widget.prototype = {
520 widgetName: "widget",
521 widgetEventPrefix: "",
522 defaultElement: "<div>",
523 options: {
524 disabled: false,
525
526 // callbacks
527 create: null
528 },
529 _createWidget: function( options, element ) {
530 element = $( element || this.defaultElement || this )[ 0 ];
531 this.element = $( element );
532 this.uuid = uuid++;
533 this.eventNamespace = "." + this.widgetName + this.uuid;
534 this.options = $.widget.extend( {},
535 this.options,
536 this._getCreateOptions(),
537 options );
538
539 this.bindings = $();
540 this.hoverable = $();
541 this.focusable = $();
542
543 if ( element !== this ) {
544 $.data( element, this.widgetFullName, this );
545 this._on( true, this.element, {
546 remove: function( event ) {
547 if ( event.target === element ) {
548 this.destroy();
549 }
550 }
551 });
552 this.document = $( element.style ?
553 // element within the document
554 element.ownerDocument :
555 // element is window or document
556 element.document || element );
557 this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
558 }
559
560 this._create();
561 this._trigger( "create", null, this._getCreateEventData() );
562 this._init();
563 },
564 _getCreateOptions: $.noop,
565 _getCreateEventData: $.noop,
566 _create: $.noop,
567 _init: $.noop,
568
569 destroy: function() {
570 this._destroy();
571 // we can probably remove the unbind calls in 2.0
572 // all event bindings should go through this._on()
573 this.element
574 .unbind( this.eventNamespace )
575 // 1.9 BC for #7810
576 // TODO remove dual storage
577 .removeData( this.widgetName )
578 .removeData( this.widgetFullName )
579 // support: jquery <1.6.3
580 // http://bugs.jquery.com/ticket/9413
581 .removeData( $.camelCase( this.widgetFullName ) );
582 this.widget()
583 .unbind( this.eventNamespace )
584 .removeAttr( "aria-disabled" )
585 .removeClass(
586 this.widgetFullName + "-disabled " +
587 "ui-state-disabled" );
588
589 // clean up events and states
590 this.bindings.unbind( this.eventNamespace );
591 this.hoverable.removeClass( "ui-state-hover" );
592 this.focusable.removeClass( "ui-state-focus" );
593 },
594 _destroy: $.noop,
595
596 widget: function() {
597 return this.element;
598 },
599
600 option: function( key, value ) {
601 var options = key,
602 parts,
603 curOption,
604 i;
605
606 if ( arguments.length === 0 ) {
607 // don't return a reference to the internal hash
608 return $.widget.extend( {}, this.options );
609 }
610
611 if ( typeof key === "string" ) {
612 // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
613 options = {};
614 parts = key.split( "." );
615 key = parts.shift();
616 if ( parts.length ) {
617 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
618 for ( i = 0; i < parts.length - 1; i++ ) {
619 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
620 curOption = curOption[ parts[ i ] ];
621 }
622 key = parts.pop();
623 if ( value === undefined ) {
624 return curOption[ key ] === undefined ? null : curOption[ key ];
625 }
626 curOption[ key ] = value;
627 } else {
628 if ( value === undefined ) {
629 return this.options[ key ] === undefined ? null : this.options[ key ];
630 }
631 options[ key ] = value;
632 }
633 }
634
635 this._setOptions( options );
636
637 return this;
638 },
639 _setOptions: function( options ) {
640 var key;
641
642 for ( key in options ) {
643 this._setOption( key, options[ key ] );
644 }
645
646 return this;
647 },
648 _setOption: function( key, value ) {
649 this.options[ key ] = value;
650
651 if ( key === "disabled" ) {
652 this.widget()
653 .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
654 .attr( "aria-disabled", value );
655 this.hoverable.removeClass( "ui-state-hover" );
656 this.focusable.removeClass( "ui-state-focus" );
657 }
658
659 return this;
660 },
661
662 enable: function() {
663 return this._setOption( "disabled", false );
664 },
665 disable: function() {
666 return this._setOption( "disabled", true );
667 },
668
669 _on: function( suppressDisabledCheck, element, handlers ) {
670 var delegateElement,
671 instance = this;
672
673 // no suppressDisabledCheck flag, shuffle arguments
674 if ( typeof suppressDisabledCheck !== "boolean" ) {
675 handlers = element;
676 element = suppressDisabledCheck;
677 suppressDisabledCheck = false;
678 }
679
680 // no element argument, shuffle and use this.element
681 if ( !handlers ) {
682 handlers = element;
683 element = this.element;
684 delegateElement = this.widget();
685 } else {
686 // accept selectors, DOM elements
687 element = delegateElement = $( element );
688 this.bindings = this.bindings.add( element );
689 }
690
691 $.each( handlers, function( event, handler ) {
692 function handlerProxy() {
693 // allow widgets to customize the disabled handling
694 // - disabled as an array instead of boolean
695 // - disabled class as method for disabling individual parts
696 if ( !suppressDisabledCheck &&
697 ( instance.options.disabled === true ||
698 $( this ).hasClass( "ui-state-disabled" ) ) ) {
699 return;
700 }
701 return ( typeof handler === "string" ? instance[ handler ] : handler )
702 .apply( instance, arguments );
703 }
704
705 // copy the guid so direct unbinding works
706 if ( typeof handler !== "string" ) {
707 handlerProxy.guid = handler.guid =
708 handler.guid || handlerProxy.guid || $.guid++;
709 }
710
711 var match = event.match( /^(\w+)\s*(.*)$/ ),
712 eventName = match[1] + instance.eventNamespace,
713 selector = match[2];
714 if ( selector ) {
715 delegateElement.delegate( selector, eventName, handlerProxy );
716 } else {
717 element.bind( eventName, handlerProxy );
718 }
719 });
720 },
721
722 _off: function( element, eventName ) {
723 eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
724 element.unbind( eventName ).undelegate( eventName );
725 },
726
727 _delay: function( handler, delay ) {
728 function handlerProxy() {
729 return ( typeof handler === "string" ? instance[ handler ] : handler )
730 .apply( instance, arguments );
731 }
732 var instance = this;
733 return setTimeout( handlerProxy, delay || 0 );
734 },
735
736 _hoverable: function( element ) {
737 this.hoverable = this.hoverable.add( element );
738 this._on( element, {
739 mouseenter: function( event ) {
740 $( event.currentTarget ).addClass( "ui-state-hover" );
741 },
742 mouseleave: function( event ) {
743 $( event.currentTarget ).removeClass( "ui-state-hover" );
744 }
745 });
746 },
747
748 _focusable: function( element ) {
749 this.focusable = this.focusable.add( element );
750 this._on( element, {
751 focusin: function( event ) {
752 $( event.currentTarget ).addClass( "ui-state-focus" );
753 },
754 focusout: function( event ) {
755 $( event.currentTarget ).removeClass( "ui-state-focus" );
756 }
757 });
758 },
759
760 _trigger: function( type, event, data ) {
761 var prop, orig,
762 callback = this.options[ type ];
763
764 data = data || {};
765 event = $.Event( event );
766 event.type = ( type === this.widgetEventPrefix ?
767 type :
768 this.widgetEventPrefix + type ).toLowerCase();
769 // the original event may come from any element
770 // so we need to reset the target on the new event
771 event.target = this.element[ 0 ];
772
773 // copy original event properties over to the new event
774 orig = event.originalEvent;
775 if ( orig ) {
776 for ( prop in orig ) {
777 if ( !( prop in event ) ) {
778 event[ prop ] = orig[ prop ];
779 }
780 }
781 }
782
783 this.element.trigger( event, data );
784 return !( $.isFunction( callback ) &&
785 callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
786 event.isDefaultPrevented() );
787 }
788};
789
790$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
791 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
792 if ( typeof options === "string" ) {
793 options = { effect: options };
794 }
795 var hasOptions,
796 effectName = !options ?
797 method :
798 options === true || typeof options === "number" ?
799 defaultEffect :
800 options.effect || defaultEffect;
801 options = options || {};
802 if ( typeof options === "number" ) {
803 options = { duration: options };
804 }
805 hasOptions = !$.isEmptyObject( options );
806 options.complete = callback;
807 if ( options.delay ) {
808 element.delay( options.delay );
809 }
810 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
811 element[ method ]( options );
812 } else if ( effectName !== method && element[ effectName ] ) {
813 element[ effectName ]( options.duration, options.easing, callback );
814 } else {
815 element.queue(function( next ) {
816 $( this )[ method ]();
817 if ( callback ) {
818 callback.call( element[ 0 ] );
819 }
820 next();
821 });
822 }
823 };
824});
825
826})( jQuery );
827
828(function( $, undefined ) {
829
830var mouseHandled = false;
831$( document ).mouseup( function() {
832 mouseHandled = false;
833});
834
835$.widget("ui.mouse", {
836 version: "1.10.3",
837 options: {
838 cancel: "input,textarea,button,select,option",
839 distance: 1,
840 delay: 0
841 },
842 _mouseInit: function() {
843 var that = this;
844
845 this.element
846 .bind("mousedown."+this.widgetName, function(event) {
847 return that._mouseDown(event);
848 })
849 .bind("click."+this.widgetName, function(event) {
850 if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
851 $.removeData(event.target, that.widgetName + ".preventClickEvent");
852 event.stopImmediatePropagation();
853 return false;
854 }
855 });
856
857 this.started = false;
858 },
859
860 // TODO: make sure destroying one instance of mouse doesn't mess with
861 // other instances of mouse
862 _mouseDestroy: function() {
863 this.element.unbind("."+this.widgetName);
864 if ( this._mouseMoveDelegate ) {
865 $(document)
866 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
867 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
868 }
869 },
870
871 _mouseDown: function(event) {
872 // don't let more than one widget handle mouseStart
873 if( mouseHandled ) { return; }
874
875 // we may have missed mouseup (out of window)
876 (this._mouseStarted && this._mouseUp(event));
877
878 this._mouseDownEvent = event;
879
880 var that = this,
881 btnIsLeft = (event.which === 1),
882 // event.target.nodeName works around a bug in IE 8 with
883 // disabled inputs (#7620)
884 elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
885 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
886 return true;
887 }
888
889 this.mouseDelayMet = !this.options.delay;
890 if (!this.mouseDelayMet) {
891 this._mouseDelayTimer = setTimeout(function() {
892 that.mouseDelayMet = true;
893 }, this.options.delay);
894 }
895
896 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
897 this._mouseStarted = (this._mouseStart(event) !== false);
898 if (!this._mouseStarted) {
899 event.preventDefault();
900 return true;
901 }
902 }
903
904 // Click event may never have fired (Gecko & Opera)
905 if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
906 $.removeData(event.target, this.widgetName + ".preventClickEvent");
907 }
908
909 // these delegates are required to keep context
910 this._mouseMoveDelegate = function(event) {
911 return that._mouseMove(event);
912 };
913 this._mouseUpDelegate = function(event) {
914 return that._mouseUp(event);
915 };
916 $(document)
917 .bind("mousemove."+this.widgetName, this._mouseMoveDelegate)
918 .bind("mouseup."+this.widgetName, this._mouseUpDelegate);
919
920 event.preventDefault();
921
922 mouseHandled = true;
923 return true;
924 },
925
926 _mouseMove: function(event) {
927 // IE mouseup check - mouseup happened when mouse was out of window
928 if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
929 return this._mouseUp(event);
930 }
931
932 if (this._mouseStarted) {
933 this._mouseDrag(event);
934 return event.preventDefault();
935 }
936
937 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
938 this._mouseStarted =
939 (this._mouseStart(this._mouseDownEvent, event) !== false);
940 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
941 }
942
943 return !this._mouseStarted;
944 },
945
946 _mouseUp: function(event) {
947 $(document)
948 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
949 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
950
951 if (this._mouseStarted) {
952 this._mouseStarted = false;
953
954 if (event.target === this._mouseDownEvent.target) {
955 $.data(event.target, this.widgetName + ".preventClickEvent", true);
956 }
957
958 this._mouseStop(event);
959 }
960
961 return false;
962 },
963
964 _mouseDistanceMet: function(event) {
965 return (Math.max(
966 Math.abs(this._mouseDownEvent.pageX - event.pageX),
967 Math.abs(this._mouseDownEvent.pageY - event.pageY)
968 ) >= this.options.distance
969 );
970 },
971
972 _mouseDelayMet: function(/* event */) {
973 return this.mouseDelayMet;
974 },
975
976 // These are placeholder methods, to be overriden by extending plugin
977 _mouseStart: function(/* event */) {},
978 _mouseDrag: function(/* event */) {},
979 _mouseStop: function(/* event */) {},
980 _mouseCapture: function(/* event */) { return true; }
981});
982
983})(jQuery);
984
985(function( $, undefined ) {
986
987$.widget("ui.draggable", $.ui.mouse, {
988 version: "1.10.3",
989 widgetEventPrefix: "drag",
990 options: {
991 addClasses: true,
992 appendTo: "parent",
993 axis: false,
994 connectToSortable: false,
995 containment: false,
996 cursor: "auto",
997 cursorAt: false,
998 grid: false,
999 handle: false,
1000 helper: "original",
1001 iframeFix: false,
1002 opacity: false,
1003 refreshPositions: false,
1004 revert: false,
1005 revertDuration: 500,
1006 scope: "default",
1007 scroll: true,
1008 scrollSensitivity: 20,
1009 scrollSpeed: 20,
1010 snap: false,
1011 snapMode: "both",
1012 snapTolerance: 20,
1013 stack: false,
1014 zIndex: false,
1015
1016 // callbacks
1017 drag: null,
1018 start: null,
1019 stop: null
1020 },
1021 _create: function() {
1022
1023 if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) {
1024 this.element[0].style.position = "relative";
1025 }
1026 if (this.options.addClasses){
1027 this.element.addClass("ui-draggable");
1028 }
1029 if (this.options.disabled){
1030 this.element.addClass("ui-draggable-disabled");
1031 }
1032
1033 this._mouseInit();
1034
1035 },
1036
1037 _destroy: function() {
1038 this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
1039 this._mouseDestroy();
1040 },
1041
1042 _mouseCapture: function(event) {
1043
1044 var o = this.options;
1045
1046 // among others, prevent a drag on a resizable-handle
1047 if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
1048 return false;
1049 }
1050
1051 //Quit if we're not on a valid handle
1052 this.handle = this._getHandle(event);
1053 if (!this.handle) {
1054 return false;
1055 }
1056
1057 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1058 $("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>")
1059 .css({
1060 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
1061 position: "absolute", opacity: "0.001", zIndex: 1000
1062 })
1063 .css($(this).offset())
1064 .appendTo("body");
1065 });
1066
1067 return true;
1068
1069 },
1070
1071 _mouseStart: function(event) {
1072
1073 var o = this.options;
1074
1075 //Create and append the visible helper
1076 this.helper = this._createHelper(event);
1077
1078 this.helper.addClass("ui-draggable-dragging");
1079
1080 //Cache the helper size
1081 this._cacheHelperProportions();
1082
1083 //If ddmanager is used for droppables, set the global draggable
1084 if($.ui.ddmanager) {
1085 $.ui.ddmanager.current = this;
1086 }
1087
1088 /*
1089 * - Position generation -
1090 * This block generates everything position related - it's the core of draggables.
1091 */
1092
1093 //Cache the margins of the original element
1094 this._cacheMargins();
1095
1096 //Store the helper's css position
1097 this.cssPosition = this.helper.css( "position" );
1098 this.scrollParent = this.helper.scrollParent();
1099 this.offsetParent = this.helper.offsetParent();
1100 this.offsetParentCssPosition = this.offsetParent.css( "position" );
1101
1102 //The element's absolute position on the page minus margins
1103 this.offset = this.positionAbs = this.element.offset();
1104 this.offset = {
1105 top: this.offset.top - this.margins.top,
1106 left: this.offset.left - this.margins.left
1107 };
1108
1109 //Reset scroll cache
1110 this.offset.scroll = false;
1111
1112 $.extend(this.offset, {
1113 click: { //Where the click happened, relative to the element
1114 left: event.pageX - this.offset.left,
1115 top: event.pageY - this.offset.top
1116 },
1117 parent: this._getParentOffset(),
1118 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
1119 });
1120
1121 //Generate the original position
1122 this.originalPosition = this.position = this._generatePosition(event);
1123 this.originalPageX = event.pageX;
1124 this.originalPageY = event.pageY;
1125
1126 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
1127 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
1128
1129 //Set a containment if given in the options
1130 this._setContainment();
1131
1132 //Trigger event + callbacks
1133 if(this._trigger("start", event) === false) {
1134 this._clear();
1135 return false;
1136 }
1137
1138 //Recache the helper size
1139 this._cacheHelperProportions();
1140
1141 //Prepare the droppable offsets
1142 if ($.ui.ddmanager && !o.dropBehaviour) {
1143 $.ui.ddmanager.prepareOffsets(this, event);
1144 }
1145
1146
1147 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
1148
1149 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
1150 if ( $.ui.ddmanager ) {
1151 $.ui.ddmanager.dragStart(this, event);
1152 }
1153
1154 return true;
1155 },
1156
1157 _mouseDrag: function(event, noPropagation) {
1158 // reset any necessary cached properties (see #5009)
1159 if ( this.offsetParentCssPosition === "fixed" ) {
1160 this.offset.parent = this._getParentOffset();
1161 }
1162
1163 //Compute the helpers position
1164 this.position = this._generatePosition(event);
1165 this.positionAbs = this._convertPositionTo("absolute");
1166
1167 //Call plugins and callbacks and use the resulting position if something is returned
1168 if (!noPropagation) {
1169 var ui = this._uiHash();
1170 if(this._trigger("drag", event, ui) === false) {
1171 this._mouseUp({});
1172 return false;
1173 }
1174 this.position = ui.position;
1175 }
1176
1177 if(!this.options.axis || this.options.axis !== "y") {
1178 this.helper[0].style.left = this.position.left+"px";
1179 }
1180 if(!this.options.axis || this.options.axis !== "x") {
1181 this.helper[0].style.top = this.position.top+"px";
1182 }
1183 if($.ui.ddmanager) {
1184 $.ui.ddmanager.drag(this, event);
1185 }
1186
1187 return false;
1188 },
1189
1190 _mouseStop: function(event) {
1191
1192 //If we are using droppables, inform the manager about the drop
1193 var that = this,
1194 dropped = false;
1195 if ($.ui.ddmanager && !this.options.dropBehaviour) {
1196 dropped = $.ui.ddmanager.drop(this, event);
1197 }
1198
1199 //if a drop comes from outside (a sortable)
1200 if(this.dropped) {
1201 dropped = this.dropped;
1202 this.dropped = false;
1203 }
1204
1205 //if the original element is no longer in the DOM don't bother to continue (see #8269)
1206 if ( this.options.helper === "original" && !$.contains( this.element[ 0 ].ownerDocument, this.element[ 0 ] ) ) {
1207 return false;
1208 }
1209
1210 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))) {
1211 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
1212 if(that._trigger("stop", event) !== false) {
1213 that._clear();
1214 }
1215 });
1216 } else {
1217 if(this._trigger("stop", event) !== false) {
1218 this._clear();
1219 }
1220 }
1221
1222 return false;
1223 },
1224
1225 _mouseUp: function(event) {
1226 //Remove frame helpers
1227 $("div.ui-draggable-iframeFix").each(function() {
1228 this.parentNode.removeChild(this);
1229 });
1230
1231 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
1232 if( $.ui.ddmanager ) {
1233 $.ui.ddmanager.dragStop(this, event);
1234 }
1235
1236 return $.ui.mouse.prototype._mouseUp.call(this, event);
1237 },
1238
1239 cancel: function() {
1240
1241 if(this.helper.is(".ui-draggable-dragging")) {
1242 this._mouseUp({});
1243 } else {
1244 this._clear();
1245 }
1246
1247 return this;
1248
1249 },
1250
1251 _getHandle: function(event) {
1252 return this.options.handle ?
1253 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
1254 true;
1255 },
1256
1257 _createHelper: function(event) {
1258
1259 var o = this.options,
1260 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element);
1261
1262 if(!helper.parents("body").length) {
1263 helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
1264 }
1265
1266 if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
1267 helper.css("position", "absolute");
1268 }
1269
1270 return helper;
1271
1272 },
1273
1274 _adjustOffsetFromHelper: function(obj) {
1275 if (typeof obj === "string") {
1276 obj = obj.split(" ");
1277 }
1278 if ($.isArray(obj)) {
1279 obj = {left: +obj[0], top: +obj[1] || 0};
1280 }
1281 if ("left" in obj) {
1282 this.offset.click.left = obj.left + this.margins.left;
1283 }
1284 if ("right" in obj) {
1285 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1286 }
1287 if ("top" in obj) {
1288 this.offset.click.top = obj.top + this.margins.top;
1289 }
1290 if ("bottom" in obj) {
1291 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1292 }
1293 },
1294
1295 _getParentOffset: function() {
1296
1297 //Get the offsetParent and cache its position
1298 var po = this.offsetParent.offset();
1299
1300 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1301 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1302 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1303 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1304 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
1305 po.left += this.scrollParent.scrollLeft();
1306 po.top += this.scrollParent.scrollTop();
1307 }
1308
1309 //This needs to be actually done for all browsers, since pageX/pageY includes this information
1310 //Ugly IE fix
1311 if((this.offsetParent[0] === document.body) ||
1312 (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
1313 po = { top: 0, left: 0 };
1314 }
1315
1316 return {
1317 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1318 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1319 };
1320
1321 },
1322
1323 _getRelativeOffset: function() {
1324
1325 if(this.cssPosition === "relative") {
1326 var p = this.element.position();
1327 return {
1328 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1329 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1330 };
1331 } else {
1332 return { top: 0, left: 0 };
1333 }
1334
1335 },
1336
1337 _cacheMargins: function() {
1338 this.margins = {
1339 left: (parseInt(this.element.css("marginLeft"),10) || 0),
1340 top: (parseInt(this.element.css("marginTop"),10) || 0),
1341 right: (parseInt(this.element.css("marginRight"),10) || 0),
1342 bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
1343 };
1344 },
1345
1346 _cacheHelperProportions: function() {
1347 this.helperProportions = {
1348 width: this.helper.outerWidth(),
1349 height: this.helper.outerHeight()
1350 };
1351 },
1352
1353 _setContainment: function() {
1354
1355 var over, c, ce,
1356 o = this.options;
1357
1358 if ( !o.containment ) {
1359 this.containment = null;
1360 return;
1361 }
1362
1363 if ( o.containment === "window" ) {
1364 this.containment = [
1365 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
1366 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
1367 $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,
1368 $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
1369 ];
1370 return;
1371 }
1372
1373 if ( o.containment === "document") {
1374 this.containment = [
1375 0,
1376 0,
1377 $( document ).width() - this.helperProportions.width - this.margins.left,
1378 ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
1379 ];
1380 return;
1381 }
1382
1383 if ( o.containment.constructor === Array ) {
1384 this.containment = o.containment;
1385 return;
1386 }
1387
1388 if ( o.containment === "parent" ) {
1389 o.containment = this.helper[ 0 ].parentNode;
1390 }
1391
1392 c = $( o.containment );
1393 ce = c[ 0 ];
1394
1395 if( !ce ) {
1396 return;
1397 }
1398
1399 over = c.css( "overflow" ) !== "hidden";
1400
1401 this.containment = [
1402 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
1403 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ) ,
1404 ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - this.helperProportions.width - this.margins.left - this.margins.right,
1405 ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - this.helperProportions.height - this.margins.top - this.margins.bottom
1406 ];
1407 this.relative_container = c;
1408 },
1409
1410 _convertPositionTo: function(d, pos) {
1411
1412 if(!pos) {
1413 pos = this.position;
1414 }
1415
1416 var mod = d === "absolute" ? 1 : -1,
1417 scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent;
1418
1419 //Cache the scroll
1420 if (!this.offset.scroll) {
1421 this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
1422 }
1423
1424 return {
1425 top: (
1426 pos.top + // The absolute mouse position
1427 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
1428 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
1429 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) * mod )
1430 ),
1431 left: (
1432 pos.left + // The absolute mouse position
1433 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
1434 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
1435 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) * mod )
1436 )
1437 };
1438
1439 },
1440
1441 _generatePosition: function(event) {
1442
1443 var containment, co, top, left,
1444 o = this.options,
1445 scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent,
1446 pageX = event.pageX,
1447 pageY = event.pageY;
1448
1449 //Cache the scroll
1450 if (!this.offset.scroll) {
1451 this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
1452 }
1453
1454 /*
1455 * - Position constraining -
1456 * Constrain the position to a mix of grid, containment.
1457 */
1458
1459 // If we are not dragging yet, we won't check for options
1460 if ( this.originalPosition ) {
1461 if ( this.containment ) {
1462 if ( this.relative_container ){
1463 co = this.relative_container.offset();
1464 containment = [
1465 this.containment[ 0 ] + co.left,
1466 this.containment[ 1 ] + co.top,
1467 this.containment[ 2 ] + co.left,
1468 this.containment[ 3 ] + co.top
1469 ];
1470 }
1471 else {
1472 containment = this.containment;
1473 }
1474
1475 if(event.pageX - this.offset.click.left < containment[0]) {
1476 pageX = containment[0] + this.offset.click.left;
1477 }
1478 if(event.pageY - this.offset.click.top < containment[1]) {
1479 pageY = containment[1] + this.offset.click.top;
1480 }
1481 if(event.pageX - this.offset.click.left > containment[2]) {
1482 pageX = containment[2] + this.offset.click.left;
1483 }
1484 if(event.pageY - this.offset.click.top > containment[3]) {
1485 pageY = containment[3] + this.offset.click.top;
1486 }
1487 }
1488
1489 if(o.grid) {
1490 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
1491 top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
1492 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;
1493
1494 left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
1495 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;
1496 }
1497
1498 }
1499
1500 return {
1501 top: (
1502 pageY - // The absolute mouse position
1503 this.offset.click.top - // Click offset (relative to the element)
1504 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
1505 this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
1506 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top )
1507 ),
1508 left: (
1509 pageX - // The absolute mouse position
1510 this.offset.click.left - // Click offset (relative to the element)
1511 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
1512 this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
1513 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left )
1514 )
1515 };
1516
1517 },
1518
1519 _clear: function() {
1520 this.helper.removeClass("ui-draggable-dragging");
1521 if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
1522 this.helper.remove();
1523 }
1524 this.helper = null;
1525 this.cancelHelperRemoval = false;
1526 },
1527
1528 // From now on bulk stuff - mainly helpers
1529
1530 _trigger: function(type, event, ui) {
1531 ui = ui || this._uiHash();
1532 $.ui.plugin.call(this, type, [event, ui]);
1533 //The absolute position has to be recalculated after plugins
1534 if(type === "drag") {
1535 this.positionAbs = this._convertPositionTo("absolute");
1536 }
1537 return $.Widget.prototype._trigger.call(this, type, event, ui);
1538 },
1539
1540 plugins: {},
1541
1542 _uiHash: function() {
1543 return {
1544 helper: this.helper,
1545 position: this.position,
1546 originalPosition: this.originalPosition,
1547 offset: this.positionAbs
1548 };
1549 }
1550
1551});
1552
1553$.ui.plugin.add("draggable", "connectToSortable", {
1554 start: function(event, ui) {
1555
1556 var inst = $(this).data("ui-draggable"), o = inst.options,
1557 uiSortable = $.extend({}, ui, { item: inst.element });
1558 inst.sortables = [];
1559 $(o.connectToSortable).each(function() {
1560 var sortable = $.data(this, "ui-sortable");
1561 if (sortable && !sortable.options.disabled) {
1562 inst.sortables.push({
1563 instance: sortable,
1564 shouldRevert: sortable.options.revert
1565 });
1566 sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
1567 sortable._trigger("activate", event, uiSortable);
1568 }
1569 });
1570
1571 },
1572 stop: function(event, ui) {
1573
1574 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1575 var inst = $(this).data("ui-draggable"),
1576 uiSortable = $.extend({}, ui, { item: inst.element });
1577
1578 $.each(inst.sortables, function() {
1579 if(this.instance.isOver) {
1580
1581 this.instance.isOver = 0;
1582
1583 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
1584 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1585
1586 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid"
1587 if(this.shouldRevert) {
1588 this.instance.options.revert = this.shouldRevert;
1589 }
1590
1591 //Trigger the stop of the sortable
1592 this.instance._mouseStop(event);
1593
1594 this.instance.options.helper = this.instance.options._helper;
1595
1596 //If the helper has been the original item, restore properties in the sortable
1597 if(inst.options.helper === "original") {
1598 this.instance.currentItem.css({ top: "auto", left: "auto" });
1599 }
1600
1601 } else {
1602 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1603 this.instance._trigger("deactivate", event, uiSortable);
1604 }
1605
1606 });
1607
1608 },
1609 drag: function(event, ui) {
1610
1611 var inst = $(this).data("ui-draggable"), that = this;
1612
1613 $.each(inst.sortables, function() {
1614
1615 var innermostIntersecting = false,
1616 thisSortable = this;
1617
1618 //Copy over some variables to allow calling the sortable's native _intersectsWith
1619 this.instance.positionAbs = inst.positionAbs;
1620 this.instance.helperProportions = inst.helperProportions;
1621 this.instance.offset.click = inst.offset.click;
1622
1623 if(this.instance._intersectsWith(this.instance.containerCache)) {
1624 innermostIntersecting = true;
1625 $.each(inst.sortables, function () {
1626 this.instance.positionAbs = inst.positionAbs;
1627 this.instance.helperProportions = inst.helperProportions;
1628 this.instance.offset.click = inst.offset.click;
1629 if (this !== thisSortable &&
1630 this.instance._intersectsWith(this.instance.containerCache) &&
1631 $.contains(thisSortable.instance.element[0], this.instance.element[0])
1632 ) {
1633 innermostIntersecting = false;
1634 }
1635 return innermostIntersecting;
1636 });
1637 }
1638
1639
1640 if(innermostIntersecting) {
1641 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1642 if(!this.instance.isOver) {
1643
1644 this.instance.isOver = 1;
1645 //Now we fake the start of dragging for the sortable instance,
1646 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1647 //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
1648 this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true);
1649 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1650 this.instance.options.helper = function() { return ui.helper[0]; };
1651
1652 event.target = this.instance.currentItem[0];
1653 this.instance._mouseCapture(event, true);
1654 this.instance._mouseStart(event, true, true);
1655
1656 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1657 this.instance.offset.click.top = inst.offset.click.top;
1658 this.instance.offset.click.left = inst.offset.click.left;
1659 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1660 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1661
1662 inst._trigger("toSortable", event);
1663 inst.dropped = this.instance.element; //draggable revert needs that
1664 //hack so receive/update callbacks work (mostly)
1665 inst.currentItem = inst.element;
1666 this.instance.fromOutside = inst;
1667
1668 }
1669
1670 //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
1671 if(this.instance.currentItem) {
1672 this.instance._mouseDrag(event);
1673 }
1674
1675 } else {
1676
1677 //If it doesn't intersect with the sortable, and it intersected before,
1678 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1679 if(this.instance.isOver) {
1680
1681 this.instance.isOver = 0;
1682 this.instance.cancelHelperRemoval = true;
1683
1684 //Prevent reverting on this forced stop
1685 this.instance.options.revert = false;
1686
1687 // The out event needs to be triggered independently
1688 this.instance._trigger("out", event, this.instance._uiHash(this.instance));
1689
1690 this.instance._mouseStop(event, true);
1691 this.instance.options.helper = this.instance.options._helper;
1692
1693 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1694 this.instance.currentItem.remove();
1695 if(this.instance.placeholder) {
1696 this.instance.placeholder.remove();
1697 }
1698
1699 inst._trigger("fromSortable", event);
1700 inst.dropped = false; //draggable revert needs that
1701 }
1702
1703 }
1704
1705 });
1706
1707 }
1708});
1709
1710$.ui.plugin.add("draggable", "cursor", {
1711 start: function() {
1712 var t = $("body"), o = $(this).data("ui-draggable").options;
1713 if (t.css("cursor")) {
1714 o._cursor = t.css("cursor");
1715 }
1716 t.css("cursor", o.cursor);
1717 },
1718 stop: function() {
1719 var o = $(this).data("ui-draggable").options;
1720 if (o._cursor) {
1721 $("body").css("cursor", o._cursor);
1722 }
1723 }
1724});
1725
1726$.ui.plugin.add("draggable", "opacity", {
1727 start: function(event, ui) {
1728 var t = $(ui.helper), o = $(this).data("ui-draggable").options;
1729 if(t.css("opacity")) {
1730 o._opacity = t.css("opacity");
1731 }
1732 t.css("opacity", o.opacity);
1733 },
1734 stop: function(event, ui) {
1735 var o = $(this).data("ui-draggable").options;
1736 if(o._opacity) {
1737 $(ui.helper).css("opacity", o._opacity);
1738 }
1739 }
1740});
1741
1742$.ui.plugin.add("draggable", "scroll", {
1743 start: function() {
1744 var i = $(this).data("ui-draggable");
1745 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
1746 i.overflowOffset = i.scrollParent.offset();
1747 }
1748 },
1749 drag: function( event ) {
1750
1751 var i = $(this).data("ui-draggable"), o = i.options, scrolled = false;
1752
1753 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
1754
1755 if(!o.axis || o.axis !== "x") {
1756 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
1757 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1758 } else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) {
1759 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1760 }
1761 }
1762
1763 if(!o.axis || o.axis !== "y") {
1764 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
1765 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1766 } else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) {
1767 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1768 }
1769 }
1770
1771 } else {
1772
1773 if(!o.axis || o.axis !== "x") {
1774 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
1775 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1776 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
1777 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1778 }
1779 }
1780
1781 if(!o.axis || o.axis !== "y") {
1782 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
1783 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1784 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
1785 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1786 }
1787 }
1788
1789 }
1790
1791 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
1792 $.ui.ddmanager.prepareOffsets(i, event);
1793 }
1794
1795 }
1796});
1797
1798$.ui.plugin.add("draggable", "snap", {
1799 start: function() {
1800
1801 var i = $(this).data("ui-draggable"),
1802 o = i.options;
1803
1804 i.snapElements = [];
1805
1806 $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
1807 var $t = $(this),
1808 $o = $t.offset();
1809 if(this !== i.element[0]) {
1810 i.snapElements.push({
1811 item: this,
1812 width: $t.outerWidth(), height: $t.outerHeight(),
1813 top: $o.top, left: $o.left
1814 });
1815 }
1816 });
1817
1818 },
1819 drag: function(event, ui) {
1820
1821 var ts, bs, ls, rs, l, r, t, b, i, first,
1822 inst = $(this).data("ui-draggable"),
1823 o = inst.options,
1824 d = o.snapTolerance,
1825 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
1826 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
1827
1828 for (i = inst.snapElements.length - 1; i >= 0; i--){
1829
1830 l = inst.snapElements[i].left;
1831 r = l + inst.snapElements[i].width;
1832 t = inst.snapElements[i].top;
1833 b = t + inst.snapElements[i].height;
1834
1835 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {
1836 if(inst.snapElements[i].snapping) {
1837 (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1838 }
1839 inst.snapElements[i].snapping = false;
1840 continue;
1841 }
1842
1843 if(o.snapMode !== "inner") {
1844 ts = Math.abs(t - y2) <= d;
1845 bs = Math.abs(b - y1) <= d;
1846 ls = Math.abs(l - x2) <= d;
1847 rs = Math.abs(r - x1) <= d;
1848 if(ts) {
1849 ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1850 }
1851 if(bs) {
1852 ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1853 }
1854 if(ls) {
1855 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1856 }
1857 if(rs) {
1858 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1859 }
1860 }
1861
1862 first = (ts || bs || ls || rs);
1863
1864 if(o.snapMode !== "outer") {
1865 ts = Math.abs(t - y1) <= d;
1866 bs = Math.abs(b - y2) <= d;
1867 ls = Math.abs(l - x1) <= d;
1868 rs = Math.abs(r - x2) <= d;
1869 if(ts) {
1870 ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1871 }
1872 if(bs) {
1873 ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1874 }
1875 if(ls) {
1876 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1877 }
1878 if(rs) {
1879 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1880 }
1881 }
1882
1883 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
1884 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1885 }
1886 inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1887
1888 }
1889
1890 }
1891});
1892
1893$.ui.plugin.add("draggable", "stack", {
1894 start: function() {
1895 var min,
1896 o = this.data("ui-draggable").options,
1897 group = $.makeArray($(o.stack)).sort(function(a,b) {
1898 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
1899 });
1900
1901 if (!group.length) { return; }
1902
1903 min = parseInt($(group[0]).css("zIndex"), 10) || 0;
1904 $(group).each(function(i) {
1905 $(this).css("zIndex", min + i);
1906 });
1907 this.css("zIndex", (min + group.length));
1908 }
1909});
1910
1911$.ui.plugin.add("draggable", "zIndex", {
1912 start: function(event, ui) {
1913 var t = $(ui.helper), o = $(this).data("ui-draggable").options;
1914 if(t.css("zIndex")) {
1915 o._zIndex = t.css("zIndex");
1916 }
1917 t.css("zIndex", o.zIndex);
1918 },
1919 stop: function(event, ui) {
1920 var o = $(this).data("ui-draggable").options;
1921 if(o._zIndex) {
1922 $(ui.helper).css("zIndex", o._zIndex);
1923 }
1924 }
1925});
1926
1927})(jQuery);
1928
1929(function( $, undefined ) {
1930
1931function isOverAxis( x, reference, size ) {
1932 return ( x > reference ) && ( x < ( reference + size ) );
1933}
1934
1935$.widget("ui.droppable", {
1936 version: "1.10.3",
1937 widgetEventPrefix: "drop",
1938 options: {
1939 accept: "*",
1940 activeClass: false,
1941 addClasses: true,
1942 greedy: false,
1943 hoverClass: false,
1944 scope: "default",
1945 tolerance: "intersect",
1946
1947 // callbacks
1948 activate: null,
1949 deactivate: null,
1950 drop: null,
1951 out: null,
1952 over: null
1953 },
1954 _create: function() {
1955
1956 var o = this.options,
1957 accept = o.accept;
1958
1959 this.isover = false;
1960 this.isout = true;
1961
1962 this.accept = $.isFunction(accept) ? accept : function(d) {
1963 return d.is(accept);
1964 };
1965
1966 //Store the droppable's proportions
1967 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
1968
1969 // Add the reference and positions to the manager
1970 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
1971 $.ui.ddmanager.droppables[o.scope].push(this);
1972
1973 (o.addClasses && this.element.addClass("ui-droppable"));
1974
1975 },
1976
1977 _destroy: function() {
1978 var i = 0,
1979 drop = $.ui.ddmanager.droppables[this.options.scope];
1980
1981 for ( ; i < drop.length; i++ ) {
1982 if ( drop[i] === this ) {
1983 drop.splice(i, 1);
1984 }
1985 }
1986
1987 this.element.removeClass("ui-droppable ui-droppable-disabled");
1988 },
1989
1990 _setOption: function(key, value) {
1991
1992 if(key === "accept") {
1993 this.accept = $.isFunction(value) ? value : function(d) {
1994 return d.is(value);
1995 };
1996 }
1997 $.Widget.prototype._setOption.apply(this, arguments);
1998 },
1999
2000 _activate: function(event) {
2001 var draggable = $.ui.ddmanager.current;
2002 if(this.options.activeClass) {
2003 this.element.addClass(this.options.activeClass);
2004 }
2005 if(draggable){
2006 this._trigger("activate", event, this.ui(draggable));
2007 }
2008 },
2009
2010 _deactivate: function(event) {
2011 var draggable = $.ui.ddmanager.current;
2012 if(this.options.activeClass) {
2013 this.element.removeClass(this.options.activeClass);
2014 }
2015 if(draggable){
2016 this._trigger("deactivate", event, this.ui(draggable));
2017 }
2018 },
2019
2020 _over: function(event) {
2021
2022 var draggable = $.ui.ddmanager.current;
2023
2024 // Bail if draggable and droppable are same element
2025 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
2026 return;
2027 }
2028
2029 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2030 if(this.options.hoverClass) {
2031 this.element.addClass(this.options.hoverClass);
2032 }
2033 this._trigger("over", event, this.ui(draggable));
2034 }
2035
2036 },
2037
2038 _out: function(event) {
2039
2040 var draggable = $.ui.ddmanager.current;
2041
2042 // Bail if draggable and droppable are same element
2043 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
2044 return;
2045 }
2046
2047 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2048 if(this.options.hoverClass) {
2049 this.element.removeClass(this.options.hoverClass);
2050 }
2051 this._trigger("out", event, this.ui(draggable));
2052 }
2053
2054 },
2055
2056 _drop: function(event,custom) {
2057
2058 var draggable = custom || $.ui.ddmanager.current,
2059 childrenIntersection = false;
2060
2061 // Bail if draggable and droppable are same element
2062 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
2063 return false;
2064 }
2065
2066 this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() {
2067 var inst = $.data(this, "ui-droppable");
2068 if(
2069 inst.options.greedy &&
2070 !inst.options.disabled &&
2071 inst.options.scope === draggable.options.scope &&
2072 inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) &&
2073 $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
2074 ) { childrenIntersection = true; return false; }
2075 });
2076 if(childrenIntersection) {
2077 return false;
2078 }
2079
2080 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2081 if(this.options.activeClass) {
2082 this.element.removeClass(this.options.activeClass);
2083 }
2084 if(this.options.hoverClass) {
2085 this.element.removeClass(this.options.hoverClass);
2086 }
2087 this._trigger("drop", event, this.ui(draggable));
2088 return this.element;
2089 }
2090
2091 return false;
2092
2093 },
2094
2095 ui: function(c) {
2096 return {
2097 draggable: (c.currentItem || c.element),
2098 helper: c.helper,
2099 position: c.position,
2100 offset: c.positionAbs
2101 };
2102 }
2103
2104});
2105
2106$.ui.intersect = function(draggable, droppable, toleranceMode) {
2107
2108 if (!droppable.offset) {
2109 return false;
2110 }
2111
2112 var draggableLeft, draggableTop,
2113 x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
2114 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height,
2115 l = droppable.offset.left, r = l + droppable.proportions.width,
2116 t = droppable.offset.top, b = t + droppable.proportions.height;
2117
2118 switch (toleranceMode) {
2119 case "fit":
2120 return (l <= x1 && x2 <= r && t <= y1 && y2 <= b);
2121 case "intersect":
2122 return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half
2123 x2 - (draggable.helperProportions.width / 2) < r && // Left Half
2124 t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half
2125 y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
2126 case "pointer":
2127 draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left);
2128 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top);
2129 return isOverAxis( draggableTop, t, droppable.proportions.height ) && isOverAxis( draggableLeft, l, droppable.proportions.width );
2130 case "touch":
2131 return (
2132 (y1 >= t && y1 <= b) || // Top edge touching
2133 (y2 >= t && y2 <= b) || // Bottom edge touching
2134 (y1 < t && y2 > b) // Surrounded vertically
2135 ) && (
2136 (x1 >= l && x1 <= r) || // Left edge touching
2137 (x2 >= l && x2 <= r) || // Right edge touching
2138 (x1 < l && x2 > r) // Surrounded horizontally
2139 );
2140 default:
2141 return false;
2142 }
2143
2144};
2145
2146/*
2147 This manager tracks offsets of draggables and droppables
2148*/
2149$.ui.ddmanager = {
2150 current: null,
2151 droppables: { "default": [] },
2152 prepareOffsets: function(t, event) {
2153
2154 var i, j,
2155 m = $.ui.ddmanager.droppables[t.options.scope] || [],
2156 type = event ? event.type : null, // workaround for #2317
2157 list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack();
2158
2159 droppablesLoop: for (i = 0; i < m.length; i++) {
2160
2161 //No disabled and non-accepted
2162 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) {
2163 continue;
2164 }
2165
2166 // Filter out elements in the current dragged item
2167 for (j=0; j < list.length; j++) {
2168 if(list[j] === m[i].element[0]) {
2169 m[i].proportions.height = 0;
2170 continue droppablesLoop;
2171 }
2172 }
2173
2174 m[i].visible = m[i].element.css("display") !== "none";
2175 if(!m[i].visible) {
2176 continue;
2177 }
2178
2179 //Activate the droppable if used directly from draggables
2180 if(type === "mousedown") {
2181 m[i]._activate.call(m[i], event);
2182 }
2183
2184 m[i].offset = m[i].element.offset();
2185 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
2186
2187 }
2188
2189 },
2190 drop: function(draggable, event) {
2191
2192 var dropped = false;
2193 // Create a copy of the droppables in case the list changes during the drop (#9116)
2194 $.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function() {
2195
2196 if(!this.options) {
2197 return;
2198 }
2199 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) {
2200 dropped = this._drop.call(this, event) || dropped;
2201 }
2202
2203 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2204 this.isout = true;
2205 this.isover = false;
2206 this._deactivate.call(this, event);
2207 }
2208
2209 });
2210 return dropped;
2211
2212 },
2213 dragStart: function( draggable, event ) {
2214 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
2215 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
2216 if( !draggable.options.refreshPositions ) {
2217 $.ui.ddmanager.prepareOffsets( draggable, event );
2218 }
2219 });
2220 },
2221 drag: function(draggable, event) {
2222
2223 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
2224 if(draggable.options.refreshPositions) {
2225 $.ui.ddmanager.prepareOffsets(draggable, event);
2226 }
2227
2228 //Run through all droppables and check their positions based on specific tolerance options
2229 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
2230
2231 if(this.options.disabled || this.greedyChild || !this.visible) {
2232 return;
2233 }
2234
2235 var parentInstance, scope, parent,
2236 intersects = $.ui.intersect(draggable, this, this.options.tolerance),
2237 c = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null);
2238 if(!c) {
2239 return;
2240 }
2241
2242 if (this.options.greedy) {
2243 // find droppable parents with same scope
2244 scope = this.options.scope;
2245 parent = this.element.parents(":data(ui-droppable)").filter(function () {
2246 return $.data(this, "ui-droppable").options.scope === scope;
2247 });
2248
2249 if (parent.length) {
2250 parentInstance = $.data(parent[0], "ui-droppable");
2251 parentInstance.greedyChild = (c === "isover");
2252 }
2253 }
2254
2255 // we just moved into a greedy child
2256 if (parentInstance && c === "isover") {
2257 parentInstance.isover = false;
2258 parentInstance.isout = true;
2259 parentInstance._out.call(parentInstance, event);
2260 }
2261
2262 this[c] = true;
2263 this[c === "isout" ? "isover" : "isout"] = false;
2264 this[c === "isover" ? "_over" : "_out"].call(this, event);
2265
2266 // we just moved out of a greedy child
2267 if (parentInstance && c === "isout") {
2268 parentInstance.isout = false;
2269 parentInstance.isover = true;
2270 parentInstance._over.call(parentInstance, event);
2271 }
2272 });
2273
2274 },
2275 dragStop: function( draggable, event ) {
2276 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
2277 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
2278 if( !draggable.options.refreshPositions ) {
2279 $.ui.ddmanager.prepareOffsets( draggable, event );
2280 }
2281 }
2282};
2283
2284})(jQuery);
2285
2286(function( $, undefined ) {
2287
2288function num(v) {
2289 return parseInt(v, 10) || 0;
2290}
2291
2292function isNumber(value) {
2293 return !isNaN(parseInt(value, 10));
2294}
2295
2296$.widget("ui.resizable", $.ui.mouse, {
2297 version: "1.10.3",
2298 widgetEventPrefix: "resize",
2299 options: {
2300 alsoResize: false,
2301 animate: false,
2302 animateDuration: "slow",
2303 animateEasing: "swing",
2304 aspectRatio: false,
2305 autoHide: false,
2306 containment: false,
2307 ghost: false,
2308 grid: false,
2309 handles: "e,s,se",
2310 helper: false,
2311 maxHeight: null,
2312 maxWidth: null,
2313 minHeight: 10,
2314 minWidth: 10,
2315 // See #7960
2316 zIndex: 90,
2317
2318 // callbacks
2319 resize: null,
2320 start: null,
2321 stop: null
2322 },
2323 _create: function() {
2324
2325 var n, i, handle, axis, hname,
2326 that = this,
2327 o = this.options;
2328 this.element.addClass("ui-resizable");
2329
2330 $.extend(this, {
2331 _aspectRatio: !!(o.aspectRatio),
2332 aspectRatio: o.aspectRatio,
2333 originalElement: this.element,
2334 _proportionallyResizeElements: [],
2335 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
2336 });
2337
2338 //Wrap the element if it cannot hold child nodes
2339 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
2340
2341 //Create a wrapper element and set the wrapper to the new current internal element
2342 this.element.wrap(
2343 $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
2344 position: this.element.css("position"),
2345 width: this.element.outerWidth(),
2346 height: this.element.outerHeight(),
2347 top: this.element.css("top"),
2348 left: this.element.css("left")
2349 })
2350 );
2351
2352 //Overwrite the original this.element
2353 this.element = this.element.parent().data(
2354 "ui-resizable", this.element.data("ui-resizable")
2355 );
2356
2357 this.elementIsWrapper = true;
2358
2359 //Move margins to the wrapper
2360 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
2361 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
2362
2363 //Prevent Safari textarea resize
2364 this.originalResizeStyle = this.originalElement.css("resize");
2365 this.originalElement.css("resize", "none");
2366
2367 //Push the actual element to our proportionallyResize internal array
2368 this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" }));
2369
2370 // avoid IE jump (hard set the margin)
2371 this.originalElement.css({ margin: this.originalElement.css("margin") });
2372
2373 // fix handlers offset
2374 this._proportionallyResize();
2375
2376 }
2377
2378 this.handles = o.handles || (!$(".ui-resizable-handle", this.element).length ? "e,s,se" : { n: ".ui-resizable-n", e: ".ui-resizable-e", s: ".ui-resizable-s", w: ".ui-resizable-w", se: ".ui-resizable-se", sw: ".ui-resizable-sw", ne: ".ui-resizable-ne", nw: ".ui-resizable-nw" });
2379 if(this.handles.constructor === String) {
2380
2381 if ( this.handles === "all") {
2382 this.handles = "n,e,s,w,se,sw,ne,nw";
2383 }
2384
2385 n = this.handles.split(",");
2386 this.handles = {};
2387
2388 for(i = 0; i < n.length; i++) {
2389
2390 handle = $.trim(n[i]);
2391 hname = "ui-resizable-"+handle;
2392 axis = $("<div class='ui-resizable-handle " + hname + "'></div>");
2393
2394 // Apply zIndex to all handles - see #7960
2395 axis.css({ zIndex: o.zIndex });
2396
2397 //TODO : What's going on here?
2398 if ("se" === handle) {
2399 axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
2400 }
2401
2402 //Insert into internal handles object and append to element
2403 this.handles[handle] = ".ui-resizable-"+handle;
2404 this.element.append(axis);
2405 }
2406
2407 }
2408
2409 this._renderAxis = function(target) {
2410
2411 var i, axis, padPos, padWrapper;
2412
2413 target = target || this.element;
2414
2415 for(i in this.handles) {
2416
2417 if(this.handles[i].constructor === String) {
2418 this.handles[i] = $(this.handles[i], this.element).show();
2419 }
2420
2421 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
2422 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
2423
2424 axis = $(this.handles[i], this.element);
2425
2426 //Checking the correct pad and border
2427 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
2428
2429 //The padding type i have to apply...
2430 padPos = [ "padding",
2431 /ne|nw|n/.test(i) ? "Top" :
2432 /se|sw|s/.test(i) ? "Bottom" :
2433 /^e$/.test(i) ? "Right" : "Left" ].join("");
2434
2435 target.css(padPos, padWrapper);
2436
2437 this._proportionallyResize();
2438
2439 }
2440
2441 //TODO: What's that good for? There's not anything to be executed left
2442 if(!$(this.handles[i]).length) {
2443 continue;
2444 }
2445 }
2446 };
2447
2448 //TODO: make renderAxis a prototype function
2449 this._renderAxis(this.element);
2450
2451 this._handles = $(".ui-resizable-handle", this.element)
2452 .disableSelection();
2453
2454 //Matching axis name
2455 this._handles.mouseover(function() {
2456 if (!that.resizing) {
2457 if (this.className) {
2458 axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
2459 }
2460 //Axis, default = se
2461 that.axis = axis && axis[1] ? axis[1] : "se";
2462 }
2463 });
2464
2465 //If we want to auto hide the elements
2466 if (o.autoHide) {
2467 this._handles.hide();
2468 $(this.element)
2469 .addClass("ui-resizable-autohide")
2470 .mouseenter(function() {
2471 if (o.disabled) {
2472 return;
2473 }
2474 $(this).removeClass("ui-resizable-autohide");
2475 that._handles.show();
2476 })
2477 .mouseleave(function(){
2478 if (o.disabled) {
2479 return;
2480 }
2481 if (!that.resizing) {
2482 $(this).addClass("ui-resizable-autohide");
2483 that._handles.hide();
2484 }
2485 });
2486 }
2487
2488 //Initialize the mouse interaction
2489 this._mouseInit();
2490
2491 },
2492
2493 _destroy: function() {
2494
2495 this._mouseDestroy();
2496
2497 var wrapper,
2498 _destroy = function(exp) {
2499 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
2500 .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove();
2501 };
2502
2503 //TODO: Unwrap at same DOM position
2504 if (this.elementIsWrapper) {
2505 _destroy(this.element);
2506 wrapper = this.element;
2507 this.originalElement.css({
2508 position: wrapper.css("position"),
2509 width: wrapper.outerWidth(),
2510 height: wrapper.outerHeight(),
2511 top: wrapper.css("top"),
2512 left: wrapper.css("left")
2513 }).insertAfter( wrapper );
2514 wrapper.remove();
2515 }
2516
2517 this.originalElement.css("resize", this.originalResizeStyle);
2518 _destroy(this.originalElement);
2519
2520 return this;
2521 },
2522
2523 _mouseCapture: function(event) {
2524 var i, handle,
2525 capture = false;
2526
2527 for (i in this.handles) {
2528 handle = $(this.handles[i])[0];
2529 if (handle === event.target || $.contains(handle, event.target)) {
2530 capture = true;
2531 }
2532 }
2533
2534 return !this.options.disabled && capture;
2535 },
2536
2537 _mouseStart: function(event) {
2538
2539 var curleft, curtop, cursor,
2540 o = this.options,
2541 iniPos = this.element.position(),
2542 el = this.element;
2543
2544 this.resizing = true;
2545
2546 // bugfix for http://dev.jquery.com/ticket/1749
2547 if ( (/absolute/).test( el.css("position") ) ) {
2548 el.css({ position: "absolute", top: el.css("top"), left: el.css("left") });
2549 } else if (el.is(".ui-draggable")) {
2550 el.css({ position: "absolute", top: iniPos.top, left: iniPos.left });
2551 }
2552
2553 this._renderProxy();
2554
2555 curleft = num(this.helper.css("left"));
2556 curtop = num(this.helper.css("top"));
2557
2558 if (o.containment) {
2559 curleft += $(o.containment).scrollLeft() || 0;
2560 curtop += $(o.containment).scrollTop() || 0;
2561 }
2562
2563 //Store needed variables
2564 this.offset = this.helper.offset();
2565 this.position = { left: curleft, top: curtop };
2566 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2567 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2568 this.originalPosition = { left: curleft, top: curtop };
2569 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
2570 this.originalMousePosition = { left: event.pageX, top: event.pageY };
2571
2572 //Aspect Ratio
2573 this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
2574
2575 cursor = $(".ui-resizable-" + this.axis).css("cursor");
2576 $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
2577
2578 el.addClass("ui-resizable-resizing");
2579 this._propagate("start", event);
2580 return true;
2581 },
2582
2583 _mouseDrag: function(event) {
2584
2585 //Increase performance, avoid regex
2586 var data,
2587 el = this.helper, props = {},
2588 smp = this.originalMousePosition,
2589 a = this.axis,
2590 prevTop = this.position.top,
2591 prevLeft = this.position.left,
2592 prevWidth = this.size.width,
2593 prevHeight = this.size.height,
2594 dx = (event.pageX-smp.left)||0,
2595 dy = (event.pageY-smp.top)||0,
2596 trigger = this._change[a];
2597
2598 if (!trigger) {
2599 return false;
2600 }
2601
2602 // Calculate the attrs that will be change
2603 data = trigger.apply(this, [event, dx, dy]);
2604
2605 // Put this in the mouseDrag handler since the user can start pressing shift while resizing
2606 this._updateVirtualBoundaries(event.shiftKey);
2607 if (this._aspectRatio || event.shiftKey) {
2608 data = this._updateRatio(data, event);
2609 }
2610
2611 data = this._respectSize(data, event);
2612
2613 this._updateCache(data);
2614
2615 // plugins callbacks need to be called first
2616 this._propagate("resize", event);
2617
2618 if (this.position.top !== prevTop) {
2619 props.top = this.position.top + "px";
2620 }
2621 if (this.position.left !== prevLeft) {
2622 props.left = this.position.left + "px";
2623 }
2624 if (this.size.width !== prevWidth) {
2625 props.width = this.size.width + "px";
2626 }
2627 if (this.size.height !== prevHeight) {
2628 props.height = this.size.height + "px";
2629 }
2630 el.css(props);
2631
2632 if (!this._helper && this._proportionallyResizeElements.length) {
2633 this._proportionallyResize();
2634 }
2635
2636 // Call the user callback if the element was resized
2637 if ( ! $.isEmptyObject(props) ) {
2638 this._trigger("resize", event, this.ui());
2639 }
2640
2641 return false;
2642 },
2643
2644 _mouseStop: function(event) {
2645
2646 this.resizing = false;
2647 var pr, ista, soffseth, soffsetw, s, left, top,
2648 o = this.options, that = this;
2649
2650 if(this._helper) {
2651
2652 pr = this._proportionallyResizeElements;
2653 ista = pr.length && (/textarea/i).test(pr[0].nodeName);
2654 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height;
2655 soffsetw = ista ? 0 : that.sizeDiff.width;
2656
2657 s = { width: (that.helper.width() - soffsetw), height: (that.helper.height() - soffseth) };
2658 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null;
2659 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
2660
2661 if (!o.animate) {
2662 this.element.css($.extend(s, { top: top, left: left }));
2663 }
2664
2665 that.helper.height(that.size.height);
2666 that.helper.width(that.size.width);
2667
2668 if (this._helper && !o.animate) {
2669 this._proportionallyResize();
2670 }
2671 }
2672
2673 $("body").css("cursor", "auto");
2674
2675 this.element.removeClass("ui-resizable-resizing");
2676
2677 this._propagate("stop", event);
2678
2679 if (this._helper) {
2680 this.helper.remove();
2681 }
2682
2683 return false;
2684
2685 },
2686
2687 _updateVirtualBoundaries: function(forceAspectRatio) {
2688 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
2689 o = this.options;
2690
2691 b = {
2692 minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
2693 maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
2694 minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
2695 maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
2696 };
2697
2698 if(this._aspectRatio || forceAspectRatio) {
2699 // We want to create an enclosing box whose aspect ration is the requested one
2700 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
2701 pMinWidth = b.minHeight * this.aspectRatio;
2702 pMinHeight = b.minWidth / this.aspectRatio;
2703 pMaxWidth = b.maxHeight * this.aspectRatio;
2704 pMaxHeight = b.maxWidth / this.aspectRatio;
2705
2706 if(pMinWidth > b.minWidth) {
2707 b.minWidth = pMinWidth;
2708 }
2709 if(pMinHeight > b.minHeight) {
2710 b.minHeight = pMinHeight;
2711 }
2712 if(pMaxWidth < b.maxWidth) {
2713 b.maxWidth = pMaxWidth;
2714 }
2715 if(pMaxHeight < b.maxHeight) {
2716 b.maxHeight = pMaxHeight;
2717 }
2718 }
2719 this._vBoundaries = b;
2720 },
2721
2722 _updateCache: function(data) {
2723 this.offset = this.helper.offset();
2724 if (isNumber(data.left)) {
2725 this.position.left = data.left;
2726 }
2727 if (isNumber(data.top)) {
2728 this.position.top = data.top;
2729 }
2730 if (isNumber(data.height)) {
2731 this.size.height = data.height;
2732 }
2733 if (isNumber(data.width)) {
2734 this.size.width = data.width;
2735 }
2736 },
2737
2738 _updateRatio: function( data ) {
2739
2740 var cpos = this.position,
2741 csize = this.size,
2742 a = this.axis;
2743
2744 if (isNumber(data.height)) {
2745 data.width = (data.height * this.aspectRatio);
2746 } else if (isNumber(data.width)) {
2747 data.height = (data.width / this.aspectRatio);
2748 }
2749
2750 if (a === "sw") {
2751 data.left = cpos.left + (csize.width - data.width);
2752 data.top = null;
2753 }
2754 if (a === "nw") {
2755 data.top = cpos.top + (csize.height - data.height);
2756 data.left = cpos.left + (csize.width - data.width);
2757 }
2758
2759 return data;
2760 },
2761
2762 _respectSize: function( data ) {
2763
2764 var o = this._vBoundaries,
2765 a = this.axis,
2766 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
2767 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
2768 dw = this.originalPosition.left + this.originalSize.width,
2769 dh = this.position.top + this.size.height,
2770 cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
2771 if (isminw) {
2772 data.width = o.minWidth;
2773 }
2774 if (isminh) {
2775 data.height = o.minHeight;
2776 }
2777 if (ismaxw) {
2778 data.width = o.maxWidth;
2779 }
2780 if (ismaxh) {
2781 data.height = o.maxHeight;
2782 }
2783
2784 if (isminw && cw) {
2785 data.left = dw - o.minWidth;
2786 }
2787 if (ismaxw && cw) {
2788 data.left = dw - o.maxWidth;
2789 }
2790 if (isminh && ch) {
2791 data.top = dh - o.minHeight;
2792 }
2793 if (ismaxh && ch) {
2794 data.top = dh - o.maxHeight;
2795 }
2796
2797 // fixing jump error on top/left - bug #2330
2798 if (!data.width && !data.height && !data.left && data.top) {
2799 data.top = null;
2800 } else if (!data.width && !data.height && !data.top && data.left) {
2801 data.left = null;
2802 }
2803
2804 return data;
2805 },
2806
2807 _proportionallyResize: function() {
2808
2809 if (!this._proportionallyResizeElements.length) {
2810 return;
2811 }
2812
2813 var i, j, borders, paddings, prel,
2814 element = this.helper || this.element;
2815
2816 for ( i=0; i < this._proportionallyResizeElements.length; i++) {
2817
2818 prel = this._proportionallyResizeElements[i];
2819
2820 if (!this.borderDif) {
2821 this.borderDif = [];
2822 borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")];
2823 paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")];
2824
2825 for ( j = 0; j < borders.length; j++ ) {
2826 this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 );
2827 }
2828 }
2829
2830 prel.css({
2831 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
2832 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
2833 });
2834
2835 }
2836
2837 },
2838
2839 _renderProxy: function() {
2840
2841 var el = this.element, o = this.options;
2842 this.elementOffset = el.offset();
2843
2844 if(this._helper) {
2845
2846 this.helper = this.helper || $("<div style='overflow:hidden;'></div>");
2847
2848 this.helper.addClass(this._helper).css({
2849 width: this.element.outerWidth() - 1,
2850 height: this.element.outerHeight() - 1,
2851 position: "absolute",
2852 left: this.elementOffset.left +"px",
2853 top: this.elementOffset.top +"px",
2854 zIndex: ++o.zIndex //TODO: Don't modify option
2855 });
2856
2857 this.helper
2858 .appendTo("body")
2859 .disableSelection();
2860
2861 } else {
2862 this.helper = this.element;
2863 }
2864
2865 },
2866
2867 _change: {
2868 e: function(event, dx) {
2869 return { width: this.originalSize.width + dx };
2870 },
2871 w: function(event, dx) {
2872 var cs = this.originalSize, sp = this.originalPosition;
2873 return { left: sp.left + dx, width: cs.width - dx };
2874 },
2875 n: function(event, dx, dy) {
2876 var cs = this.originalSize, sp = this.originalPosition;
2877 return { top: sp.top + dy, height: cs.height - dy };
2878 },
2879 s: function(event, dx, dy) {
2880 return { height: this.originalSize.height + dy };
2881 },
2882 se: function(event, dx, dy) {
2883 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2884 },
2885 sw: function(event, dx, dy) {
2886 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2887 },
2888 ne: function(event, dx, dy) {
2889 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2890 },
2891 nw: function(event, dx, dy) {
2892 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2893 }
2894 },
2895
2896 _propagate: function(n, event) {
2897 $.ui.plugin.call(this, n, [event, this.ui()]);
2898 (n !== "resize" && this._trigger(n, event, this.ui()));
2899 },
2900
2901 plugins: {},
2902
2903 ui: function() {
2904 return {
2905 originalElement: this.originalElement,
2906 element: this.element,
2907 helper: this.helper,
2908 position: this.position,
2909 size: this.size,
2910 originalSize: this.originalSize,
2911 originalPosition: this.originalPosition
2912 };
2913 }
2914
2915});
2916
2917/*
2918 * Resizable Extensions
2919 */
2920
2921$.ui.plugin.add("resizable", "animate", {
2922
2923 stop: function( event ) {
2924 var that = $(this).data("ui-resizable"),
2925 o = that.options,
2926 pr = that._proportionallyResizeElements,
2927 ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2928 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height,
2929 soffsetw = ista ? 0 : that.sizeDiff.width,
2930 style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
2931 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null,
2932 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
2933
2934 that.element.animate(
2935 $.extend(style, top && left ? { top: top, left: left } : {}), {
2936 duration: o.animateDuration,
2937 easing: o.animateEasing,
2938 step: function() {
2939
2940 var data = {
2941 width: parseInt(that.element.css("width"), 10),
2942 height: parseInt(that.element.css("height"), 10),
2943 top: parseInt(that.element.css("top"), 10),
2944 left: parseInt(that.element.css("left"), 10)
2945 };
2946
2947 if (pr && pr.length) {
2948 $(pr[0]).css({ width: data.width, height: data.height });
2949 }
2950
2951 // propagating resize, and updating values for each animation step
2952 that._updateCache(data);
2953 that._propagate("resize", event);
2954
2955 }
2956 }
2957 );
2958 }
2959
2960});
2961
2962$.ui.plugin.add("resizable", "containment", {
2963
2964 start: function() {
2965 var element, p, co, ch, cw, width, height,
2966 that = $(this).data("ui-resizable"),
2967 o = that.options,
2968 el = that.element,
2969 oc = o.containment,
2970 ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
2971
2972 if (!ce) {
2973 return;
2974 }
2975
2976 that.containerElement = $(ce);
2977
2978 if (/document/.test(oc) || oc === document) {
2979 that.containerOffset = { left: 0, top: 0 };
2980 that.containerPosition = { left: 0, top: 0 };
2981
2982 that.parentData = {
2983 element: $(document), left: 0, top: 0,
2984 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
2985 };
2986 }
2987
2988 // i'm a node, so compute top, left, right, bottom
2989 else {
2990 element = $(ce);
2991 p = [];
2992 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
2993
2994 that.containerOffset = element.offset();
2995 that.containerPosition = element.position();
2996 that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
2997
2998 co = that.containerOffset;
2999 ch = that.containerSize.height;
3000 cw = that.containerSize.width;
3001 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw );
3002 height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
3003
3004 that.parentData = {
3005 element: ce, left: co.left, top: co.top, width: width, height: height
3006 };
3007 }
3008 },
3009
3010 resize: function( event ) {
3011 var woset, hoset, isParent, isOffsetRelative,
3012 that = $(this).data("ui-resizable"),
3013 o = that.options,
3014 co = that.containerOffset, cp = that.position,
3015 pRatio = that._aspectRatio || event.shiftKey,
3016 cop = { top:0, left:0 }, ce = that.containerElement;
3017
3018 if (ce[0] !== document && (/static/).test(ce.css("position"))) {
3019 cop = co;
3020 }
3021
3022 if (cp.left < (that._helper ? co.left : 0)) {
3023 that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left));
3024 if (pRatio) {
3025 that.size.height = that.size.width / that.aspectRatio;
3026 }
3027 that.position.left = o.helper ? co.left : 0;
3028 }
3029
3030 if (cp.top < (that._helper ? co.top : 0)) {
3031 that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top);
3032 if (pRatio) {
3033 that.size.width = that.size.height * that.aspectRatio;
3034 }
3035 that.position.top = that._helper ? co.top : 0;
3036 }
3037
3038 that.offset.left = that.parentData.left+that.position.left;
3039 that.offset.top = that.parentData.top+that.position.top;
3040
3041 woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width );
3042 hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height );
3043
3044 isParent = that.containerElement.get(0) === that.element.parent().get(0);
3045 isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position"));
3046
3047 if(isParent && isOffsetRelative) {
3048 woset -= that.parentData.left;
3049 }
3050
3051 if (woset + that.size.width >= that.parentData.width) {
3052 that.size.width = that.parentData.width - woset;
3053 if (pRatio) {
3054 that.size.height = that.size.width / that.aspectRatio;
3055 }
3056 }
3057
3058 if (hoset + that.size.height >= that.parentData.height) {
3059 that.size.height = that.parentData.height - hoset;
3060 if (pRatio) {
3061 that.size.width = that.size.height * that.aspectRatio;
3062 }
3063 }
3064 },
3065
3066 stop: function(){
3067 var that = $(this).data("ui-resizable"),
3068 o = that.options,
3069 co = that.containerOffset,
3070 cop = that.containerPosition,
3071 ce = that.containerElement,
3072 helper = $(that.helper),
3073 ho = helper.offset(),
3074 w = helper.outerWidth() - that.sizeDiff.width,
3075 h = helper.outerHeight() - that.sizeDiff.height;
3076
3077 if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) {
3078 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
3079 }
3080
3081 if (that._helper && !o.animate && (/static/).test(ce.css("position"))) {
3082 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
3083 }
3084
3085 }
3086});
3087
3088$.ui.plugin.add("resizable", "alsoResize", {
3089
3090 start: function () {
3091 var that = $(this).data("ui-resizable"),
3092 o = that.options,
3093 _store = function (exp) {
3094 $(exp).each(function() {
3095 var el = $(this);
3096 el.data("ui-resizable-alsoresize", {
3097 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
3098 left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
3099 });
3100 });
3101 };
3102
3103 if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) {
3104 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
3105 else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
3106 }else{
3107 _store(o.alsoResize);
3108 }
3109 },
3110
3111 resize: function (event, ui) {
3112 var that = $(this).data("ui-resizable"),
3113 o = that.options,
3114 os = that.originalSize,
3115 op = that.originalPosition,
3116 delta = {
3117 height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0,
3118 top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0
3119 },
3120
3121 _alsoResize = function (exp, c) {
3122 $(exp).each(function() {
3123 var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
3124 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"];
3125
3126 $.each(css, function (i, prop) {
3127 var sum = (start[prop]||0) + (delta[prop]||0);
3128 if (sum && sum >= 0) {
3129 style[prop] = sum || null;
3130 }
3131 });
3132
3133 el.css(style);
3134 });
3135 };
3136
3137 if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) {
3138 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
3139 }else{
3140 _alsoResize(o.alsoResize);
3141 }
3142 },
3143
3144 stop: function () {
3145 $(this).removeData("resizable-alsoresize");
3146 }
3147});
3148
3149$.ui.plugin.add("resizable", "ghost", {
3150
3151 start: function() {
3152
3153 var that = $(this).data("ui-resizable"), o = that.options, cs = that.size;
3154
3155 that.ghost = that.originalElement.clone();
3156 that.ghost
3157 .css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
3158 .addClass("ui-resizable-ghost")
3159 .addClass(typeof o.ghost === "string" ? o.ghost : "");
3160
3161 that.ghost.appendTo(that.helper);
3162
3163 },
3164
3165 resize: function(){
3166 var that = $(this).data("ui-resizable");
3167 if (that.ghost) {
3168 that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width });
3169 }
3170 },
3171
3172 stop: function() {
3173 var that = $(this).data("ui-resizable");
3174 if (that.ghost && that.helper) {
3175 that.helper.get(0).removeChild(that.ghost.get(0));
3176 }
3177 }
3178
3179});
3180
3181$.ui.plugin.add("resizable", "grid", {
3182
3183 resize: function() {
3184 var that = $(this).data("ui-resizable"),
3185 o = that.options,
3186 cs = that.size,
3187 os = that.originalSize,
3188 op = that.originalPosition,
3189 a = that.axis,
3190 grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid,
3191 gridX = (grid[0]||1),
3192 gridY = (grid[1]||1),
3193 ox = Math.round((cs.width - os.width) / gridX) * gridX,
3194 oy = Math.round((cs.height - os.height) / gridY) * gridY,
3195 newWidth = os.width + ox,
3196 newHeight = os.height + oy,
3197 isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
3198 isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
3199 isMinWidth = o.minWidth && (o.minWidth > newWidth),
3200 isMinHeight = o.minHeight && (o.minHeight > newHeight);
3201
3202 o.grid = grid;
3203
3204 if (isMinWidth) {
3205 newWidth = newWidth + gridX;
3206 }
3207 if (isMinHeight) {
3208 newHeight = newHeight + gridY;
3209 }
3210 if (isMaxWidth) {
3211 newWidth = newWidth - gridX;
3212 }
3213 if (isMaxHeight) {
3214 newHeight = newHeight - gridY;
3215 }
3216
3217 if (/^(se|s|e)$/.test(a)) {
3218 that.size.width = newWidth;
3219 that.size.height = newHeight;
3220 } else if (/^(ne)$/.test(a)) {
3221 that.size.width = newWidth;
3222 that.size.height = newHeight;
3223 that.position.top = op.top - oy;
3224 } else if (/^(sw)$/.test(a)) {
3225 that.size.width = newWidth;
3226 that.size.height = newHeight;
3227 that.position.left = op.left - ox;
3228 } else {
3229 that.size.width = newWidth;
3230 that.size.height = newHeight;
3231 that.position.top = op.top - oy;
3232 that.position.left = op.left - ox;
3233 }
3234 }
3235
3236});
3237
3238})(jQuery);
3239
3240(function( $, undefined ) {
3241
3242$.widget("ui.selectable", $.ui.mouse, {
3243 version: "1.10.3",
3244 options: {
3245 appendTo: "body",
3246 autoRefresh: true,
3247 distance: 0,
3248 filter: "*",
3249 tolerance: "touch",
3250
3251 // callbacks
3252 selected: null,
3253 selecting: null,
3254 start: null,
3255 stop: null,
3256 unselected: null,
3257 unselecting: null
3258 },
3259 _create: function() {
3260 var selectees,
3261 that = this;
3262
3263 this.element.addClass("ui-selectable");
3264
3265 this.dragged = false;
3266
3267 // cache selectee children based on filter
3268 this.refresh = function() {
3269 selectees = $(that.options.filter, that.element[0]);
3270 selectees.addClass("ui-selectee");
3271 selectees.each(function() {
3272 var $this = $(this),
3273 pos = $this.offset();
3274 $.data(this, "selectable-item", {
3275 element: this,
3276 $element: $this,
3277 left: pos.left,
3278 top: pos.top,
3279 right: pos.left + $this.outerWidth(),
3280 bottom: pos.top + $this.outerHeight(),
3281 startselected: false,
3282 selected: $this.hasClass("ui-selected"),
3283 selecting: $this.hasClass("ui-selecting"),
3284 unselecting: $this.hasClass("ui-unselecting")
3285 });
3286 });
3287 };
3288 this.refresh();
3289
3290 this.selectees = selectees.addClass("ui-selectee");
3291
3292 this._mouseInit();
3293
3294 this.helper = $("<div class='ui-selectable-helper'></div>");
3295 },
3296
3297 _destroy: function() {
3298 this.selectees
3299 .removeClass("ui-selectee")
3300 .removeData("selectable-item");
3301 this.element
3302 .removeClass("ui-selectable ui-selectable-disabled");
3303 this._mouseDestroy();
3304 },
3305
3306 _mouseStart: function(event) {
3307 var that = this,
3308 options = this.options;
3309
3310 this.opos = [event.pageX, event.pageY];
3311
3312 if (this.options.disabled) {
3313 return;
3314 }
3315
3316 this.selectees = $(options.filter, this.element[0]);
3317
3318 this._trigger("start", event);
3319
3320 $(options.appendTo).append(this.helper);
3321 // position helper (lasso)
3322 this.helper.css({
3323 "left": event.pageX,
3324 "top": event.pageY,
3325 "width": 0,
3326 "height": 0
3327 });
3328
3329 if (options.autoRefresh) {
3330 this.refresh();
3331 }
3332
3333 this.selectees.filter(".ui-selected").each(function() {
3334 var selectee = $.data(this, "selectable-item");
3335 selectee.startselected = true;
3336 if (!event.metaKey && !event.ctrlKey) {
3337 selectee.$element.removeClass("ui-selected");
3338 selectee.selected = false;
3339 selectee.$element.addClass("ui-unselecting");
3340 selectee.unselecting = true;
3341 // selectable UNSELECTING callback
3342 that._trigger("unselecting", event, {
3343 unselecting: selectee.element
3344 });
3345 }
3346 });
3347
3348 $(event.target).parents().addBack().each(function() {
3349 var doSelect,
3350 selectee = $.data(this, "selectable-item");
3351 if (selectee) {
3352 doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");
3353 selectee.$element
3354 .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
3355 .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
3356 selectee.unselecting = !doSelect;
3357 selectee.selecting = doSelect;
3358 selectee.selected = doSelect;
3359 // selectable (UN)SELECTING callback
3360 if (doSelect) {
3361 that._trigger("selecting", event, {
3362 selecting: selectee.element
3363 });
3364 } else {
3365 that._trigger("unselecting", event, {
3366 unselecting: selectee.element
3367 });
3368 }
3369 return false;
3370 }
3371 });
3372
3373 },
3374
3375 _mouseDrag: function(event) {
3376
3377 this.dragged = true;
3378
3379 if (this.options.disabled) {
3380 return;
3381 }
3382
3383 var tmp,
3384 that = this,
3385 options = this.options,
3386 x1 = this.opos[0],
3387 y1 = this.opos[1],
3388 x2 = event.pageX,
3389 y2 = event.pageY;
3390
3391 if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
3392 if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
3393 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
3394
3395 this.selectees.each(function() {
3396 var selectee = $.data(this, "selectable-item"),
3397 hit = false;
3398
3399 //prevent helper from being selected if appendTo: selectable
3400 if (!selectee || selectee.element === that.element[0]) {
3401 return;
3402 }
3403
3404 if (options.tolerance === "touch") {
3405 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
3406 } else if (options.tolerance === "fit") {
3407 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
3408 }
3409
3410 if (hit) {
3411 // SELECT
3412 if (selectee.selected) {
3413 selectee.$element.removeClass("ui-selected");
3414 selectee.selected = false;
3415 }
3416 if (selectee.unselecting) {
3417 selectee.$element.removeClass("ui-unselecting");
3418 selectee.unselecting = false;
3419 }
3420 if (!selectee.selecting) {
3421 selectee.$element.addClass("ui-selecting");
3422 selectee.selecting = true;
3423 // selectable SELECTING callback
3424 that._trigger("selecting", event, {
3425 selecting: selectee.element
3426 });
3427 }
3428 } else {
3429 // UNSELECT
3430 if (selectee.selecting) {
3431 if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
3432 selectee.$element.removeClass("ui-selecting");
3433 selectee.selecting = false;
3434 selectee.$element.addClass("ui-selected");
3435 selectee.selected = true;
3436 } else {
3437 selectee.$element.removeClass("ui-selecting");
3438 selectee.selecting = false;
3439 if (selectee.startselected) {
3440 selectee.$element.addClass("ui-unselecting");
3441 selectee.unselecting = true;
3442 }
3443 // selectable UNSELECTING callback
3444 that._trigger("unselecting", event, {
3445 unselecting: selectee.element
3446 });
3447 }
3448 }
3449 if (selectee.selected) {
3450 if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
3451 selectee.$element.removeClass("ui-selected");
3452 selectee.selected = false;
3453
3454 selectee.$element.addClass("ui-unselecting");
3455 selectee.unselecting = true;
3456 // selectable UNSELECTING callback
3457 that._trigger("unselecting", event, {
3458 unselecting: selectee.element
3459 });
3460 }
3461 }
3462 }
3463 });
3464
3465 return false;
3466 },
3467
3468 _mouseStop: function(event) {
3469 var that = this;
3470
3471 this.dragged = false;
3472
3473 $(".ui-unselecting", this.element[0]).each(function() {
3474 var selectee = $.data(this, "selectable-item");
3475 selectee.$element.removeClass("ui-unselecting");
3476 selectee.unselecting = false;
3477 selectee.startselected = false;
3478 that._trigger("unselected", event, {
3479 unselected: selectee.element
3480 });
3481 });
3482 $(".ui-selecting", this.element[0]).each(function() {
3483 var selectee = $.data(this, "selectable-item");
3484 selectee.$element.removeClass("ui-selecting").addClass("ui-selected");
3485 selectee.selecting = false;
3486 selectee.selected = true;
3487 selectee.startselected = true;
3488 that._trigger("selected", event, {
3489 selected: selectee.element
3490 });
3491 });
3492 this._trigger("stop", event);
3493
3494 this.helper.remove();
3495
3496 return false;
3497 }
3498
3499});
3500
3501})(jQuery);
3502
3503(function( $, undefined ) {
3504
3505/*jshint loopfunc: true */
3506
3507function isOverAxis( x, reference, size ) {
3508 return ( x > reference ) && ( x < ( reference + size ) );
3509}
3510
3511function isFloating(item) {
3512 return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display"));
3513}
3514
3515$.widget("ui.sortable", $.ui.mouse, {
3516 version: "1.10.3",
3517 widgetEventPrefix: "sort",
3518 ready: false,
3519 options: {
3520 appendTo: "parent",
3521 axis: false,
3522 connectWith: false,
3523 containment: false,
3524 cursor: "auto",
3525 cursorAt: false,
3526 dropOnEmpty: true,
3527 forcePlaceholderSize: false,
3528 forceHelperSize: false,
3529 grid: false,
3530 handle: false,
3531 helper: "original",
3532 items: "> *",
3533 opacity: false,
3534 placeholder: false,
3535 revert: false,
3536 scroll: true,
3537 scrollSensitivity: 20,
3538 scrollSpeed: 20,
3539 scope: "default",
3540 tolerance: "intersect",
3541 zIndex: 1000,
3542
3543 // callbacks
3544 activate: null,
3545 beforeStop: null,
3546 change: null,
3547 deactivate: null,
3548 out: null,
3549 over: null,
3550 receive: null,
3551 remove: null,
3552 sort: null,
3553 start: null,
3554 stop: null,
3555 update: null
3556 },
3557 _create: function() {
3558
3559 var o = this.options;
3560 this.containerCache = {};
3561 this.element.addClass("ui-sortable");
3562
3563 //Get the items
3564 this.refresh();
3565
3566 //Let's determine if the items are being displayed horizontally
3567 this.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false;
3568
3569 //Let's determine the parent's offset
3570 this.offset = this.element.offset();
3571
3572 //Initialize mouse events for interaction
3573 this._mouseInit();
3574
3575 //We're ready to go
3576 this.ready = true;
3577
3578 },
3579
3580 _destroy: function() {
3581 this.element
3582 .removeClass("ui-sortable ui-sortable-disabled");
3583 this._mouseDestroy();
3584
3585 for ( var i = this.items.length - 1; i >= 0; i-- ) {
3586 this.items[i].item.removeData(this.widgetName + "-item");
3587 }
3588
3589 return this;
3590 },
3591
3592 _setOption: function(key, value){
3593 if ( key === "disabled" ) {
3594 this.options[ key ] = value;
3595
3596 this.widget().toggleClass( "ui-sortable-disabled", !!value );
3597 } else {
3598 // Don't call widget base _setOption for disable as it adds ui-state-disabled class
3599 $.Widget.prototype._setOption.apply(this, arguments);
3600 }
3601 },
3602
3603 _mouseCapture: function(event, overrideHandle) {
3604 var currentItem = null,
3605 validHandle = false,
3606 that = this;
3607
3608 if (this.reverting) {
3609 return false;
3610 }
3611
3612 if(this.options.disabled || this.options.type === "static") {
3613 return false;
3614 }
3615
3616 //We have to refresh the items data once first
3617 this._refreshItems(event);
3618
3619 //Find out if the clicked node (or one of its parents) is a actual item in this.items
3620 $(event.target).parents().each(function() {
3621 if($.data(this, that.widgetName + "-item") === that) {
3622 currentItem = $(this);
3623 return false;
3624 }
3625 });
3626 if($.data(event.target, that.widgetName + "-item") === that) {
3627 currentItem = $(event.target);
3628 }
3629
3630 if(!currentItem) {
3631 return false;
3632 }
3633 if(this.options.handle && !overrideHandle) {
3634 $(this.options.handle, currentItem).find("*").addBack().each(function() {
3635 if(this === event.target) {
3636 validHandle = true;
3637 }
3638 });
3639 if(!validHandle) {
3640 return false;
3641 }
3642 }
3643
3644 this.currentItem = currentItem;
3645 this._removeCurrentsFromItems();
3646 return true;
3647
3648 },
3649
3650 _mouseStart: function(event, overrideHandle, noActivation) {
3651
3652 var i, body,
3653 o = this.options;
3654
3655 this.currentContainer = this;
3656
3657 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
3658 this.refreshPositions();
3659
3660 //Create and append the visible helper
3661 this.helper = this._createHelper(event);
3662
3663 //Cache the helper size
3664 this._cacheHelperProportions();
3665
3666 /*
3667 * - Position generation -
3668 * This block generates everything position related - it's the core of draggables.
3669 */
3670
3671 //Cache the margins of the original element
3672 this._cacheMargins();
3673
3674 //Get the next scrolling parent
3675 this.scrollParent = this.helper.scrollParent();
3676
3677 //The element's absolute position on the page minus margins
3678 this.offset = this.currentItem.offset();
3679 this.offset = {
3680 top: this.offset.top - this.margins.top,
3681 left: this.offset.left - this.margins.left
3682 };
3683
3684 $.extend(this.offset, {
3685 click: { //Where the click happened, relative to the element
3686 left: event.pageX - this.offset.left,
3687 top: event.pageY - this.offset.top
3688 },
3689 parent: this._getParentOffset(),
3690 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
3691 });
3692
3693 // Only after we got the offset, we can change the helper's position to absolute
3694 // TODO: Still need to figure out a way to make relative sorting possible
3695 this.helper.css("position", "absolute");
3696 this.cssPosition = this.helper.css("position");
3697
3698 //Generate the original position
3699 this.originalPosition = this._generatePosition(event);
3700 this.originalPageX = event.pageX;
3701 this.originalPageY = event.pageY;
3702
3703 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
3704 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
3705
3706 //Cache the former DOM position
3707 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
3708
3709 //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
3710 if(this.helper[0] !== this.currentItem[0]) {
3711 this.currentItem.hide();
3712 }
3713
3714 //Create the placeholder
3715 this._createPlaceholder();
3716
3717 //Set a containment if given in the options
3718 if(o.containment) {
3719 this._setContainment();
3720 }
3721
3722 if( o.cursor && o.cursor !== "auto" ) { // cursor option
3723 body = this.document.find( "body" );
3724
3725 // support: IE
3726 this.storedCursor = body.css( "cursor" );
3727 body.css( "cursor", o.cursor );
3728
3729 this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );
3730 }
3731
3732 if(o.opacity) { // opacity option
3733 if (this.helper.css("opacity")) {
3734 this._storedOpacity = this.helper.css("opacity");
3735 }
3736 this.helper.css("opacity", o.opacity);
3737 }
3738
3739 if(o.zIndex) { // zIndex option
3740 if (this.helper.css("zIndex")) {
3741 this._storedZIndex = this.helper.css("zIndex");
3742 }
3743 this.helper.css("zIndex", o.zIndex);
3744 }
3745
3746 //Prepare scrolling
3747 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
3748 this.overflowOffset = this.scrollParent.offset();
3749 }
3750
3751 //Call callbacks
3752 this._trigger("start", event, this._uiHash());
3753
3754 //Recache the helper size
3755 if(!this._preserveHelperProportions) {
3756 this._cacheHelperProportions();
3757 }
3758
3759
3760 //Post "activate" events to possible containers
3761 if( !noActivation ) {
3762 for ( i = this.containers.length - 1; i >= 0; i-- ) {
3763 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
3764 }
3765 }
3766
3767 //Prepare possible droppables
3768 if($.ui.ddmanager) {
3769 $.ui.ddmanager.current = this;
3770 }
3771
3772 if ($.ui.ddmanager && !o.dropBehaviour) {
3773 $.ui.ddmanager.prepareOffsets(this, event);
3774 }
3775
3776 this.dragging = true;
3777
3778 this.helper.addClass("ui-sortable-helper");
3779 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
3780 return true;
3781
3782 },
3783
3784 _mouseDrag: function(event) {
3785 var i, item, itemElement, intersection,
3786 o = this.options,
3787 scrolled = false;
3788
3789 //Compute the helpers position
3790 this.position = this._generatePosition(event);
3791 this.positionAbs = this._convertPositionTo("absolute");
3792
3793 if (!this.lastPositionAbs) {
3794 this.lastPositionAbs = this.positionAbs;
3795 }
3796
3797 //Do scrolling
3798 if(this.options.scroll) {
3799 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
3800
3801 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
3802 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
3803 } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
3804 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
3805 }
3806
3807 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
3808 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
3809 } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
3810 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
3811 }
3812
3813 } else {
3814
3815 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
3816 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
3817 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
3818 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
3819 }
3820
3821 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
3822 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
3823 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
3824 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
3825 }
3826
3827 }
3828
3829 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
3830 $.ui.ddmanager.prepareOffsets(this, event);
3831 }
3832 }
3833
3834 //Regenerate the absolute position used for position checks
3835 this.positionAbs = this._convertPositionTo("absolute");
3836
3837 //Set the helper position
3838 if(!this.options.axis || this.options.axis !== "y") {
3839 this.helper[0].style.left = this.position.left+"px";
3840 }
3841 if(!this.options.axis || this.options.axis !== "x") {
3842 this.helper[0].style.top = this.position.top+"px";
3843 }
3844
3845 //Rearrange
3846 for (i = this.items.length - 1; i >= 0; i--) {
3847
3848 //Cache variables and intersection, continue if no intersection
3849 item = this.items[i];
3850 itemElement = item.item[0];
3851 intersection = this._intersectsWithPointer(item);
3852 if (!intersection) {
3853 continue;
3854 }
3855
3856 // Only put the placeholder inside the current Container, skip all
3857 // items form other containers. This works because when moving
3858 // an item from one container to another the
3859 // currentContainer is switched before the placeholder is moved.
3860 //
3861 // Without this moving items in "sub-sortables" can cause the placeholder to jitter
3862 // beetween the outer and inner container.
3863 if (item.instance !== this.currentContainer) {
3864 continue;
3865 }
3866
3867 // cannot intersect with itself
3868 // no useless actions that have been done before
3869 // no action if the item moved is the parent of the item checked
3870 if (itemElement !== this.currentItem[0] &&
3871 this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
3872 !$.contains(this.placeholder[0], itemElement) &&
3873 (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
3874 ) {
3875
3876 this.direction = intersection === 1 ? "down" : "up";
3877
3878 if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
3879 this._rearrange(event, item);
3880 } else {
3881 break;
3882 }
3883
3884 this._trigger("change", event, this._uiHash());
3885 break;
3886 }
3887 }
3888
3889 //Post events to containers
3890 this._contactContainers(event);
3891
3892 //Interconnect with droppables
3893 if($.ui.ddmanager) {
3894 $.ui.ddmanager.drag(this, event);
3895 }
3896
3897 //Call callbacks
3898 this._trigger("sort", event, this._uiHash());
3899
3900 this.lastPositionAbs = this.positionAbs;
3901 return false;
3902
3903 },
3904
3905 _mouseStop: function(event, noPropagation) {
3906
3907 if(!event) {
3908 return;
3909 }
3910
3911 //If we are using droppables, inform the manager about the drop
3912 if ($.ui.ddmanager && !this.options.dropBehaviour) {
3913 $.ui.ddmanager.drop(this, event);
3914 }
3915
3916 if(this.options.revert) {
3917 var that = this,
3918 cur = this.placeholder.offset(),
3919 axis = this.options.axis,
3920 animation = {};
3921
3922 if ( !axis || axis === "x" ) {
3923 animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft);
3924 }
3925 if ( !axis || axis === "y" ) {
3926 animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop);
3927 }
3928 this.reverting = true;
3929 $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {
3930 that._clear(event);
3931 });
3932 } else {
3933 this._clear(event, noPropagation);
3934 }
3935
3936 return false;
3937
3938 },
3939
3940 cancel: function() {
3941
3942 if(this.dragging) {
3943
3944 this._mouseUp({ target: null });
3945
3946 if(this.options.helper === "original") {
3947 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3948 } else {
3949 this.currentItem.show();
3950 }
3951
3952 //Post deactivating events to containers
3953 for (var i = this.containers.length - 1; i >= 0; i--){
3954 this.containers[i]._trigger("deactivate", null, this._uiHash(this));
3955 if(this.containers[i].containerCache.over) {
3956 this.containers[i]._trigger("out", null, this._uiHash(this));
3957 this.containers[i].containerCache.over = 0;
3958 }
3959 }
3960
3961 }
3962
3963 if (this.placeholder) {
3964 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3965 if(this.placeholder[0].parentNode) {
3966 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3967 }
3968 if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
3969 this.helper.remove();
3970 }
3971
3972 $.extend(this, {
3973 helper: null,
3974 dragging: false,
3975 reverting: false,
3976 _noFinalSort: null
3977 });
3978
3979 if(this.domPosition.prev) {
3980 $(this.domPosition.prev).after(this.currentItem);
3981 } else {
3982 $(this.domPosition.parent).prepend(this.currentItem);
3983 }
3984 }
3985
3986 return this;
3987
3988 },
3989
3990 serialize: function(o) {
3991
3992 var items = this._getItemsAsjQuery(o && o.connected),
3993 str = [];
3994 o = o || {};
3995
3996 $(items).each(function() {
3997 var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/));
3998 if (res) {
3999 str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));
4000 }
4001 });
4002
4003 if(!str.length && o.key) {
4004 str.push(o.key + "=");
4005 }
4006
4007 return str.join("&");
4008
4009 },
4010
4011 toArray: function(o) {
4012
4013 var items = this._getItemsAsjQuery(o && o.connected),
4014 ret = [];
4015
4016 o = o || {};
4017
4018 items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
4019 return ret;
4020
4021 },
4022
4023 /* Be careful with the following core functions */
4024 _intersectsWith: function(item) {
4025
4026 var x1 = this.positionAbs.left,
4027 x2 = x1 + this.helperProportions.width,
4028 y1 = this.positionAbs.top,
4029 y2 = y1 + this.helperProportions.height,
4030 l = item.left,
4031 r = l + item.width,
4032 t = item.top,
4033 b = t + item.height,
4034 dyClick = this.offset.click.top,
4035 dxClick = this.offset.click.left,
4036 isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),
4037 isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),
4038 isOverElement = isOverElementHeight && isOverElementWidth;
4039
4040 if ( this.options.tolerance === "pointer" ||
4041 this.options.forcePointerForContainers ||
4042 (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])
4043 ) {
4044 return isOverElement;
4045 } else {
4046
4047 return (l < x1 + (this.helperProportions.width / 2) && // Right Half
4048 x2 - (this.helperProportions.width / 2) < r && // Left Half
4049 t < y1 + (this.helperProportions.height / 2) && // Bottom Half
4050 y2 - (this.helperProportions.height / 2) < b ); // Top Half
4051
4052 }
4053 },
4054
4055 _intersectsWithPointer: function(item) {
4056
4057 var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
4058 isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
4059 isOverElement = isOverElementHeight && isOverElementWidth,
4060 verticalDirection = this._getDragVerticalDirection(),
4061 horizontalDirection = this._getDragHorizontalDirection();
4062
4063 if (!isOverElement) {
4064 return false;
4065 }
4066
4067 return this.floating ?
4068 ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )
4069 : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );
4070
4071 },
4072
4073 _intersectsWithSides: function(item) {
4074
4075 var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
4076 isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
4077 verticalDirection = this._getDragVerticalDirection(),
4078 horizontalDirection = this._getDragHorizontalDirection();
4079
4080 if (this.floating && horizontalDirection) {
4081 return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
4082 } else {
4083 return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
4084 }
4085
4086 },
4087
4088 _getDragVerticalDirection: function() {
4089 var delta = this.positionAbs.top - this.lastPositionAbs.top;
4090 return delta !== 0 && (delta > 0 ? "down" : "up");
4091 },
4092
4093 _getDragHorizontalDirection: function() {
4094 var delta = this.positionAbs.left - this.lastPositionAbs.left;
4095 return delta !== 0 && (delta > 0 ? "right" : "left");
4096 },
4097
4098 refresh: function(event) {
4099 this._refreshItems(event);
4100 this.refreshPositions();
4101 return this;
4102 },
4103
4104 _connectWith: function() {
4105 var options = this.options;
4106 return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
4107 },
4108
4109 _getItemsAsjQuery: function(connected) {
4110
4111 var i, j, cur, inst,
4112 items = [],
4113 queries = [],
4114 connectWith = this._connectWith();
4115
4116 if(connectWith && connected) {
4117 for (i = connectWith.length - 1; i >= 0; i--){
4118 cur = $(connectWith[i]);
4119 for ( j = cur.length - 1; j >= 0; j--){
4120 inst = $.data(cur[j], this.widgetFullName);
4121 if(inst && inst !== this && !inst.options.disabled) {
4122 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]);
4123 }
4124 }
4125 }
4126 }
4127
4128 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]);
4129
4130 for (i = queries.length - 1; i >= 0; i--){
4131 queries[i][0].each(function() {
4132 items.push(this);
4133 });
4134 }
4135
4136 return $(items);
4137
4138 },
4139
4140 _removeCurrentsFromItems: function() {
4141
4142 var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
4143
4144 this.items = $.grep(this.items, function (item) {
4145 for (var j=0; j < list.length; j++) {
4146 if(list[j] === item.item[0]) {
4147 return false;
4148 }
4149 }
4150 return true;
4151 });
4152
4153 },
4154
4155 _refreshItems: function(event) {
4156
4157 this.items = [];
4158 this.containers = [this];
4159
4160 var i, j, cur, inst, targetData, _queries, item, queriesLength,
4161 items = this.items,
4162 queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],
4163 connectWith = this._connectWith();
4164
4165 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
4166 for (i = connectWith.length - 1; i >= 0; i--){
4167 cur = $(connectWith[i]);
4168 for (j = cur.length - 1; j >= 0; j--){
4169 inst = $.data(cur[j], this.widgetFullName);
4170 if(inst && inst !== this && !inst.options.disabled) {
4171 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
4172 this.containers.push(inst);
4173 }
4174 }
4175 }
4176 }
4177
4178 for (i = queries.length - 1; i >= 0; i--) {
4179 targetData = queries[i][1];
4180 _queries = queries[i][0];
4181
4182 for (j=0, queriesLength = _queries.length; j < queriesLength; j++) {
4183 item = $(_queries[j]);
4184
4185 item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)
4186
4187 items.push({
4188 item: item,
4189 instance: targetData,
4190 width: 0, height: 0,
4191 left: 0, top: 0
4192 });
4193 }
4194 }
4195
4196 },
4197
4198 refreshPositions: function(fast) {
4199
4200 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
4201 if(this.offsetParent && this.helper) {
4202 this.offset.parent = this._getParentOffset();
4203 }
4204
4205 var i, item, t, p;
4206
4207 for (i = this.items.length - 1; i >= 0; i--){
4208 item = this.items[i];
4209
4210 //We ignore calculating positions of all connected containers when we're not over them
4211 if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
4212 continue;
4213 }
4214
4215 t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
4216
4217 if (!fast) {
4218 item.width = t.outerWidth();
4219 item.height = t.outerHeight();
4220 }
4221
4222 p = t.offset();
4223 item.left = p.left;
4224 item.top = p.top;
4225 }
4226
4227 if(this.options.custom && this.options.custom.refreshContainers) {
4228 this.options.custom.refreshContainers.call(this);
4229 } else {
4230 for (i = this.containers.length - 1; i >= 0; i--){
4231 p = this.containers[i].element.offset();
4232 this.containers[i].containerCache.left = p.left;
4233 this.containers[i].containerCache.top = p.top;
4234 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
4235 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
4236 }
4237 }
4238
4239 return this;
4240 },
4241
4242 _createPlaceholder: function(that) {
4243 that = that || this;
4244 var className,
4245 o = that.options;
4246
4247 if(!o.placeholder || o.placeholder.constructor === String) {
4248 className = o.placeholder;
4249 o.placeholder = {
4250 element: function() {
4251
4252 var nodeName = that.currentItem[0].nodeName.toLowerCase(),
4253 element = $( "<" + nodeName + ">", that.document[0] )
4254 .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
4255 .removeClass("ui-sortable-helper");
4256
4257 if ( nodeName === "tr" ) {
4258 that.currentItem.children().each(function() {
4259 $( "<td>&#160;</td>", that.document[0] )
4260 .attr( "colspan", $( this ).attr( "colspan" ) || 1 )
4261 .appendTo( element );
4262 });
4263 } else if ( nodeName === "img" ) {
4264 element.attr( "src", that.currentItem.attr( "src" ) );
4265 }
4266
4267 if ( !className ) {
4268 element.css( "visibility", "hidden" );
4269 }
4270
4271 return element;
4272 },
4273 update: function(container, p) {
4274
4275 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
4276 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
4277 if(className && !o.forcePlaceholderSize) {
4278 return;
4279 }
4280
4281 //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
4282 if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }
4283 if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }
4284 }
4285 };
4286 }
4287
4288 //Create the placeholder
4289 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
4290
4291 //Append it after the actual current item
4292 that.currentItem.after(that.placeholder);
4293
4294 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
4295 o.placeholder.update(that, that.placeholder);
4296
4297 },
4298
4299 _contactContainers: function(event) {
4300 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating,
4301 innermostContainer = null,
4302 innermostIndex = null;
4303
4304 // get innermost container that intersects with item
4305 for (i = this.containers.length - 1; i >= 0; i--) {
4306
4307 // never consider a container that's located within the item itself
4308 if($.contains(this.currentItem[0], this.containers[i].element[0])) {
4309 continue;
4310 }
4311
4312 if(this._intersectsWith(this.containers[i].containerCache)) {
4313
4314 // if we've already found a container and it's more "inner" than this, then continue
4315 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
4316 continue;
4317 }
4318
4319 innermostContainer = this.containers[i];
4320 innermostIndex = i;
4321
4322 } else {
4323 // container doesn't intersect. trigger "out" event if necessary
4324 if(this.containers[i].containerCache.over) {
4325 this.containers[i]._trigger("out", event, this._uiHash(this));
4326 this.containers[i].containerCache.over = 0;
4327 }
4328 }
4329
4330 }
4331
4332 // if no intersecting containers found, return
4333 if(!innermostContainer) {
4334 return;
4335 }
4336
4337 // move the item into the container if it's not there already
4338 if(this.containers.length === 1) {
4339 if (!this.containers[innermostIndex].containerCache.over) {
4340 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
4341 this.containers[innermostIndex].containerCache.over = 1;
4342 }
4343 } else {
4344
4345 //When entering a new container, we will find the item with the least distance and append our item near it
4346 dist = 10000;
4347 itemWithLeastDistance = null;
4348 floating = innermostContainer.floating || isFloating(this.currentItem);
4349 posProperty = floating ? "left" : "top";
4350 sizeProperty = floating ? "width" : "height";
4351 base = this.positionAbs[posProperty] + this.offset.click[posProperty];
4352 for (j = this.items.length - 1; j >= 0; j--) {
4353 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
4354 continue;
4355 }
4356 if(this.items[j].item[0] === this.currentItem[0]) {
4357 continue;
4358 }
4359 if (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) {
4360 continue;
4361 }
4362 cur = this.items[j].item.offset()[posProperty];
4363 nearBottom = false;
4364 if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){
4365 nearBottom = true;
4366 cur += this.items[j][sizeProperty];
4367 }
4368
4369 if(Math.abs(cur - base) < dist) {
4370 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
4371 this.direction = nearBottom ? "up": "down";
4372 }
4373 }
4374
4375 //Check if dropOnEmpty is enabled
4376 if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
4377 return;
4378 }
4379
4380 if(this.currentContainer === this.containers[innermostIndex]) {
4381 return;
4382 }
4383
4384 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
4385 this._trigger("change", event, this._uiHash());
4386 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
4387 this.currentContainer = this.containers[innermostIndex];
4388
4389 //Update the placeholder
4390 this.options.placeholder.update(this.currentContainer, this.placeholder);
4391
4392 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
4393 this.containers[innermostIndex].containerCache.over = 1;
4394 }
4395
4396
4397 },
4398
4399 _createHelper: function(event) {
4400
4401 var o = this.options,
4402 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);
4403
4404 //Add the helper to the DOM if that didn't happen already
4405 if(!helper.parents("body").length) {
4406 $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
4407 }
4408
4409 if(helper[0] === this.currentItem[0]) {
4410 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") };
4411 }
4412
4413 if(!helper[0].style.width || o.forceHelperSize) {
4414 helper.width(this.currentItem.width());
4415 }
4416 if(!helper[0].style.height || o.forceHelperSize) {
4417 helper.height(this.currentItem.height());
4418 }
4419
4420 return helper;
4421
4422 },
4423
4424 _adjustOffsetFromHelper: function(obj) {
4425 if (typeof obj === "string") {
4426 obj = obj.split(" ");
4427 }
4428 if ($.isArray(obj)) {
4429 obj = {left: +obj[0], top: +obj[1] || 0};
4430 }
4431 if ("left" in obj) {
4432 this.offset.click.left = obj.left + this.margins.left;
4433 }
4434 if ("right" in obj) {
4435 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
4436 }
4437 if ("top" in obj) {
4438 this.offset.click.top = obj.top + this.margins.top;
4439 }
4440 if ("bottom" in obj) {
4441 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
4442 }
4443 },
4444
4445 _getParentOffset: function() {
4446
4447
4448 //Get the offsetParent and cache its position
4449 this.offsetParent = this.helper.offsetParent();
4450 var po = this.offsetParent.offset();
4451
4452 // This is a special case where we need to modify a offset calculated on start, since the following happened:
4453 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
4454 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
4455 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
4456 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
4457 po.left += this.scrollParent.scrollLeft();
4458 po.top += this.scrollParent.scrollTop();
4459 }
4460
4461 // This needs to be actually done for all browsers, since pageX/pageY includes this information
4462 // with an ugly IE fix
4463 if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
4464 po = { top: 0, left: 0 };
4465 }
4466
4467 return {
4468 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
4469 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
4470 };
4471
4472 },
4473
4474 _getRelativeOffset: function() {
4475
4476 if(this.cssPosition === "relative") {
4477 var p = this.currentItem.position();
4478 return {
4479 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
4480 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
4481 };
4482 } else {
4483 return { top: 0, left: 0 };
4484 }
4485
4486 },
4487
4488 _cacheMargins: function() {
4489 this.margins = {
4490 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
4491 top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
4492 };
4493 },
4494
4495 _cacheHelperProportions: function() {
4496 this.helperProportions = {
4497 width: this.helper.outerWidth(),
4498 height: this.helper.outerHeight()
4499 };
4500 },
4501
4502 _setContainment: function() {
4503
4504 var ce, co, over,
4505 o = this.options;
4506 if(o.containment === "parent") {
4507 o.containment = this.helper[0].parentNode;
4508 }
4509 if(o.containment === "document" || o.containment === "window") {
4510 this.containment = [
4511 0 - this.offset.relative.left - this.offset.parent.left,
4512 0 - this.offset.relative.top - this.offset.parent.top,
4513 $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left,
4514 ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
4515 ];
4516 }
4517
4518 if(!(/^(document|window|parent)$/).test(o.containment)) {
4519 ce = $(o.containment)[0];
4520 co = $(o.containment).offset();
4521 over = ($(ce).css("overflow") !== "hidden");
4522
4523 this.containment = [
4524 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
4525 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
4526 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,
4527 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
4528 ];
4529 }
4530
4531 },
4532
4533 _convertPositionTo: function(d, pos) {
4534
4535 if(!pos) {
4536 pos = this.position;
4537 }
4538 var mod = d === "absolute" ? 1 : -1,
4539 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
4540 scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
4541
4542 return {
4543 top: (
4544 pos.top + // The absolute mouse position
4545 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
4546 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
4547 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
4548 ),
4549 left: (
4550 pos.left + // The absolute mouse position
4551 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
4552 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
4553 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
4554 )
4555 };
4556
4557 },
4558
4559 _generatePosition: function(event) {
4560
4561 var top, left,
4562 o = this.options,
4563 pageX = event.pageX,
4564 pageY = event.pageY,
4565 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);
4566
4567 // This is another very weird special case that only happens for relative elements:
4568 // 1. If the css position is relative
4569 // 2. and the scroll parent is the document or similar to the offset parent
4570 // we have to refresh the relative offset during the scroll so there are no jumps
4571 if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) {
4572 this.offset.relative = this._getRelativeOffset();
4573 }
4574
4575 /*
4576 * - Position constraining -
4577 * Constrain the position to a mix of grid, containment.
4578 */
4579
4580 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
4581
4582 if(this.containment) {
4583 if(event.pageX - this.offset.click.left < this.containment[0]) {
4584 pageX = this.containment[0] + this.offset.click.left;
4585 }
4586 if(event.pageY - this.offset.click.top < this.containment[1]) {
4587 pageY = this.containment[1] + this.offset.click.top;
4588 }
4589 if(event.pageX - this.offset.click.left > this.containment[2]) {
4590 pageX = this.containment[2] + this.offset.click.left;
4591 }
4592 if(event.pageY - this.offset.click.top > this.containment[3]) {
4593 pageY = this.containment[3] + this.offset.click.top;
4594 }
4595 }
4596
4597 if(o.grid) {
4598 top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
4599 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;
4600
4601 left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
4602 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;
4603 }
4604
4605 }
4606
4607 return {
4608 top: (
4609 pageY - // The absolute mouse position
4610 this.offset.click.top - // Click offset (relative to the element)
4611 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
4612 this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
4613 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
4614 ),
4615 left: (
4616 pageX - // The absolute mouse position
4617 this.offset.click.left - // Click offset (relative to the element)
4618 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
4619 this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
4620 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
4621 )
4622 };
4623
4624 },
4625
4626 _rearrange: function(event, i, a, hardRefresh) {
4627
4628 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));
4629
4630 //Various things done here to improve the performance:
4631 // 1. we create a setTimeout, that calls refreshPositions
4632 // 2. on the instance, we have a counter variable, that get's higher after every append
4633 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
4634 // 4. this lets only the last addition to the timeout stack through
4635 this.counter = this.counter ? ++this.counter : 1;
4636 var counter = this.counter;
4637
4638 this._delay(function() {
4639 if(counter === this.counter) {
4640 this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
4641 }
4642 });
4643
4644 },
4645
4646 _clear: function(event, noPropagation) {
4647
4648 this.reverting = false;
4649 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
4650 // everything else normalized again
4651 var i,
4652 delayedTriggers = [];
4653
4654 // We first have to update the dom position of the actual currentItem
4655 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
4656 if(!this._noFinalSort && this.currentItem.parent().length) {
4657 this.placeholder.before(this.currentItem);
4658 }
4659 this._noFinalSort = null;
4660
4661 if(this.helper[0] === this.currentItem[0]) {
4662 for(i in this._storedCSS) {
4663 if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
4664 this._storedCSS[i] = "";
4665 }
4666 }
4667 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
4668 } else {
4669 this.currentItem.show();
4670 }
4671
4672 if(this.fromOutside && !noPropagation) {
4673 delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
4674 }
4675 if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
4676 delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
4677 }
4678
4679 // Check if the items Container has Changed and trigger appropriate
4680 // events.
4681 if (this !== this.currentContainer) {
4682 if(!noPropagation) {
4683 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
4684 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
4685 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
4686 }
4687 }
4688
4689
4690 //Post events to containers
4691 for (i = this.containers.length - 1; i >= 0; i--){
4692 if(!noPropagation) {
4693 delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4694 }
4695 if(this.containers[i].containerCache.over) {
4696 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4697 this.containers[i].containerCache.over = 0;
4698 }
4699 }
4700
4701 //Do what was originally in plugins
4702 if ( this.storedCursor ) {
4703 this.document.find( "body" ).css( "cursor", this.storedCursor );
4704 this.storedStylesheet.remove();
4705 }
4706 if(this._storedOpacity) {
4707 this.helper.css("opacity", this._storedOpacity);
4708 }
4709 if(this._storedZIndex) {
4710 this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
4711 }
4712
4713 this.dragging = false;
4714 if(this.cancelHelperRemoval) {
4715 if(!noPropagation) {
4716 this._trigger("beforeStop", event, this._uiHash());
4717 for (i=0; i < delayedTriggers.length; i++) {
4718 delayedTriggers[i].call(this, event);
4719 } //Trigger all delayed events
4720 this._trigger("stop", event, this._uiHash());
4721 }
4722
4723 this.fromOutside = false;
4724 return false;
4725 }
4726
4727 if(!noPropagation) {
4728 this._trigger("beforeStop", event, this._uiHash());
4729 }
4730
4731 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
4732 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
4733
4734 if(this.helper[0] !== this.currentItem[0]) {
4735 this.helper.remove();
4736 }
4737 this.helper = null;
4738
4739 if(!noPropagation) {
4740 for (i=0; i < delayedTriggers.length; i++) {
4741 delayedTriggers[i].call(this, event);
4742 } //Trigger all delayed events
4743 this._trigger("stop", event, this._uiHash());
4744 }
4745
4746 this.fromOutside = false;
4747 return true;
4748
4749 },
4750
4751 _trigger: function() {
4752 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
4753 this.cancel();
4754 }
4755 },
4756
4757 _uiHash: function(_inst) {
4758 var inst = _inst || this;
4759 return {
4760 helper: inst.helper,
4761 placeholder: inst.placeholder || $([]),
4762 position: inst.position,
4763 originalPosition: inst.originalPosition,
4764 offset: inst.positionAbs,
4765 item: inst.currentItem,
4766 sender: _inst ? _inst.element : null
4767 };
4768 }
4769
4770});
4771
4772})(jQuery);
4773
4774(function($, undefined) {
4775
4776var dataSpace = "ui-effects-";
4777
4778$.effects = {
4779 effect: {}
4780};
4781
4782/*!
4783 * jQuery Color Animations v2.1.2
4784 * https://github.com/jquery/jquery-color
4785 *
4786 * Copyright 2013 jQuery Foundation and other contributors
4787 * Released under the MIT license.
4788 * http://jquery.org/license
4789 *
4790 * Date: Wed Jan 16 08:47:09 2013 -0600
4791 */
4792(function( jQuery, undefined ) {
4793
4794 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
4795
4796 // plusequals test for += 100 -= 100
4797 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
4798 // a set of RE's that can match strings and generate color tuples.
4799 stringParsers = [{
4800 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
4801 parse: function( execResult ) {
4802 return [
4803 execResult[ 1 ],
4804 execResult[ 2 ],
4805 execResult[ 3 ],
4806 execResult[ 4 ]
4807 ];
4808 }
4809 }, {
4810 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
4811 parse: function( execResult ) {
4812 return [
4813 execResult[ 1 ] * 2.55,
4814 execResult[ 2 ] * 2.55,
4815 execResult[ 3 ] * 2.55,
4816 execResult[ 4 ]
4817 ];
4818 }
4819 }, {
4820 // this regex ignores A-F because it's compared against an already lowercased string
4821 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
4822 parse: function( execResult ) {
4823 return [
4824 parseInt( execResult[ 1 ], 16 ),
4825 parseInt( execResult[ 2 ], 16 ),
4826 parseInt( execResult[ 3 ], 16 )
4827 ];
4828 }
4829 }, {
4830 // this regex ignores A-F because it's compared against an already lowercased string
4831 re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
4832 parse: function( execResult ) {
4833 return [
4834 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
4835 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
4836 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
4837 ];
4838 }
4839 }, {
4840 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
4841 space: "hsla",
4842 parse: function( execResult ) {
4843 return [
4844 execResult[ 1 ],
4845 execResult[ 2 ] / 100,
4846 execResult[ 3 ] / 100,
4847 execResult[ 4 ]
4848 ];
4849 }
4850 }],
4851
4852 // jQuery.Color( )
4853 color = jQuery.Color = function( color, green, blue, alpha ) {
4854 return new jQuery.Color.fn.parse( color, green, blue, alpha );
4855 },
4856 spaces = {
4857 rgba: {
4858 props: {
4859 red: {
4860 idx: 0,
4861 type: "byte"
4862 },
4863 green: {
4864 idx: 1,
4865 type: "byte"
4866 },
4867 blue: {
4868 idx: 2,
4869 type: "byte"
4870 }
4871 }
4872 },
4873
4874 hsla: {
4875 props: {
4876 hue: {
4877 idx: 0,
4878 type: "degrees"
4879 },
4880 saturation: {
4881 idx: 1,
4882 type: "percent"
4883 },
4884 lightness: {
4885 idx: 2,
4886 type: "percent"
4887 }
4888 }
4889 }
4890 },
4891 propTypes = {
4892 "byte": {
4893 floor: true,
4894 max: 255
4895 },
4896 "percent": {
4897 max: 1
4898 },
4899 "degrees": {
4900 mod: 360,
4901 floor: true
4902 }
4903 },
4904 support = color.support = {},
4905
4906 // element for support tests
4907 supportElem = jQuery( "<p>" )[ 0 ],
4908
4909 // colors = jQuery.Color.names
4910 colors,
4911
4912 // local aliases of functions called often
4913 each = jQuery.each;
4914
4915// determine rgba support immediately
4916supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
4917support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
4918
4919// define cache name and alpha properties
4920// for rgba and hsla spaces
4921each( spaces, function( spaceName, space ) {
4922 space.cache = "_" + spaceName;
4923 space.props.alpha = {
4924 idx: 3,
4925 type: "percent",
4926 def: 1
4927 };
4928});
4929
4930function clamp( value, prop, allowEmpty ) {
4931 var type = propTypes[ prop.type ] || {};
4932
4933 if ( value == null ) {
4934 return (allowEmpty || !prop.def) ? null : prop.def;
4935 }
4936
4937 // ~~ is an short way of doing floor for positive numbers
4938 value = type.floor ? ~~value : parseFloat( value );
4939
4940 // IE will pass in empty strings as value for alpha,
4941 // which will hit this case
4942 if ( isNaN( value ) ) {
4943 return prop.def;
4944 }
4945
4946 if ( type.mod ) {
4947 // we add mod before modding to make sure that negatives values
4948 // get converted properly: -10 -> 350
4949 return (value + type.mod) % type.mod;
4950 }
4951
4952 // for now all property types without mod have min and max
4953 return 0 > value ? 0 : type.max < value ? type.max : value;
4954}
4955
4956function stringParse( string ) {
4957 var inst = color(),
4958 rgba = inst._rgba = [];
4959
4960 string = string.toLowerCase();
4961
4962 each( stringParsers, function( i, parser ) {
4963 var parsed,
4964 match = parser.re.exec( string ),
4965 values = match && parser.parse( match ),
4966 spaceName = parser.space || "rgba";
4967
4968 if ( values ) {
4969 parsed = inst[ spaceName ]( values );
4970
4971 // if this was an rgba parse the assignment might happen twice
4972 // oh well....
4973 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
4974 rgba = inst._rgba = parsed._rgba;
4975
4976 // exit each( stringParsers ) here because we matched
4977 return false;
4978 }
4979 });
4980
4981 // Found a stringParser that handled it
4982 if ( rgba.length ) {
4983
4984 // if this came from a parsed string, force "transparent" when alpha is 0
4985 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
4986 if ( rgba.join() === "0,0,0,0" ) {
4987 jQuery.extend( rgba, colors.transparent );
4988 }
4989 return inst;
4990 }
4991
4992 // named colors
4993 return colors[ string ];
4994}
4995
4996color.fn = jQuery.extend( color.prototype, {
4997 parse: function( red, green, blue, alpha ) {
4998 if ( red === undefined ) {
4999 this._rgba = [ null, null, null, null ];
5000 return this;
5001 }
5002 if ( red.jquery || red.nodeType ) {
5003 red = jQuery( red ).css( green );
5004 green = undefined;
5005 }
5006
5007 var inst = this,
5008 type = jQuery.type( red ),
5009 rgba = this._rgba = [];
5010
5011 // more than 1 argument specified - assume ( red, green, blue, alpha )
5012 if ( green !== undefined ) {
5013 red = [ red, green, blue, alpha ];
5014 type = "array";
5015 }
5016
5017 if ( type === "string" ) {
5018 return this.parse( stringParse( red ) || colors._default );
5019 }
5020
5021 if ( type === "array" ) {
5022 each( spaces.rgba.props, function( key, prop ) {
5023 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
5024 });
5025 return this;
5026 }
5027
5028 if ( type === "object" ) {
5029 if ( red instanceof color ) {
5030 each( spaces, function( spaceName, space ) {
5031 if ( red[ space.cache ] ) {
5032 inst[ space.cache ] = red[ space.cache ].slice();
5033 }
5034 });
5035 } else {
5036 each( spaces, function( spaceName, space ) {
5037 var cache = space.cache;
5038 each( space.props, function( key, prop ) {
5039
5040 // if the cache doesn't exist, and we know how to convert
5041 if ( !inst[ cache ] && space.to ) {
5042
5043 // if the value was null, we don't need to copy it
5044 // if the key was alpha, we don't need to copy it either
5045 if ( key === "alpha" || red[ key ] == null ) {
5046 return;
5047 }
5048 inst[ cache ] = space.to( inst._rgba );
5049 }
5050
5051 // this is the only case where we allow nulls for ALL properties.
5052 // call clamp with alwaysAllowEmpty
5053 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
5054 });
5055
5056 // everything defined but alpha?
5057 if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
5058 // use the default of 1
5059 inst[ cache ][ 3 ] = 1;
5060 if ( space.from ) {
5061 inst._rgba = space.from( inst[ cache ] );
5062 }
5063 }
5064 });
5065 }
5066 return this;
5067 }
5068 },
5069 is: function( compare ) {
5070 var is = color( compare ),
5071 same = true,
5072 inst = this;
5073
5074 each( spaces, function( _, space ) {
5075 var localCache,
5076 isCache = is[ space.cache ];
5077 if (isCache) {
5078 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
5079 each( space.props, function( _, prop ) {
5080 if ( isCache[ prop.idx ] != null ) {
5081 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
5082 return same;
5083 }
5084 });
5085 }
5086 return same;
5087 });
5088 return same;
5089 },
5090 _space: function() {
5091 var used = [],
5092 inst = this;
5093 each( spaces, function( spaceName, space ) {
5094 if ( inst[ space.cache ] ) {
5095 used.push( spaceName );
5096 }
5097 });
5098 return used.pop();
5099 },
5100 transition: function( other, distance ) {
5101 var end = color( other ),
5102 spaceName = end._space(),
5103 space = spaces[ spaceName ],
5104 startColor = this.alpha() === 0 ? color( "transparent" ) : this,
5105 start = startColor[ space.cache ] || space.to( startColor._rgba ),
5106 result = start.slice();
5107
5108 end = end[ space.cache ];
5109 each( space.props, function( key, prop ) {
5110 var index = prop.idx,
5111 startValue = start[ index ],
5112 endValue = end[ index ],
5113 type = propTypes[ prop.type ] || {};
5114
5115 // if null, don't override start value
5116 if ( endValue === null ) {
5117 return;
5118 }
5119 // if null - use end
5120 if ( startValue === null ) {
5121 result[ index ] = endValue;
5122 } else {
5123 if ( type.mod ) {
5124 if ( endValue - startValue > type.mod / 2 ) {
5125 startValue += type.mod;
5126 } else if ( startValue - endValue > type.mod / 2 ) {
5127 startValue -= type.mod;
5128 }
5129 }
5130 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
5131 }
5132 });
5133 return this[ spaceName ]( result );
5134 },
5135 blend: function( opaque ) {
5136 // if we are already opaque - return ourself
5137 if ( this._rgba[ 3 ] === 1 ) {
5138 return this;
5139 }
5140
5141 var rgb = this._rgba.slice(),
5142 a = rgb.pop(),
5143 blend = color( opaque )._rgba;
5144
5145 return color( jQuery.map( rgb, function( v, i ) {
5146 return ( 1 - a ) * blend[ i ] + a * v;
5147 }));
5148 },
5149 toRgbaString: function() {
5150 var prefix = "rgba(",
5151 rgba = jQuery.map( this._rgba, function( v, i ) {
5152 return v == null ? ( i > 2 ? 1 : 0 ) : v;
5153 });
5154
5155 if ( rgba[ 3 ] === 1 ) {
5156 rgba.pop();
5157 prefix = "rgb(";
5158 }
5159
5160 return prefix + rgba.join() + ")";
5161 },
5162 toHslaString: function() {
5163 var prefix = "hsla(",
5164 hsla = jQuery.map( this.hsla(), function( v, i ) {
5165 if ( v == null ) {
5166 v = i > 2 ? 1 : 0;
5167 }
5168
5169 // catch 1 and 2
5170 if ( i && i < 3 ) {
5171 v = Math.round( v * 100 ) + "%";
5172 }
5173 return v;
5174 });
5175
5176 if ( hsla[ 3 ] === 1 ) {
5177 hsla.pop();
5178 prefix = "hsl(";
5179 }
5180 return prefix + hsla.join() + ")";
5181 },
5182 toHexString: function( includeAlpha ) {
5183 var rgba = this._rgba.slice(),
5184 alpha = rgba.pop();
5185
5186 if ( includeAlpha ) {
5187 rgba.push( ~~( alpha * 255 ) );
5188 }
5189
5190 return "#" + jQuery.map( rgba, function( v ) {
5191
5192 // default to 0 when nulls exist
5193 v = ( v || 0 ).toString( 16 );
5194 return v.length === 1 ? "0" + v : v;
5195 }).join("");
5196 },
5197 toString: function() {
5198 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
5199 }
5200});
5201color.fn.parse.prototype = color.fn;
5202
5203// hsla conversions adapted from:
5204// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
5205
5206function hue2rgb( p, q, h ) {
5207 h = ( h + 1 ) % 1;
5208 if ( h * 6 < 1 ) {
5209 return p + (q - p) * h * 6;
5210 }
5211 if ( h * 2 < 1) {
5212 return q;
5213 }
5214 if ( h * 3 < 2 ) {
5215 return p + (q - p) * ((2/3) - h) * 6;
5216 }
5217 return p;
5218}
5219
5220spaces.hsla.to = function ( rgba ) {
5221 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
5222 return [ null, null, null, rgba[ 3 ] ];
5223 }
5224 var r = rgba[ 0 ] / 255,
5225 g = rgba[ 1 ] / 255,
5226 b = rgba[ 2 ] / 255,
5227 a = rgba[ 3 ],
5228 max = Math.max( r, g, b ),
5229 min = Math.min( r, g, b ),
5230 diff = max - min,
5231 add = max + min,
5232 l = add * 0.5,
5233 h, s;
5234
5235 if ( min === max ) {
5236 h = 0;
5237 } else if ( r === max ) {
5238 h = ( 60 * ( g - b ) / diff ) + 360;
5239 } else if ( g === max ) {
5240 h = ( 60 * ( b - r ) / diff ) + 120;
5241 } else {
5242 h = ( 60 * ( r - g ) / diff ) + 240;
5243 }
5244
5245 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
5246 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
5247 if ( diff === 0 ) {
5248 s = 0;
5249 } else if ( l <= 0.5 ) {
5250 s = diff / add;
5251 } else {
5252 s = diff / ( 2 - add );
5253 }
5254 return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
5255};
5256
5257spaces.hsla.from = function ( hsla ) {
5258 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
5259 return [ null, null, null, hsla[ 3 ] ];
5260 }
5261 var h = hsla[ 0 ] / 360,
5262 s = hsla[ 1 ],
5263 l = hsla[ 2 ],
5264 a = hsla[ 3 ],
5265 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
5266 p = 2 * l - q;
5267
5268 return [
5269 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
5270 Math.round( hue2rgb( p, q, h ) * 255 ),
5271 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
5272 a
5273 ];
5274};
5275
5276
5277each( spaces, function( spaceName, space ) {
5278 var props = space.props,
5279 cache = space.cache,
5280 to = space.to,
5281 from = space.from;
5282
5283 // makes rgba() and hsla()
5284 color.fn[ spaceName ] = function( value ) {
5285
5286 // generate a cache for this space if it doesn't exist
5287 if ( to && !this[ cache ] ) {
5288 this[ cache ] = to( this._rgba );
5289 }
5290 if ( value === undefined ) {
5291 return this[ cache ].slice();
5292 }
5293
5294 var ret,
5295 type = jQuery.type( value ),
5296 arr = ( type === "array" || type === "object" ) ? value : arguments,
5297 local = this[ cache ].slice();
5298
5299 each( props, function( key, prop ) {
5300 var val = arr[ type === "object" ? key : prop.idx ];
5301 if ( val == null ) {
5302 val = local[ prop.idx ];
5303 }
5304 local[ prop.idx ] = clamp( val, prop );
5305 });
5306
5307 if ( from ) {
5308 ret = color( from( local ) );
5309 ret[ cache ] = local;
5310 return ret;
5311 } else {
5312 return color( local );
5313 }
5314 };
5315
5316 // makes red() green() blue() alpha() hue() saturation() lightness()
5317 each( props, function( key, prop ) {
5318 // alpha is included in more than one space
5319 if ( color.fn[ key ] ) {
5320 return;
5321 }
5322 color.fn[ key ] = function( value ) {
5323 var vtype = jQuery.type( value ),
5324 fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
5325 local = this[ fn ](),
5326 cur = local[ prop.idx ],
5327 match;
5328
5329 if ( vtype === "undefined" ) {
5330 return cur;
5331 }
5332
5333 if ( vtype === "function" ) {
5334 value = value.call( this, cur );
5335 vtype = jQuery.type( value );
5336 }
5337 if ( value == null && prop.empty ) {
5338 return this;
5339 }
5340 if ( vtype === "string" ) {
5341 match = rplusequals.exec( value );
5342 if ( match ) {
5343 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
5344 }
5345 }
5346 local[ prop.idx ] = value;
5347 return this[ fn ]( local );
5348 };
5349 });
5350});
5351
5352// add cssHook and .fx.step function for each named hook.
5353// accept a space separated string of properties
5354color.hook = function( hook ) {
5355 var hooks = hook.split( " " );
5356 each( hooks, function( i, hook ) {
5357 jQuery.cssHooks[ hook ] = {
5358 set: function( elem, value ) {
5359 var parsed, curElem,
5360 backgroundColor = "";
5361
5362 if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
5363 value = color( parsed || value );
5364 if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
5365 curElem = hook === "backgroundColor" ? elem.parentNode : elem;
5366 while (
5367 (backgroundColor === "" || backgroundColor === "transparent") &&
5368 curElem && curElem.style
5369 ) {
5370 try {
5371 backgroundColor = jQuery.css( curElem, "backgroundColor" );
5372 curElem = curElem.parentNode;
5373 } catch ( e ) {
5374 }
5375 }
5376
5377 value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
5378 backgroundColor :
5379 "_default" );
5380 }
5381
5382 value = value.toRgbaString();
5383 }
5384 try {
5385 elem.style[ hook ] = value;
5386 } catch( e ) {
5387 // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
5388 }
5389 }
5390 };
5391 jQuery.fx.step[ hook ] = function( fx ) {
5392 if ( !fx.colorInit ) {
5393 fx.start = color( fx.elem, hook );
5394 fx.end = color( fx.end );
5395 fx.colorInit = true;
5396 }
5397 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
5398 };
5399 });
5400
5401};
5402
5403color.hook( stepHooks );
5404
5405jQuery.cssHooks.borderColor = {
5406 expand: function( value ) {
5407 var expanded = {};
5408
5409 each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
5410 expanded[ "border" + part + "Color" ] = value;
5411 });
5412 return expanded;
5413 }
5414};
5415
5416// Basic color names only.
5417// Usage of any of the other color names requires adding yourself or including
5418// jquery.color.svg-names.js.
5419colors = jQuery.Color.names = {
5420 // 4.1. Basic color keywords
5421 aqua: "#00ffff",
5422 black: "#000000",
5423 blue: "#0000ff",
5424 fuchsia: "#ff00ff",
5425 gray: "#808080",
5426 green: "#008000",
5427 lime: "#00ff00",
5428 maroon: "#800000",
5429 navy: "#000080",
5430 olive: "#808000",
5431 purple: "#800080",
5432 red: "#ff0000",
5433 silver: "#c0c0c0",
5434 teal: "#008080",
5435 white: "#ffffff",
5436 yellow: "#ffff00",
5437
5438 // 4.2.3. "transparent" color keyword
5439 transparent: [ null, null, null, 0 ],
5440
5441 _default: "#ffffff"
5442};
5443
5444})( jQuery );
5445
5446
5447/******************************************************************************/
5448/****************************** CLASS ANIMATIONS ******************************/
5449/******************************************************************************/
5450(function() {
5451
5452var classAnimationActions = [ "add", "remove", "toggle" ],
5453 shorthandStyles = {
5454 border: 1,
5455 borderBottom: 1,
5456 borderColor: 1,
5457 borderLeft: 1,
5458 borderRight: 1,
5459 borderTop: 1,
5460 borderWidth: 1,
5461 margin: 1,
5462 padding: 1
5463 };
5464
5465$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
5466 $.fx.step[ prop ] = function( fx ) {
5467 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
5468 jQuery.style( fx.elem, prop, fx.end );
5469 fx.setAttr = true;
5470 }
5471 };
5472});
5473
5474function getElementStyles( elem ) {
5475 var key, len,
5476 style = elem.ownerDocument.defaultView ?
5477 elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
5478 elem.currentStyle,
5479 styles = {};
5480
5481 if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
5482 len = style.length;
5483 while ( len-- ) {
5484 key = style[ len ];
5485 if ( typeof style[ key ] === "string" ) {
5486 styles[ $.camelCase( key ) ] = style[ key ];
5487 }
5488 }
5489 // support: Opera, IE <9
5490 } else {
5491 for ( key in style ) {
5492 if ( typeof style[ key ] === "string" ) {
5493 styles[ key ] = style[ key ];
5494 }
5495 }
5496 }
5497
5498 return styles;
5499}
5500
5501
5502function styleDifference( oldStyle, newStyle ) {
5503 var diff = {},
5504 name, value;
5505
5506 for ( name in newStyle ) {
5507 value = newStyle[ name ];
5508 if ( oldStyle[ name ] !== value ) {
5509 if ( !shorthandStyles[ name ] ) {
5510 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
5511 diff[ name ] = value;
5512 }
5513 }
5514 }
5515 }
5516
5517 return diff;
5518}
5519
5520// support: jQuery <1.8
5521if ( !$.fn.addBack ) {
5522 $.fn.addBack = function( selector ) {
5523 return this.add( selector == null ?
5524 this.prevObject : this.prevObject.filter( selector )
5525 );
5526 };
5527}
5528
5529$.effects.animateClass = function( value, duration, easing, callback ) {
5530 var o = $.speed( duration, easing, callback );
5531
5532 return this.queue( function() {
5533 var animated = $( this ),
5534 baseClass = animated.attr( "class" ) || "",
5535 applyClassChange,
5536 allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
5537
5538 // map the animated objects to store the original styles.
5539 allAnimations = allAnimations.map(function() {
5540 var el = $( this );
5541 return {
5542 el: el,
5543 start: getElementStyles( this )
5544 };
5545 });
5546
5547 // apply class change
5548 applyClassChange = function() {
5549 $.each( classAnimationActions, function(i, action) {
5550 if ( value[ action ] ) {
5551 animated[ action + "Class" ]( value[ action ] );
5552 }
5553 });
5554 };
5555 applyClassChange();
5556
5557 // map all animated objects again - calculate new styles and diff
5558 allAnimations = allAnimations.map(function() {
5559 this.end = getElementStyles( this.el[ 0 ] );
5560 this.diff = styleDifference( this.start, this.end );
5561 return this;
5562 });
5563
5564 // apply original class
5565 animated.attr( "class", baseClass );
5566
5567 // map all animated objects again - this time collecting a promise
5568 allAnimations = allAnimations.map(function() {
5569 var styleInfo = this,
5570 dfd = $.Deferred(),
5571 opts = $.extend({}, o, {
5572 queue: false,
5573 complete: function() {
5574 dfd.resolve( styleInfo );
5575 }
5576 });
5577
5578 this.el.animate( this.diff, opts );
5579 return dfd.promise();
5580 });
5581
5582 // once all animations have completed:
5583 $.when.apply( $, allAnimations.get() ).done(function() {
5584
5585 // set the final class
5586 applyClassChange();
5587
5588 // for each animated element,
5589 // clear all css properties that were animated
5590 $.each( arguments, function() {
5591 var el = this.el;
5592 $.each( this.diff, function(key) {
5593 el.css( key, "" );
5594 });
5595 });
5596
5597 // this is guarnteed to be there if you use jQuery.speed()
5598 // it also handles dequeuing the next anim...
5599 o.complete.call( animated[ 0 ] );
5600 });
5601 });
5602};
5603
5604$.fn.extend({
5605 addClass: (function( orig ) {
5606 return function( classNames, speed, easing, callback ) {
5607 return speed ?
5608 $.effects.animateClass.call( this,
5609 { add: classNames }, speed, easing, callback ) :
5610 orig.apply( this, arguments );
5611 };
5612 })( $.fn.addClass ),
5613
5614 removeClass: (function( orig ) {
5615 return function( classNames, speed, easing, callback ) {
5616 return arguments.length > 1 ?
5617 $.effects.animateClass.call( this,
5618 { remove: classNames }, speed, easing, callback ) :
5619 orig.apply( this, arguments );
5620 };
5621 })( $.fn.removeClass ),
5622
5623 toggleClass: (function( orig ) {
5624 return function( classNames, force, speed, easing, callback ) {
5625 if ( typeof force === "boolean" || force === undefined ) {
5626 if ( !speed ) {
5627 // without speed parameter
5628 return orig.apply( this, arguments );
5629 } else {
5630 return $.effects.animateClass.call( this,
5631 (force ? { add: classNames } : { remove: classNames }),
5632 speed, easing, callback );
5633 }
5634 } else {
5635 // without force parameter
5636 return $.effects.animateClass.call( this,
5637 { toggle: classNames }, force, speed, easing );
5638 }
5639 };
5640 })( $.fn.toggleClass ),
5641
5642 switchClass: function( remove, add, speed, easing, callback) {
5643 return $.effects.animateClass.call( this, {
5644 add: add,
5645 remove: remove
5646 }, speed, easing, callback );
5647 }
5648});
5649
5650})();
5651
5652/******************************************************************************/
5653/*********************************** EFFECTS **********************************/
5654/******************************************************************************/
5655
5656(function() {
5657
5658$.extend( $.effects, {
5659 version: "1.10.3",
5660
5661 // Saves a set of properties in a data storage
5662 save: function( element, set ) {
5663 for( var i=0; i < set.length; i++ ) {
5664 if ( set[ i ] !== null ) {
5665 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
5666 }
5667 }
5668 },
5669
5670 // Restores a set of previously saved properties from a data storage
5671 restore: function( element, set ) {
5672 var val, i;
5673 for( i=0; i < set.length; i++ ) {
5674 if ( set[ i ] !== null ) {
5675 val = element.data( dataSpace + set[ i ] );
5676 // support: jQuery 1.6.2
5677 // http://bugs.jquery.com/ticket/9917
5678 // jQuery 1.6.2 incorrectly returns undefined for any falsy value.
5679 // We can't differentiate between "" and 0 here, so we just assume
5680 // empty string since it's likely to be a more common value...
5681 if ( val === undefined ) {
5682 val = "";
5683 }
5684 element.css( set[ i ], val );
5685 }
5686 }
5687 },
5688
5689 setMode: function( el, mode ) {
5690 if (mode === "toggle") {
5691 mode = el.is( ":hidden" ) ? "show" : "hide";
5692 }
5693 return mode;
5694 },
5695
5696 // Translates a [top,left] array into a baseline value
5697 // this should be a little more flexible in the future to handle a string & hash
5698 getBaseline: function( origin, original ) {
5699 var y, x;
5700 switch ( origin[ 0 ] ) {
5701 case "top": y = 0; break;
5702 case "middle": y = 0.5; break;
5703 case "bottom": y = 1; break;
5704 default: y = origin[ 0 ] / original.height;
5705 }
5706 switch ( origin[ 1 ] ) {
5707 case "left": x = 0; break;
5708 case "center": x = 0.5; break;
5709 case "right": x = 1; break;
5710 default: x = origin[ 1 ] / original.width;
5711 }
5712 return {
5713 x: x,
5714 y: y
5715 };
5716 },
5717
5718 // Wraps the element around a wrapper that copies position properties
5719 createWrapper: function( element ) {
5720
5721 // if the element is already wrapped, return it
5722 if ( element.parent().is( ".ui-effects-wrapper" )) {
5723 return element.parent();
5724 }
5725
5726 // wrap the element
5727 var props = {
5728 width: element.outerWidth(true),
5729 height: element.outerHeight(true),
5730 "float": element.css( "float" )
5731 },
5732 wrapper = $( "<div></div>" )
5733 .addClass( "ui-effects-wrapper" )
5734 .css({
5735 fontSize: "100%",
5736 background: "transparent",
5737 border: "none",
5738 margin: 0,
5739 padding: 0
5740 }),
5741 // Store the size in case width/height are defined in % - Fixes #5245
5742 size = {
5743 width: element.width(),
5744 height: element.height()
5745 },
5746 active = document.activeElement;
5747
5748 // support: Firefox
5749 // Firefox incorrectly exposes anonymous content
5750 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
5751 try {
5752 active.id;
5753 } catch( e ) {
5754 active = document.body;
5755 }
5756
5757 element.wrap( wrapper );
5758
5759 // Fixes #7595 - Elements lose focus when wrapped.
5760 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
5761 $( active ).focus();
5762 }
5763
5764 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
5765
5766 // transfer positioning properties to the wrapper
5767 if ( element.css( "position" ) === "static" ) {
5768 wrapper.css({ position: "relative" });
5769 element.css({ position: "relative" });
5770 } else {
5771 $.extend( props, {
5772 position: element.css( "position" ),
5773 zIndex: element.css( "z-index" )
5774 });
5775 $.each([ "top", "left", "bottom", "right" ], function(i, pos) {
5776 props[ pos ] = element.css( pos );
5777 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
5778 props[ pos ] = "auto";
5779 }
5780 });
5781 element.css({
5782 position: "relative",
5783 top: 0,
5784 left: 0,
5785 right: "auto",
5786 bottom: "auto"
5787 });
5788 }
5789 element.css(size);
5790
5791 return wrapper.css( props ).show();
5792 },
5793
5794 removeWrapper: function( element ) {
5795 var active = document.activeElement;
5796
5797 if ( element.parent().is( ".ui-effects-wrapper" ) ) {
5798 element.parent().replaceWith( element );
5799
5800 // Fixes #7595 - Elements lose focus when wrapped.
5801 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
5802 $( active ).focus();
5803 }
5804 }
5805
5806
5807 return element;
5808 },
5809
5810 setTransition: function( element, list, factor, value ) {
5811 value = value || {};
5812 $.each( list, function( i, x ) {
5813 var unit = element.cssUnit( x );
5814 if ( unit[ 0 ] > 0 ) {
5815 value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
5816 }
5817 });
5818 return value;
5819 }
5820});
5821
5822// return an effect options object for the given parameters:
5823function _normalizeArguments( effect, options, speed, callback ) {
5824
5825 // allow passing all options as the first parameter
5826 if ( $.isPlainObject( effect ) ) {
5827 options = effect;
5828 effect = effect.effect;
5829 }
5830
5831 // convert to an object
5832 effect = { effect: effect };
5833
5834 // catch (effect, null, ...)
5835 if ( options == null ) {
5836 options = {};
5837 }
5838
5839 // catch (effect, callback)
5840 if ( $.isFunction( options ) ) {
5841 callback = options;
5842 speed = null;
5843 options = {};
5844 }
5845
5846 // catch (effect, speed, ?)
5847 if ( typeof options === "number" || $.fx.speeds[ options ] ) {
5848 callback = speed;
5849 speed = options;
5850 options = {};
5851 }
5852
5853 // catch (effect, options, callback)
5854 if ( $.isFunction( speed ) ) {
5855 callback = speed;
5856 speed = null;
5857 }
5858
5859 // add options to effect
5860 if ( options ) {
5861 $.extend( effect, options );
5862 }
5863
5864 speed = speed || options.duration;
5865 effect.duration = $.fx.off ? 0 :
5866 typeof speed === "number" ? speed :
5867 speed in $.fx.speeds ? $.fx.speeds[ speed ] :
5868 $.fx.speeds._default;
5869
5870 effect.complete = callback || options.complete;
5871
5872 return effect;
5873}
5874
5875function standardAnimationOption( option ) {
5876 // Valid standard speeds (nothing, number, named speed)
5877 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
5878 return true;
5879 }
5880
5881 // Invalid strings - treat as "normal" speed
5882 if ( typeof option === "string" && !$.effects.effect[ option ] ) {
5883 return true;
5884 }
5885
5886 // Complete callback
5887 if ( $.isFunction( option ) ) {
5888 return true;
5889 }
5890
5891 // Options hash (but not naming an effect)
5892 if ( typeof option === "object" && !option.effect ) {
5893 return true;
5894 }
5895
5896 // Didn't match any standard API
5897 return false;
5898}
5899
5900$.fn.extend({
5901 effect: function( /* effect, options, speed, callback */ ) {
5902 var args = _normalizeArguments.apply( this, arguments ),
5903 mode = args.mode,
5904 queue = args.queue,
5905 effectMethod = $.effects.effect[ args.effect ];
5906
5907 if ( $.fx.off || !effectMethod ) {
5908 // delegate to the original method (e.g., .show()) if possible
5909 if ( mode ) {
5910 return this[ mode ]( args.duration, args.complete );
5911 } else {
5912 return this.each( function() {
5913 if ( args.complete ) {
5914 args.complete.call( this );
5915 }
5916 });
5917 }
5918 }
5919
5920 function run( next ) {
5921 var elem = $( this ),
5922 complete = args.complete,
5923 mode = args.mode;
5924
5925 function done() {
5926 if ( $.isFunction( complete ) ) {
5927 complete.call( elem[0] );
5928 }
5929 if ( $.isFunction( next ) ) {
5930 next();
5931 }
5932 }
5933
5934 // If the element already has the correct final state, delegate to
5935 // the core methods so the internal tracking of "olddisplay" works.
5936 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
5937 elem[ mode ]();
5938 done();
5939 } else {
5940 effectMethod.call( elem[0], args, done );
5941 }
5942 }
5943
5944 return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
5945 },
5946
5947 show: (function( orig ) {
5948 return function( option ) {
5949 if ( standardAnimationOption( option ) ) {
5950 return orig.apply( this, arguments );
5951 } else {
5952 var args = _normalizeArguments.apply( this, arguments );
5953 args.mode = "show";
5954 return this.effect.call( this, args );
5955 }
5956 };
5957 })( $.fn.show ),
5958
5959 hide: (function( orig ) {
5960 return function( option ) {
5961 if ( standardAnimationOption( option ) ) {
5962 return orig.apply( this, arguments );
5963 } else {
5964 var args = _normalizeArguments.apply( this, arguments );
5965 args.mode = "hide";
5966 return this.effect.call( this, args );
5967 }
5968 };
5969 })( $.fn.hide ),
5970
5971 toggle: (function( orig ) {
5972 return function( option ) {
5973 if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
5974 return orig.apply( this, arguments );
5975 } else {
5976 var args = _normalizeArguments.apply( this, arguments );
5977 args.mode = "toggle";
5978 return this.effect.call( this, args );
5979 }
5980 };
5981 })( $.fn.toggle ),
5982
5983 // helper functions
5984 cssUnit: function(key) {
5985 var style = this.css( key ),
5986 val = [];
5987
5988 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
5989 if ( style.indexOf( unit ) > 0 ) {
5990 val = [ parseFloat( style ), unit ];
5991 }
5992 });
5993 return val;
5994 }
5995});
5996
5997})();
5998
5999/******************************************************************************/
6000/*********************************** EASING ***********************************/
6001/******************************************************************************/
6002
6003(function() {
6004
6005// based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
6006
6007var baseEasings = {};
6008
6009$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
6010 baseEasings[ name ] = function( p ) {
6011 return Math.pow( p, i + 2 );
6012 };
6013});
6014
6015$.extend( baseEasings, {
6016 Sine: function ( p ) {
6017 return 1 - Math.cos( p * Math.PI / 2 );
6018 },
6019 Circ: function ( p ) {
6020 return 1 - Math.sqrt( 1 - p * p );
6021 },
6022 Elastic: function( p ) {
6023 return p === 0 || p === 1 ? p :
6024 -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
6025 },
6026 Back: function( p ) {
6027 return p * p * ( 3 * p - 2 );
6028 },
6029 Bounce: function ( p ) {
6030 var pow2,
6031 bounce = 4;
6032
6033 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
6034 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
6035 }
6036});
6037
6038$.each( baseEasings, function( name, easeIn ) {
6039 $.easing[ "easeIn" + name ] = easeIn;
6040 $.easing[ "easeOut" + name ] = function( p ) {
6041 return 1 - easeIn( 1 - p );
6042 };
6043 $.easing[ "easeInOut" + name ] = function( p ) {
6044 return p < 0.5 ?
6045 easeIn( p * 2 ) / 2 :
6046 1 - easeIn( p * -2 + 2 ) / 2;
6047 };
6048});
6049
6050})();
6051
6052})(jQuery);
6053
6054(function( $, undefined ) {
6055
6056var uid = 0,
6057 hideProps = {},
6058 showProps = {};
6059
6060hideProps.height = hideProps.paddingTop = hideProps.paddingBottom =
6061 hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide";
6062showProps.height = showProps.paddingTop = showProps.paddingBottom =
6063 showProps.borderTopWidth = showProps.borderBottomWidth = "show";
6064
6065$.widget( "ui.accordion", {
6066 version: "1.10.3",
6067 options: {
6068 active: 0,
6069 animate: {},
6070 collapsible: false,
6071 event: "click",
6072 header: "> li > :first-child,> :not(li):even",
6073 heightStyle: "auto",
6074 icons: {
6075 activeHeader: "ui-icon-triangle-1-s",
6076 header: "ui-icon-triangle-1-e"
6077 },
6078
6079 // callbacks
6080 activate: null,
6081 beforeActivate: null
6082 },
6083
6084 _create: function() {
6085 var options = this.options;
6086 this.prevShow = this.prevHide = $();
6087 this.element.addClass( "ui-accordion ui-widget ui-helper-reset" )
6088 // ARIA
6089 .attr( "role", "tablist" );
6090
6091 // don't allow collapsible: false and active: false / null
6092 if ( !options.collapsible && (options.active === false || options.active == null) ) {
6093 options.active = 0;
6094 }
6095
6096 this._processPanels();
6097 // handle negative values
6098 if ( options.active < 0 ) {
6099 options.active += this.headers.length;
6100 }
6101 this._refresh();
6102 },
6103
6104 _getCreateEventData: function() {
6105 return {
6106 header: this.active,
6107 panel: !this.active.length ? $() : this.active.next(),
6108 content: !this.active.length ? $() : this.active.next()
6109 };
6110 },
6111
6112 _createIcons: function() {
6113 var icons = this.options.icons;
6114 if ( icons ) {
6115 $( "<span>" )
6116 .addClass( "ui-accordion-header-icon ui-icon " + icons.header )
6117 .prependTo( this.headers );
6118 this.active.children( ".ui-accordion-header-icon" )
6119 .removeClass( icons.header )
6120 .addClass( icons.activeHeader );
6121 this.headers.addClass( "ui-accordion-icons" );
6122 }
6123 },
6124
6125 _destroyIcons: function() {
6126 this.headers
6127 .removeClass( "ui-accordion-icons" )
6128 .children( ".ui-accordion-header-icon" )
6129 .remove();
6130 },
6131
6132 _destroy: function() {
6133 var contents;
6134
6135 // clean up main element
6136 this.element
6137 .removeClass( "ui-accordion ui-widget ui-helper-reset" )
6138 .removeAttr( "role" );
6139
6140 // clean up headers
6141 this.headers
6142 .removeClass( "ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
6143 .removeAttr( "role" )
6144 .removeAttr( "aria-selected" )
6145 .removeAttr( "aria-controls" )
6146 .removeAttr( "tabIndex" )
6147 .each(function() {
6148 if ( /^ui-accordion/.test( this.id ) ) {
6149 this.removeAttribute( "id" );
6150 }
6151 });
6152 this._destroyIcons();
6153
6154 // clean up content panels
6155 contents = this.headers.next()
6156 .css( "display", "" )
6157 .removeAttr( "role" )
6158 .removeAttr( "aria-expanded" )
6159 .removeAttr( "aria-hidden" )
6160 .removeAttr( "aria-labelledby" )
6161 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" )
6162 .each(function() {
6163 if ( /^ui-accordion/.test( this.id ) ) {
6164 this.removeAttribute( "id" );
6165 }
6166 });
6167 if ( this.options.heightStyle !== "content" ) {
6168 contents.css( "height", "" );
6169 }
6170 },
6171
6172 _setOption: function( key, value ) {
6173 if ( key === "active" ) {
6174 // _activate() will handle invalid values and update this.options
6175 this._activate( value );
6176 return;
6177 }
6178
6179 if ( key === "event" ) {
6180 if ( this.options.event ) {
6181 this._off( this.headers, this.options.event );
6182 }
6183 this._setupEvents( value );
6184 }
6185
6186 this._super( key, value );
6187
6188 // setting collapsible: false while collapsed; open first panel
6189 if ( key === "collapsible" && !value && this.options.active === false ) {
6190 this._activate( 0 );
6191 }
6192
6193 if ( key === "icons" ) {
6194 this._destroyIcons();
6195 if ( value ) {
6196 this._createIcons();
6197 }
6198 }
6199
6200 // #5332 - opacity doesn't cascade to positioned elements in IE
6201 // so we need to add the disabled class to the headers and panels
6202 if ( key === "disabled" ) {
6203 this.headers.add( this.headers.next() )
6204 .toggleClass( "ui-state-disabled", !!value );
6205 }
6206 },
6207
6208 _keydown: function( event ) {
6209 /*jshint maxcomplexity:15*/
6210 if ( event.altKey || event.ctrlKey ) {
6211 return;
6212 }
6213
6214 var keyCode = $.ui.keyCode,
6215 length = this.headers.length,
6216 currentIndex = this.headers.index( event.target ),
6217 toFocus = false;
6218
6219 switch ( event.keyCode ) {
6220 case keyCode.RIGHT:
6221 case keyCode.DOWN:
6222 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
6223 break;
6224 case keyCode.LEFT:
6225 case keyCode.UP:
6226 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
6227 break;
6228 case keyCode.SPACE:
6229 case keyCode.ENTER:
6230 this._eventHandler( event );
6231 break;
6232 case keyCode.HOME:
6233 toFocus = this.headers[ 0 ];
6234 break;
6235 case keyCode.END:
6236 toFocus = this.headers[ length - 1 ];
6237 break;
6238 }
6239
6240 if ( toFocus ) {
6241 $( event.target ).attr( "tabIndex", -1 );
6242 $( toFocus ).attr( "tabIndex", 0 );
6243 toFocus.focus();
6244 event.preventDefault();
6245 }
6246 },
6247
6248 _panelKeyDown : function( event ) {
6249 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
6250 $( event.currentTarget ).prev().focus();
6251 }
6252 },
6253
6254 refresh: function() {
6255 var options = this.options;
6256 this._processPanels();
6257
6258 // was collapsed or no panel
6259 if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {
6260 options.active = false;
6261 this.active = $();
6262 // active false only when collapsible is true
6263 } else if ( options.active === false ) {
6264 this._activate( 0 );
6265 // was active, but active panel is gone
6266 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
6267 // all remaining panel are disabled
6268 if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {
6269 options.active = false;
6270 this.active = $();
6271 // activate previous panel
6272 } else {
6273 this._activate( Math.max( 0, options.active - 1 ) );
6274 }
6275 // was active, active panel still exists
6276 } else {
6277 // make sure active index is correct
6278 options.active = this.headers.index( this.active );
6279 }
6280
6281 this._destroyIcons();
6282
6283 this._refresh();
6284 },
6285
6286 _processPanels: function() {
6287 this.headers = this.element.find( this.options.header )
6288 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" );
6289
6290 this.headers.next()
6291 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
6292 .filter(":not(.ui-accordion-content-active)")
6293 .hide();
6294 },
6295
6296 _refresh: function() {
6297 var maxHeight,
6298 options = this.options,
6299 heightStyle = options.heightStyle,
6300 parent = this.element.parent(),
6301 accordionId = this.accordionId = "ui-accordion-" +
6302 (this.element.attr( "id" ) || ++uid);
6303
6304 this.active = this._findActive( options.active )
6305 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" )
6306 .removeClass( "ui-corner-all" );
6307 this.active.next()
6308 .addClass( "ui-accordion-content-active" )
6309 .show();
6310
6311 this.headers
6312 .attr( "role", "tab" )
6313 .each(function( i ) {
6314 var header = $( this ),
6315 headerId = header.attr( "id" ),
6316 panel = header.next(),
6317 panelId = panel.attr( "id" );
6318 if ( !headerId ) {
6319 headerId = accordionId + "-header-" + i;
6320 header.attr( "id", headerId );
6321 }
6322 if ( !panelId ) {
6323 panelId = accordionId + "-panel-" + i;
6324 panel.attr( "id", panelId );
6325 }
6326 header.attr( "aria-controls", panelId );
6327 panel.attr( "aria-labelledby", headerId );
6328 })
6329 .next()
6330 .attr( "role", "tabpanel" );
6331
6332 this.headers
6333 .not( this.active )
6334 .attr({
6335 "aria-selected": "false",
6336 tabIndex: -1
6337 })
6338 .next()
6339 .attr({
6340 "aria-expanded": "false",
6341 "aria-hidden": "true"
6342 })
6343 .hide();
6344
6345 // make sure at least one header is in the tab order
6346 if ( !this.active.length ) {
6347 this.headers.eq( 0 ).attr( "tabIndex", 0 );
6348 } else {
6349 this.active.attr({
6350 "aria-selected": "true",
6351 tabIndex: 0
6352 })
6353 .next()
6354 .attr({
6355 "aria-expanded": "true",
6356 "aria-hidden": "false"
6357 });
6358 }
6359
6360 this._createIcons();
6361
6362 this._setupEvents( options.event );
6363
6364 if ( heightStyle === "fill" ) {
6365 maxHeight = parent.height();
6366 this.element.siblings( ":visible" ).each(function() {
6367 var elem = $( this ),
6368 position = elem.css( "position" );
6369
6370 if ( position === "absolute" || position === "fixed" ) {
6371 return;
6372 }
6373 maxHeight -= elem.outerHeight( true );
6374 });
6375
6376 this.headers.each(function() {
6377 maxHeight -= $( this ).outerHeight( true );
6378 });
6379
6380 this.headers.next()
6381 .each(function() {
6382 $( this ).height( Math.max( 0, maxHeight -
6383 $( this ).innerHeight() + $( this ).height() ) );
6384 })
6385 .css( "overflow", "auto" );
6386 } else if ( heightStyle === "auto" ) {
6387 maxHeight = 0;
6388 this.headers.next()
6389 .each(function() {
6390 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
6391 })
6392 .height( maxHeight );
6393 }
6394 },
6395
6396 _activate: function( index ) {
6397 var active = this._findActive( index )[ 0 ];
6398
6399 // trying to activate the already active panel
6400 if ( active === this.active[ 0 ] ) {
6401 return;
6402 }
6403
6404 // trying to collapse, simulate a click on the currently active header
6405 active = active || this.active[ 0 ];
6406
6407 this._eventHandler({
6408 target: active,
6409 currentTarget: active,
6410 preventDefault: $.noop
6411 });
6412 },
6413
6414 _findActive: function( selector ) {
6415 return typeof selector === "number" ? this.headers.eq( selector ) : $();
6416 },
6417
6418 _setupEvents: function( event ) {
6419 var events = {
6420 keydown: "_keydown"
6421 };
6422 if ( event ) {
6423 $.each( event.split(" "), function( index, eventName ) {
6424 events[ eventName ] = "_eventHandler";
6425 });
6426 }
6427
6428 this._off( this.headers.add( this.headers.next() ) );
6429 this._on( this.headers, events );
6430 this._on( this.headers.next(), { keydown: "_panelKeyDown" });
6431 this._hoverable( this.headers );
6432 this._focusable( this.headers );
6433 },
6434
6435 _eventHandler: function( event ) {
6436 var options = this.options,
6437 active = this.active,
6438 clicked = $( event.currentTarget ),
6439 clickedIsActive = clicked[ 0 ] === active[ 0 ],
6440 collapsing = clickedIsActive && options.collapsible,
6441 toShow = collapsing ? $() : clicked.next(),
6442 toHide = active.next(),
6443 eventData = {
6444 oldHeader: active,
6445 oldPanel: toHide,
6446 newHeader: collapsing ? $() : clicked,
6447 newPanel: toShow
6448 };
6449
6450 event.preventDefault();
6451
6452 if (
6453 // click on active header, but not collapsible
6454 ( clickedIsActive && !options.collapsible ) ||
6455 // allow canceling activation
6456 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
6457 return;
6458 }
6459
6460 options.active = collapsing ? false : this.headers.index( clicked );
6461
6462 // when the call to ._toggle() comes after the class changes
6463 // it causes a very odd bug in IE 8 (see #6720)
6464 this.active = clickedIsActive ? $() : clicked;
6465 this._toggle( eventData );
6466
6467 // switch classes
6468 // corner classes on the previously active header stay after the animation
6469 active.removeClass( "ui-accordion-header-active ui-state-active" );
6470 if ( options.icons ) {
6471 active.children( ".ui-accordion-header-icon" )
6472 .removeClass( options.icons.activeHeader )
6473 .addClass( options.icons.header );
6474 }
6475
6476 if ( !clickedIsActive ) {
6477 clicked
6478 .removeClass( "ui-corner-all" )
6479 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
6480 if ( options.icons ) {
6481 clicked.children( ".ui-accordion-header-icon" )
6482 .removeClass( options.icons.header )
6483 .addClass( options.icons.activeHeader );
6484 }
6485
6486 clicked
6487 .next()
6488 .addClass( "ui-accordion-content-active" );
6489 }
6490 },
6491
6492 _toggle: function( data ) {
6493 var toShow = data.newPanel,
6494 toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
6495
6496 // handle activating a panel during the animation for another activation
6497 this.prevShow.add( this.prevHide ).stop( true, true );
6498 this.prevShow = toShow;
6499 this.prevHide = toHide;
6500
6501 if ( this.options.animate ) {
6502 this._animate( toShow, toHide, data );
6503 } else {
6504 toHide.hide();
6505 toShow.show();
6506 this._toggleComplete( data );
6507 }
6508
6509 toHide.attr({
6510 "aria-expanded": "false",
6511 "aria-hidden": "true"
6512 });
6513 toHide.prev().attr( "aria-selected", "false" );
6514 // if we're switching panels, remove the old header from the tab order
6515 // if we're opening from collapsed state, remove the previous header from the tab order
6516 // if we're collapsing, then keep the collapsing header in the tab order
6517 if ( toShow.length && toHide.length ) {
6518 toHide.prev().attr( "tabIndex", -1 );
6519 } else if ( toShow.length ) {
6520 this.headers.filter(function() {
6521 return $( this ).attr( "tabIndex" ) === 0;
6522 })
6523 .attr( "tabIndex", -1 );
6524 }
6525
6526 toShow
6527 .attr({
6528 "aria-expanded": "true",
6529 "aria-hidden": "false"
6530 })
6531 .prev()
6532 .attr({
6533 "aria-selected": "true",
6534 tabIndex: 0
6535 });
6536 },
6537
6538 _animate: function( toShow, toHide, data ) {
6539 var total, easing, duration,
6540 that = this,
6541 adjust = 0,
6542 down = toShow.length &&
6543 ( !toHide.length || ( toShow.index() < toHide.index() ) ),
6544 animate = this.options.animate || {},
6545 options = down && animate.down || animate,
6546 complete = function() {
6547 that._toggleComplete( data );
6548 };
6549
6550 if ( typeof options === "number" ) {
6551 duration = options;
6552 }
6553 if ( typeof options === "string" ) {
6554 easing = options;
6555 }
6556 // fall back from options to animation in case of partial down settings
6557 easing = easing || options.easing || animate.easing;
6558 duration = duration || options.duration || animate.duration;
6559
6560 if ( !toHide.length ) {
6561 return toShow.animate( showProps, duration, easing, complete );
6562 }
6563 if ( !toShow.length ) {
6564 return toHide.animate( hideProps, duration, easing, complete );
6565 }
6566
6567 total = toShow.show().outerHeight();
6568 toHide.animate( hideProps, {
6569 duration: duration,
6570 easing: easing,
6571 step: function( now, fx ) {
6572 fx.now = Math.round( now );
6573 }
6574 });
6575 toShow
6576 .hide()
6577 .animate( showProps, {
6578 duration: duration,
6579 easing: easing,
6580 complete: complete,
6581 step: function( now, fx ) {
6582 fx.now = Math.round( now );
6583 if ( fx.prop !== "height" ) {
6584 adjust += fx.now;
6585 } else if ( that.options.heightStyle !== "content" ) {
6586 fx.now = Math.round( total - toHide.outerHeight() - adjust );
6587 adjust = 0;
6588 }
6589 }
6590 });
6591 },
6592
6593 _toggleComplete: function( data ) {
6594 var toHide = data.oldPanel;
6595
6596 toHide
6597 .removeClass( "ui-accordion-content-active" )
6598 .prev()
6599 .removeClass( "ui-corner-top" )
6600 .addClass( "ui-corner-all" );
6601
6602 // Work around for rendering bug in IE (#5421)
6603 if ( toHide.length ) {
6604 toHide.parent()[0].className = toHide.parent()[0].className;
6605 }
6606
6607 this._trigger( "activate", null, data );
6608 }
6609});
6610
6611})( jQuery );
6612
6613(function( $, undefined ) {
6614
6615// used to prevent race conditions with remote data sources
6616var requestIndex = 0;
6617
6618$.widget( "ui.autocomplete", {
6619 version: "1.10.3",
6620 defaultElement: "<input>",
6621 options: {
6622 appendTo: null,
6623 autoFocus: false,
6624 delay: 300,
6625 minLength: 1,
6626 position: {
6627 my: "left top",
6628 at: "left bottom",
6629 collision: "none"
6630 },
6631 source: null,
6632
6633 // callbacks
6634 change: null,
6635 close: null,
6636 focus: null,
6637 open: null,
6638 response: null,
6639 search: null,
6640 select: null
6641 },
6642
6643 pending: 0,
6644
6645 _create: function() {
6646 // Some browsers only repeat keydown events, not keypress events,
6647 // so we use the suppressKeyPress flag to determine if we've already
6648 // handled the keydown event. #7269
6649 // Unfortunately the code for & in keypress is the same as the up arrow,
6650 // so we use the suppressKeyPressRepeat flag to avoid handling keypress
6651 // events when we know the keydown event was used to modify the
6652 // search term. #7799
6653 var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
6654 nodeName = this.element[0].nodeName.toLowerCase(),
6655 isTextarea = nodeName === "textarea",
6656 isInput = nodeName === "input";
6657
6658 this.isMultiLine =
6659 // Textareas are always multi-line
6660 isTextarea ? true :
6661 // Inputs are always single-line, even if inside a contentEditable element
6662 // IE also treats inputs as contentEditable
6663 isInput ? false :
6664 // All other element types are determined by whether or not they're contentEditable
6665 this.element.prop( "isContentEditable" );
6666
6667 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
6668 this.isNewMenu = true;
6669
6670 this.element
6671 .addClass( "ui-autocomplete-input" )
6672 .attr( "autocomplete", "off" );
6673
6674 this._on( this.element, {
6675 keydown: function( event ) {
6676 /*jshint maxcomplexity:15*/
6677 if ( this.element.prop( "readOnly" ) ) {
6678 suppressKeyPress = true;
6679 suppressInput = true;
6680 suppressKeyPressRepeat = true;
6681 return;
6682 }
6683
6684 suppressKeyPress = false;
6685 suppressInput = false;
6686 suppressKeyPressRepeat = false;
6687 var keyCode = $.ui.keyCode;
6688 switch( event.keyCode ) {
6689 case keyCode.PAGE_UP:
6690 suppressKeyPress = true;
6691 this._move( "previousPage", event );
6692 break;
6693 case keyCode.PAGE_DOWN:
6694 suppressKeyPress = true;
6695 this._move( "nextPage", event );
6696 break;
6697 case keyCode.UP:
6698 suppressKeyPress = true;
6699 this._keyEvent( "previous", event );
6700 break;
6701 case keyCode.DOWN:
6702 suppressKeyPress = true;
6703 this._keyEvent( "next", event );
6704 break;
6705 case keyCode.ENTER:
6706 case keyCode.NUMPAD_ENTER:
6707 // when menu is open and has focus
6708 if ( this.menu.active ) {
6709 // #6055 - Opera still allows the keypress to occur
6710 // which causes forms to submit
6711 suppressKeyPress = true;
6712 event.preventDefault();
6713 this.menu.select( event );
6714 }
6715 break;
6716 case keyCode.TAB:
6717 if ( this.menu.active ) {
6718 this.menu.select( event );
6719 }
6720 break;
6721 case keyCode.ESCAPE:
6722 if ( this.menu.element.is( ":visible" ) ) {
6723 this._value( this.term );
6724 this.close( event );
6725 // Different browsers have different default behavior for escape
6726 // Single press can mean undo or clear
6727 // Double press in IE means clear the whole form
6728 event.preventDefault();
6729 }
6730 break;
6731 default:
6732 suppressKeyPressRepeat = true;
6733 // search timeout should be triggered before the input value is changed
6734 this._searchTimeout( event );
6735 break;
6736 }
6737 },
6738 keypress: function( event ) {
6739 if ( suppressKeyPress ) {
6740 suppressKeyPress = false;
6741 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6742 event.preventDefault();
6743 }
6744 return;
6745 }
6746 if ( suppressKeyPressRepeat ) {
6747 return;
6748 }
6749
6750 // replicate some key handlers to allow them to repeat in Firefox and Opera
6751 var keyCode = $.ui.keyCode;
6752 switch( event.keyCode ) {
6753 case keyCode.PAGE_UP:
6754 this._move( "previousPage", event );
6755 break;
6756 case keyCode.PAGE_DOWN:
6757 this._move( "nextPage", event );
6758 break;
6759 case keyCode.UP:
6760 this._keyEvent( "previous", event );
6761 break;
6762 case keyCode.DOWN:
6763 this._keyEvent( "next", event );
6764 break;
6765 }
6766 },
6767 input: function( event ) {
6768 if ( suppressInput ) {
6769 suppressInput = false;
6770 event.preventDefault();
6771 return;
6772 }
6773 this._searchTimeout( event );
6774 },
6775 focus: function() {
6776 this.selectedItem = null;
6777 this.previous = this._value();
6778 },
6779 blur: function( event ) {
6780 if ( this.cancelBlur ) {
6781 delete this.cancelBlur;
6782 return;
6783 }
6784
6785 clearTimeout( this.searching );
6786 this.close( event );
6787 this._change( event );
6788 }
6789 });
6790
6791 this._initSource();
6792 this.menu = $( "<ul>" )
6793 .addClass( "ui-autocomplete ui-front" )
6794 .appendTo( this._appendTo() )
6795 .menu({
6796 // disable ARIA support, the live region takes care of that
6797 role: null
6798 })
6799 .hide()
6800 .data( "ui-menu" );
6801
6802 this._on( this.menu.element, {
6803 mousedown: function( event ) {
6804 // prevent moving focus out of the text field
6805 event.preventDefault();
6806
6807 // IE doesn't prevent moving focus even with event.preventDefault()
6808 // so we set a flag to know when we should ignore the blur event
6809 this.cancelBlur = true;
6810 this._delay(function() {
6811 delete this.cancelBlur;
6812 });
6813
6814 // clicking on the scrollbar causes focus to shift to the body
6815 // but we can't detect a mouseup or a click immediately afterward
6816 // so we have to track the next mousedown and close the menu if
6817 // the user clicks somewhere outside of the autocomplete
6818 var menuElement = this.menu.element[ 0 ];
6819 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
6820 this._delay(function() {
6821 var that = this;
6822 this.document.one( "mousedown", function( event ) {
6823 if ( event.target !== that.element[ 0 ] &&
6824 event.target !== menuElement &&
6825 !$.contains( menuElement, event.target ) ) {
6826 that.close();
6827 }
6828 });
6829 });
6830 }
6831 },
6832 menufocus: function( event, ui ) {
6833 // support: Firefox
6834 // Prevent accidental activation of menu items in Firefox (#7024 #9118)
6835 if ( this.isNewMenu ) {
6836 this.isNewMenu = false;
6837 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
6838 this.menu.blur();
6839
6840 this.document.one( "mousemove", function() {
6841 $( event.target ).trigger( event.originalEvent );
6842 });
6843
6844 return;
6845 }
6846 }
6847
6848 var item = ui.item.data( "ui-autocomplete-item" );
6849 if ( false !== this._trigger( "focus", event, { item: item } ) ) {
6850 // use value to match what will end up in the input, if it was a key event
6851 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
6852 this._value( item.value );
6853 }
6854 } else {
6855 // Normally the input is populated with the item's value as the
6856 // menu is navigated, causing screen readers to notice a change and
6857 // announce the item. Since the focus event was canceled, this doesn't
6858 // happen, so we update the live region so that screen readers can
6859 // still notice the change and announce it.
6860 this.liveRegion.text( item.value );
6861 }
6862 },
6863 menuselect: function( event, ui ) {
6864 var item = ui.item.data( "ui-autocomplete-item" ),
6865 previous = this.previous;
6866
6867 // only trigger when focus was lost (click on menu)
6868 if ( this.element[0] !== this.document[0].activeElement ) {
6869 this.element.focus();
6870 this.previous = previous;
6871 // #6109 - IE triggers two focus events and the second
6872 // is asynchronous, so we need to reset the previous
6873 // term synchronously and asynchronously :-(
6874 this._delay(function() {
6875 this.previous = previous;
6876 this.selectedItem = item;
6877 });
6878 }
6879
6880 if ( false !== this._trigger( "select", event, { item: item } ) ) {
6881 this._value( item.value );
6882 }
6883 // reset the term after the select event
6884 // this allows custom select handling to work properly
6885 this.term = this._value();
6886
6887 this.close( event );
6888 this.selectedItem = item;
6889 }
6890 });
6891
6892 this.liveRegion = $( "<span>", {
6893 role: "status",
6894 "aria-live": "polite"
6895 })
6896 .addClass( "ui-helper-hidden-accessible" )
6897 .insertBefore( this.element );
6898
6899 // turning off autocomplete prevents the browser from remembering the
6900 // value when navigating through history, so we re-enable autocomplete
6901 // if the page is unloaded before the widget is destroyed. #7790
6902 this._on( this.window, {
6903 beforeunload: function() {
6904 this.element.removeAttr( "autocomplete" );
6905 }
6906 });
6907 },
6908
6909 _destroy: function() {
6910 clearTimeout( this.searching );
6911 this.element
6912 .removeClass( "ui-autocomplete-input" )
6913 .removeAttr( "autocomplete" );
6914 this.menu.element.remove();
6915 this.liveRegion.remove();
6916 },
6917
6918 _setOption: function( key, value ) {
6919 this._super( key, value );
6920 if ( key === "source" ) {
6921 this._initSource();
6922 }
6923 if ( key === "appendTo" ) {
6924 this.menu.element.appendTo( this._appendTo() );
6925 }
6926 if ( key === "disabled" && value && this.xhr ) {
6927 this.xhr.abort();
6928 }
6929 },
6930
6931 _appendTo: function() {
6932 var element = this.options.appendTo;
6933
6934 if ( element ) {
6935 element = element.jquery || element.nodeType ?
6936 $( element ) :
6937 this.document.find( element ).eq( 0 );
6938 }
6939
6940 if ( !element ) {
6941 element = this.element.closest( ".ui-front" );
6942 }
6943
6944 if ( !element.length ) {
6945 element = this.document[0].body;
6946 }
6947
6948 return element;
6949 },
6950
6951 _initSource: function() {
6952 var array, url,
6953 that = this;
6954 if ( $.isArray(this.options.source) ) {
6955 array = this.options.source;
6956 this.source = function( request, response ) {
6957 response( $.ui.autocomplete.filter( array, request.term ) );
6958 };
6959 } else if ( typeof this.options.source === "string" ) {
6960 url = this.options.source;
6961 this.source = function( request, response ) {
6962 if ( that.xhr ) {
6963 that.xhr.abort();
6964 }
6965 that.xhr = $.ajax({
6966 url: url,
6967 data: request,
6968 dataType: "json",
6969 success: function( data ) {
6970 response( data );
6971 },
6972 error: function() {
6973 response( [] );
6974 }
6975 });
6976 };
6977 } else {
6978 this.source = this.options.source;
6979 }
6980 },
6981
6982 _searchTimeout: function( event ) {
6983 clearTimeout( this.searching );
6984 this.searching = this._delay(function() {
6985 // only search if the value has changed
6986 if ( this.term !== this._value() ) {
6987 this.selectedItem = null;
6988 this.search( null, event );
6989 }
6990 }, this.options.delay );
6991 },
6992
6993 search: function( value, event ) {
6994 value = value != null ? value : this._value();
6995
6996 // always save the actual value, not the one passed as an argument
6997 this.term = this._value();
6998
6999 if ( value.length < this.options.minLength ) {
7000 return this.close( event );
7001 }
7002
7003 if ( this._trigger( "search", event ) === false ) {
7004 return;
7005 }
7006
7007 return this._search( value );
7008 },
7009
7010 _search: function( value ) {
7011 this.pending++;
7012 this.element.addClass( "ui-autocomplete-loading" );
7013 this.cancelSearch = false;
7014
7015 this.source( { term: value }, this._response() );
7016 },
7017
7018 _response: function() {
7019 var that = this,
7020 index = ++requestIndex;
7021
7022 return function( content ) {
7023 if ( index === requestIndex ) {
7024 that.__response( content );
7025 }
7026
7027 that.pending--;
7028 if ( !that.pending ) {
7029 that.element.removeClass( "ui-autocomplete-loading" );
7030 }
7031 };
7032 },
7033
7034 __response: function( content ) {
7035 if ( content ) {
7036 content = this._normalize( content );
7037 }
7038 this._trigger( "response", null, { content: content } );
7039 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
7040 this._suggest( content );
7041 this._trigger( "open" );
7042 } else {
7043 // use ._close() instead of .close() so we don't cancel future searches
7044 this._close();
7045 }
7046 },
7047
7048 close: function( event ) {
7049 this.cancelSearch = true;
7050 this._close( event );
7051 },
7052
7053 _close: function( event ) {
7054 if ( this.menu.element.is( ":visible" ) ) {
7055 this.menu.element.hide();
7056 this.menu.blur();
7057 this.isNewMenu = true;
7058 this._trigger( "close", event );
7059 }
7060 },
7061
7062 _change: function( event ) {
7063 if ( this.previous !== this._value() ) {
7064 this._trigger( "change", event, { item: this.selectedItem } );
7065 }
7066 },
7067
7068 _normalize: function( items ) {
7069 // assume all items have the right format when the first item is complete
7070 if ( items.length && items[0].label && items[0].value ) {
7071 return items;
7072 }
7073 return $.map( items, function( item ) {
7074 if ( typeof item === "string" ) {
7075 return {
7076 label: item,
7077 value: item
7078 };
7079 }
7080 return $.extend({
7081 label: item.label || item.value,
7082 value: item.value || item.label
7083 }, item );
7084 });
7085 },
7086
7087 _suggest: function( items ) {
7088 var ul = this.menu.element.empty();
7089 this._renderMenu( ul, items );
7090 this.isNewMenu = true;
7091 this.menu.refresh();
7092
7093 // size and position menu
7094 ul.show();
7095 this._resizeMenu();
7096 ul.position( $.extend({
7097 of: this.element
7098 }, this.options.position ));
7099
7100 if ( this.options.autoFocus ) {
7101 this.menu.next();
7102 }
7103 },
7104
7105 _resizeMenu: function() {
7106 var ul = this.menu.element;
7107 ul.outerWidth( Math.max(
7108 // Firefox wraps long text (possibly a rounding bug)
7109 // so we add 1px to avoid the wrapping (#7513)
7110 ul.width( "" ).outerWidth() + 1,
7111 this.element.outerWidth()
7112 ) );
7113 },
7114
7115 _renderMenu: function( ul, items ) {
7116 var that = this;
7117 $.each( items, function( index, item ) {
7118 that._renderItemData( ul, item );
7119 });
7120 },
7121
7122 _renderItemData: function( ul, item ) {
7123 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
7124 },
7125
7126 _renderItem: function( ul, item ) {
7127 return $( "<li>" )
7128 .append( $( "<a>" ).text( item.label ) )
7129 .appendTo( ul );
7130 },
7131
7132 _move: function( direction, event ) {
7133 if ( !this.menu.element.is( ":visible" ) ) {
7134 this.search( null, event );
7135 return;
7136 }
7137 if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
7138 this.menu.isLastItem() && /^next/.test( direction ) ) {
7139 this._value( this.term );
7140 this.menu.blur();
7141 return;
7142 }
7143 this.menu[ direction ]( event );
7144 },
7145
7146 widget: function() {
7147 return this.menu.element;
7148 },
7149
7150 _value: function() {
7151 return this.valueMethod.apply( this.element, arguments );
7152 },
7153
7154 _keyEvent: function( keyEvent, event ) {
7155 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
7156 this._move( keyEvent, event );
7157
7158 // prevents moving cursor to beginning/end of the text field in some browsers
7159 event.preventDefault();
7160 }
7161 }
7162});
7163
7164$.extend( $.ui.autocomplete, {
7165 escapeRegex: function( value ) {
7166 return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
7167 },
7168 filter: function(array, term) {
7169 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
7170 return $.grep( array, function(value) {
7171 return matcher.test( value.label || value.value || value );
7172 });
7173 }
7174});
7175
7176
7177// live region extension, adding a `messages` option
7178// NOTE: This is an experimental API. We are still investigating
7179// a full solution for string manipulation and internationalization.
7180$.widget( "ui.autocomplete", $.ui.autocomplete, {
7181 options: {
7182 messages: {
7183 noResults: "No search results.",
7184 results: function( amount ) {
7185 return amount + ( amount > 1 ? " results are" : " result is" ) +
7186 " available, use up and down arrow keys to navigate.";
7187 }
7188 }
7189 },
7190
7191 __response: function( content ) {
7192 var message;
7193 this._superApply( arguments );
7194 if ( this.options.disabled || this.cancelSearch ) {
7195 return;
7196 }
7197 if ( content && content.length ) {
7198 message = this.options.messages.results( content.length );
7199 } else {
7200 message = this.options.messages.noResults;
7201 }
7202 this.liveRegion.text( message );
7203 }
7204});
7205
7206}( jQuery ));
7207
7208(function( $, undefined ) {
7209
7210var lastActive, startXPos, startYPos, clickDragged,
7211 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
7212 stateClasses = "ui-state-hover ui-state-active ",
7213 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",
7214 formResetHandler = function() {
7215 var form = $( this );
7216 setTimeout(function() {
7217 form.find( ":ui-button" ).button( "refresh" );
7218 }, 1 );
7219 },
7220 radioGroup = function( radio ) {
7221 var name = radio.name,
7222 form = radio.form,
7223 radios = $( [] );
7224 if ( name ) {
7225 name = name.replace( /'/g, "\\'" );
7226 if ( form ) {
7227 radios = $( form ).find( "[name='" + name + "']" );
7228 } else {
7229 radios = $( "[name='" + name + "']", radio.ownerDocument )
7230 .filter(function() {
7231 return !this.form;
7232 });
7233 }
7234 }
7235 return radios;
7236 };
7237
7238$.widget( "ui.button", {
7239 version: "1.10.3",
7240 defaultElement: "<button>",
7241 options: {
7242 disabled: null,
7243 text: true,
7244 label: null,
7245 icons: {
7246 primary: null,
7247 secondary: null
7248 }
7249 },
7250 _create: function() {
7251 this.element.closest( "form" )
7252 .unbind( "reset" + this.eventNamespace )
7253 .bind( "reset" + this.eventNamespace, formResetHandler );
7254
7255 if ( typeof this.options.disabled !== "boolean" ) {
7256 this.options.disabled = !!this.element.prop( "disabled" );
7257 } else {
7258 this.element.prop( "disabled", this.options.disabled );
7259 }
7260
7261 this._determineButtonType();
7262 this.hasTitle = !!this.buttonElement.attr( "title" );
7263
7264 var that = this,
7265 options = this.options,
7266 toggleButton = this.type === "checkbox" || this.type === "radio",
7267 activeClass = !toggleButton ? "ui-state-active" : "",
7268 focusClass = "ui-state-focus";
7269
7270 if ( options.label === null ) {
7271 options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
7272 }
7273
7274 this._hoverable( this.buttonElement );
7275
7276 this.buttonElement
7277 .addClass( baseClasses )
7278 .attr( "role", "button" )
7279 .bind( "mouseenter" + this.eventNamespace, function() {
7280 if ( options.disabled ) {
7281 return;
7282 }
7283 if ( this === lastActive ) {
7284 $( this ).addClass( "ui-state-active" );
7285 }
7286 })
7287 .bind( "mouseleave" + this.eventNamespace, function() {
7288 if ( options.disabled ) {
7289 return;
7290 }
7291 $( this ).removeClass( activeClass );
7292 })
7293 .bind( "click" + this.eventNamespace, function( event ) {
7294 if ( options.disabled ) {
7295 event.preventDefault();
7296 event.stopImmediatePropagation();
7297 }
7298 });
7299
7300 this.element
7301 .bind( "focus" + this.eventNamespace, function() {
7302 // no need to check disabled, focus won't be triggered anyway
7303 that.buttonElement.addClass( focusClass );
7304 })
7305 .bind( "blur" + this.eventNamespace, function() {
7306 that.buttonElement.removeClass( focusClass );
7307 });
7308
7309 if ( toggleButton ) {
7310 this.element.bind( "change" + this.eventNamespace, function() {
7311 if ( clickDragged ) {
7312 return;
7313 }
7314 that.refresh();
7315 });
7316 // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
7317 // prevents issue where button state changes but checkbox/radio checked state
7318 // does not in Firefox (see ticket #6970)
7319 this.buttonElement
7320 .bind( "mousedown" + this.eventNamespace, function( event ) {
7321 if ( options.disabled ) {
7322 return;
7323 }
7324 clickDragged = false;
7325 startXPos = event.pageX;
7326 startYPos = event.pageY;
7327 })
7328 .bind( "mouseup" + this.eventNamespace, function( event ) {
7329 if ( options.disabled ) {
7330 return;
7331 }
7332 if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
7333 clickDragged = true;
7334 }
7335 });
7336 }
7337
7338 if ( this.type === "checkbox" ) {
7339 this.buttonElement.bind( "click" + this.eventNamespace, function() {
7340 if ( options.disabled || clickDragged ) {
7341 return false;
7342 }
7343 });
7344 } else if ( this.type === "radio" ) {
7345 this.buttonElement.bind( "click" + this.eventNamespace, function() {
7346 if ( options.disabled || clickDragged ) {
7347 return false;
7348 }
7349 $( this ).addClass( "ui-state-active" );
7350 that.buttonElement.attr( "aria-pressed", "true" );
7351
7352 var radio = that.element[ 0 ];
7353 radioGroup( radio )
7354 .not( radio )
7355 .map(function() {
7356 return $( this ).button( "widget" )[ 0 ];
7357 })
7358 .removeClass( "ui-state-active" )
7359 .attr( "aria-pressed", "false" );
7360 });
7361 } else {
7362 this.buttonElement
7363 .bind( "mousedown" + this.eventNamespace, function() {
7364 if ( options.disabled ) {
7365 return false;
7366 }
7367 $( this ).addClass( "ui-state-active" );
7368 lastActive = this;
7369 that.document.one( "mouseup", function() {
7370 lastActive = null;
7371 });
7372 })
7373 .bind( "mouseup" + this.eventNamespace, function() {
7374 if ( options.disabled ) {
7375 return false;
7376 }
7377 $( this ).removeClass( "ui-state-active" );
7378 })
7379 .bind( "keydown" + this.eventNamespace, function(event) {
7380 if ( options.disabled ) {
7381 return false;
7382 }
7383 if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
7384 $( this ).addClass( "ui-state-active" );
7385 }
7386 })
7387 // see #8559, we bind to blur here in case the button element loses
7388 // focus between keydown and keyup, it would be left in an "active" state
7389 .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
7390 $( this ).removeClass( "ui-state-active" );
7391 });
7392
7393 if ( this.buttonElement.is("a") ) {
7394 this.buttonElement.keyup(function(event) {
7395 if ( event.keyCode === $.ui.keyCode.SPACE ) {
7396 // TODO pass through original event correctly (just as 2nd argument doesn't work)
7397 $( this ).click();
7398 }
7399 });
7400 }
7401 }
7402
7403 // TODO: pull out $.Widget's handling for the disabled option into
7404 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
7405 // be overridden by individual plugins
7406 this._setOption( "disabled", options.disabled );
7407 this._resetButton();
7408 },
7409
7410 _determineButtonType: function() {
7411 var ancestor, labelSelector, checked;
7412
7413 if ( this.element.is("[type=checkbox]") ) {
7414 this.type = "checkbox";
7415 } else if ( this.element.is("[type=radio]") ) {
7416 this.type = "radio";
7417 } else if ( this.element.is("input") ) {
7418 this.type = "input";
7419 } else {
7420 this.type = "button";
7421 }
7422
7423 if ( this.type === "checkbox" || this.type === "radio" ) {
7424 // we don't search against the document in case the element
7425 // is disconnected from the DOM
7426 ancestor = this.element.parents().last();
7427 labelSelector = "label[for='" + this.element.attr("id") + "']";
7428 this.buttonElement = ancestor.find( labelSelector );
7429 if ( !this.buttonElement.length ) {
7430 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
7431 this.buttonElement = ancestor.filter( labelSelector );
7432 if ( !this.buttonElement.length ) {
7433 this.buttonElement = ancestor.find( labelSelector );
7434 }
7435 }
7436 this.element.addClass( "ui-helper-hidden-accessible" );
7437
7438 checked = this.element.is( ":checked" );
7439 if ( checked ) {
7440 this.buttonElement.addClass( "ui-state-active" );
7441 }
7442 this.buttonElement.prop( "aria-pressed", checked );
7443 } else {
7444 this.buttonElement = this.element;
7445 }
7446 },
7447
7448 widget: function() {
7449 return this.buttonElement;
7450 },
7451
7452 _destroy: function() {
7453 this.element
7454 .removeClass( "ui-helper-hidden-accessible" );
7455 this.buttonElement
7456 .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
7457 .removeAttr( "role" )
7458 .removeAttr( "aria-pressed" )
7459 .html( this.buttonElement.find(".ui-button-text").html() );
7460
7461 if ( !this.hasTitle ) {
7462 this.buttonElement.removeAttr( "title" );
7463 }
7464 },
7465
7466 _setOption: function( key, value ) {
7467 this._super( key, value );
7468 if ( key === "disabled" ) {
7469 if ( value ) {
7470 this.element.prop( "disabled", true );
7471 } else {
7472 this.element.prop( "disabled", false );
7473 }
7474 return;
7475 }
7476 this._resetButton();
7477 },
7478
7479 refresh: function() {
7480 //See #8237 & #8828
7481 var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
7482
7483 if ( isDisabled !== this.options.disabled ) {
7484 this._setOption( "disabled", isDisabled );
7485 }
7486 if ( this.type === "radio" ) {
7487 radioGroup( this.element[0] ).each(function() {
7488 if ( $( this ).is( ":checked" ) ) {
7489 $( this ).button( "widget" )
7490 .addClass( "ui-state-active" )
7491 .attr( "aria-pressed", "true" );
7492 } else {
7493 $( this ).button( "widget" )
7494 .removeClass( "ui-state-active" )
7495 .attr( "aria-pressed", "false" );
7496 }
7497 });
7498 } else if ( this.type === "checkbox" ) {
7499 if ( this.element.is( ":checked" ) ) {
7500 this.buttonElement
7501 .addClass( "ui-state-active" )
7502 .attr( "aria-pressed", "true" );
7503 } else {
7504 this.buttonElement
7505 .removeClass( "ui-state-active" )
7506 .attr( "aria-pressed", "false" );
7507 }
7508 }
7509 },
7510
7511 _resetButton: function() {
7512 if ( this.type === "input" ) {
7513 if ( this.options.label ) {
7514 this.element.val( this.options.label );
7515 }
7516 return;
7517 }
7518 var buttonElement = this.buttonElement.removeClass( typeClasses ),
7519 buttonText = $( "<span></span>", this.document[0] )
7520 .addClass( "ui-button-text" )
7521 .html( this.options.label )
7522 .appendTo( buttonElement.empty() )
7523 .text(),
7524 icons = this.options.icons,
7525 multipleIcons = icons.primary && icons.secondary,
7526 buttonClasses = [];
7527
7528 if ( icons.primary || icons.secondary ) {
7529 if ( this.options.text ) {
7530 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
7531 }
7532
7533 if ( icons.primary ) {
7534 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
7535 }
7536
7537 if ( icons.secondary ) {
7538 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
7539 }
7540
7541 if ( !this.options.text ) {
7542 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
7543
7544 if ( !this.hasTitle ) {
7545 buttonElement.attr( "title", $.trim( buttonText ) );
7546 }
7547 }
7548 } else {
7549 buttonClasses.push( "ui-button-text-only" );
7550 }
7551 buttonElement.addClass( buttonClasses.join( " " ) );
7552 }
7553});
7554
7555$.widget( "ui.buttonset", {
7556 version: "1.10.3",
7557 options: {
7558 items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
7559 },
7560
7561 _create: function() {
7562 this.element.addClass( "ui-buttonset" );
7563 },
7564
7565 _init: function() {
7566 this.refresh();
7567 },
7568
7569 _setOption: function( key, value ) {
7570 if ( key === "disabled" ) {
7571 this.buttons.button( "option", key, value );
7572 }
7573
7574 this._super( key, value );
7575 },
7576
7577 refresh: function() {
7578 var rtl = this.element.css( "direction" ) === "rtl";
7579
7580 this.buttons = this.element.find( this.options.items )
7581 .filter( ":ui-button" )
7582 .button( "refresh" )
7583 .end()
7584 .not( ":ui-button" )
7585 .button()
7586 .end()
7587 .map(function() {
7588 return $( this ).button( "widget" )[ 0 ];
7589 })
7590 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
7591 .filter( ":first" )
7592 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
7593 .end()
7594 .filter( ":last" )
7595 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
7596 .end()
7597 .end();
7598 },
7599
7600 _destroy: function() {
7601 this.element.removeClass( "ui-buttonset" );
7602 this.buttons
7603 .map(function() {
7604 return $( this ).button( "widget" )[ 0 ];
7605 })
7606 .removeClass( "ui-corner-left ui-corner-right" )
7607 .end()
7608 .button( "destroy" );
7609 }
7610});
7611
7612}( jQuery ) );
7613
7614(function( $, undefined ) {
7615
7616$.extend($.ui, { datepicker: { version: "1.10.3" } });
7617
7618var PROP_NAME = "datepicker",
7619 instActive;
7620
7621/* Date picker manager.
7622 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7623 Settings for (groups of) date pickers are maintained in an instance object,
7624 allowing multiple different settings on the same page. */
7625
7626function Datepicker() {
7627 this._curInst = null; // The current instance in use
7628 this._keyEvent = false; // If the last event was a key event
7629 this._disabledInputs = []; // List of date picker inputs that have been disabled
7630 this._datepickerShowing = false; // True if the popup picker is showing , false if not
7631 this._inDialog = false; // True if showing within a "dialog", false if not
7632 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
7633 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
7634 this._appendClass = "ui-datepicker-append"; // The name of the append marker class
7635 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
7636 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
7637 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
7638 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
7639 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
7640 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
7641 this.regional = []; // Available regional settings, indexed by language code
7642 this.regional[""] = { // Default regional settings
7643 closeText: "Done", // Display text for close link
7644 prevText: "Prev", // Display text for previous month link
7645 nextText: "Next", // Display text for next month link
7646 currentText: "Today", // Display text for current month link
7647 monthNames: ["January","February","March","April","May","June",
7648 "July","August","September","October","November","December"], // Names of months for drop-down and formatting
7649 monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
7650 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
7651 dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
7652 dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
7653 weekHeader: "Wk", // Column header for week of the year
7654 dateFormat: "mm/dd/yy", // See format options on parseDate
7655 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7656 isRTL: false, // True if right-to-left language, false if left-to-right
7657 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7658 yearSuffix: "" // Additional text to append to the year in the month headers
7659 };
7660 this._defaults = { // Global defaults for all the date picker instances
7661 showOn: "focus", // "focus" for popup on focus,
7662 // "button" for trigger button, or "both" for either
7663 showAnim: "fadeIn", // Name of jQuery animation for popup
7664 showOptions: {}, // Options for enhanced animations
7665 defaultDate: null, // Used when field is blank: actual date,
7666 // +/-number for offset from today, null for today
7667 appendText: "", // Display text following the input box, e.g. showing the format
7668 buttonText: "...", // Text for trigger button
7669 buttonImage: "", // URL for trigger button image
7670 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7671 hideIfNoPrevNext: false, // True to hide next/previous month links
7672 // if not applicable, false to just disable them
7673 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7674 gotoCurrent: false, // True if today link goes back to current selection instead
7675 changeMonth: false, // True if month can be selected directly, false if only prev/next
7676 changeYear: false, // True if year can be selected directly, false if only prev/next
7677 yearRange: "c-10:c+10", // Range of years to display in drop-down,
7678 // either relative to today's year (-nn:+nn), relative to currently displayed year
7679 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7680 showOtherMonths: false, // True to show dates in other months, false to leave blank
7681 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7682 showWeek: false, // True to show week of the year, false to not show it
7683 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7684 // takes a Date and returns the number of the week for it
7685 shortYearCutoff: "+10", // Short year values < this are in the current century,
7686 // > this are in the previous century,
7687 // string value starting with "+" for current year + value
7688 minDate: null, // The earliest selectable date, or null for no limit
7689 maxDate: null, // The latest selectable date, or null for no limit
7690 duration: "fast", // Duration of display/closure
7691 beforeShowDay: null, // Function that takes a date and returns an array with
7692 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
7693 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
7694 beforeShow: null, // Function that takes an input field and
7695 // returns a set of custom settings for the date picker
7696 onSelect: null, // Define a callback function when a date is selected
7697 onChangeMonthYear: null, // Define a callback function when the month or year is changed
7698 onClose: null, // Define a callback function when the datepicker is closed
7699 numberOfMonths: 1, // Number of months to show at a time
7700 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7701 stepMonths: 1, // Number of months to step back/forward
7702 stepBigMonths: 12, // Number of months to step back/forward for the big links
7703 altField: "", // Selector for an alternate field to store selected dates into
7704 altFormat: "", // The date format to use for the alternate field
7705 constrainInput: true, // The input is constrained by the current date format
7706 showButtonPanel: false, // True to show button panel, false to not show it
7707 autoSize: false, // True to size the input for the date format, false to leave as is
7708 disabled: false // The initial disabled state
7709 };
7710 $.extend(this._defaults, this.regional[""]);
7711 this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
7712}
7713
7714$.extend(Datepicker.prototype, {
7715 /* Class name added to elements to indicate already configured with a date picker. */
7716 markerClassName: "hasDatepicker",
7717
7718 //Keep track of the maximum number of rows displayed (see #7043)
7719 maxRows: 4,
7720
7721 // TODO rename to "widget" when switching to widget factory
7722 _widgetDatepicker: function() {
7723 return this.dpDiv;
7724 },
7725
7726 /* Override the default settings for all instances of the date picker.
7727 * @param settings object - the new settings to use as defaults (anonymous object)
7728 * @return the manager object
7729 */
7730 setDefaults: function(settings) {
7731 extendRemove(this._defaults, settings || {});
7732 return this;
7733 },
7734
7735 /* Attach the date picker to a jQuery selection.
7736 * @param target element - the target input field or division or span
7737 * @param settings object - the new settings to use for this date picker instance (anonymous)
7738 */
7739 _attachDatepicker: function(target, settings) {
7740 var nodeName, inline, inst;
7741 nodeName = target.nodeName.toLowerCase();
7742 inline = (nodeName === "div" || nodeName === "span");
7743 if (!target.id) {
7744 this.uuid += 1;
7745 target.id = "dp" + this.uuid;
7746 }
7747 inst = this._newInst($(target), inline);
7748 inst.settings = $.extend({}, settings || {});
7749 if (nodeName === "input") {
7750 this._connectDatepicker(target, inst);
7751 } else if (inline) {
7752 this._inlineDatepicker(target, inst);
7753 }
7754 },
7755
7756 /* Create a new instance object. */
7757 _newInst: function(target, inline) {
7758 var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
7759 return {id: id, input: target, // associated target
7760 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7761 drawMonth: 0, drawYear: 0, // month being drawn
7762 inline: inline, // is datepicker inline or not
7763 dpDiv: (!inline ? this.dpDiv : // presentation div
7764 bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
7765 },
7766
7767 /* Attach the date picker to an input field. */
7768 _connectDatepicker: function(target, inst) {
7769 var input = $(target);
7770 inst.append = $([]);
7771 inst.trigger = $([]);
7772 if (input.hasClass(this.markerClassName)) {
7773 return;
7774 }
7775 this._attachments(input, inst);
7776 input.addClass(this.markerClassName).keydown(this._doKeyDown).
7777 keypress(this._doKeyPress).keyup(this._doKeyUp);
7778 this._autoSize(inst);
7779 $.data(target, PROP_NAME, inst);
7780 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7781 if( inst.settings.disabled ) {
7782 this._disableDatepicker( target );
7783 }
7784 },
7785
7786 /* Make attachments based on settings. */
7787 _attachments: function(input, inst) {
7788 var showOn, buttonText, buttonImage,
7789 appendText = this._get(inst, "appendText"),
7790 isRTL = this._get(inst, "isRTL");
7791
7792 if (inst.append) {
7793 inst.append.remove();
7794 }
7795 if (appendText) {
7796 inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
7797 input[isRTL ? "before" : "after"](inst.append);
7798 }
7799
7800 input.unbind("focus", this._showDatepicker);
7801
7802 if (inst.trigger) {
7803 inst.trigger.remove();
7804 }
7805
7806 showOn = this._get(inst, "showOn");
7807 if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
7808 input.focus(this._showDatepicker);
7809 }
7810 if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
7811 buttonText = this._get(inst, "buttonText");
7812 buttonImage = this._get(inst, "buttonImage");
7813 inst.trigger = $(this._get(inst, "buttonImageOnly") ?
7814 $("<img/>").addClass(this._triggerClass).
7815 attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
7816 $("<button type='button'></button>").addClass(this._triggerClass).
7817 html(!buttonImage ? buttonText : $("<img/>").attr(
7818 { src:buttonImage, alt:buttonText, title:buttonText })));
7819 input[isRTL ? "before" : "after"](inst.trigger);
7820 inst.trigger.click(function() {
7821 if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
7822 $.datepicker._hideDatepicker();
7823 } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
7824 $.datepicker._hideDatepicker();
7825 $.datepicker._showDatepicker(input[0]);
7826 } else {
7827 $.datepicker._showDatepicker(input[0]);
7828 }
7829 return false;
7830 });
7831 }
7832 },
7833
7834 /* Apply the maximum length for the date format. */
7835 _autoSize: function(inst) {
7836 if (this._get(inst, "autoSize") && !inst.inline) {
7837 var findMax, max, maxI, i,
7838 date = new Date(2009, 12 - 1, 20), // Ensure double digits
7839 dateFormat = this._get(inst, "dateFormat");
7840
7841 if (dateFormat.match(/[DM]/)) {
7842 findMax = function(names) {
7843 max = 0;
7844 maxI = 0;
7845 for (i = 0; i < names.length; i++) {
7846 if (names[i].length > max) {
7847 max = names[i].length;
7848 maxI = i;
7849 }
7850 }
7851 return maxI;
7852 };
7853 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
7854 "monthNames" : "monthNamesShort"))));
7855 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
7856 "dayNames" : "dayNamesShort"))) + 20 - date.getDay());
7857 }
7858 inst.input.attr("size", this._formatDate(inst, date).length);
7859 }
7860 },
7861
7862 /* Attach an inline date picker to a div. */
7863 _inlineDatepicker: function(target, inst) {
7864 var divSpan = $(target);
7865 if (divSpan.hasClass(this.markerClassName)) {
7866 return;
7867 }
7868 divSpan.addClass(this.markerClassName).append(inst.dpDiv);
7869 $.data(target, PROP_NAME, inst);
7870 this._setDate(inst, this._getDefaultDate(inst), true);
7871 this._updateDatepicker(inst);
7872 this._updateAlternate(inst);
7873 //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7874 if( inst.settings.disabled ) {
7875 this._disableDatepicker( target );
7876 }
7877 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7878 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7879 inst.dpDiv.css( "display", "block" );
7880 },
7881
7882 /* Pop-up the date picker in a "dialog" box.
7883 * @param input element - ignored
7884 * @param date string or Date - the initial date to display
7885 * @param onSelect function - the function to call when a date is selected
7886 * @param settings object - update the dialog date picker instance's settings (anonymous object)
7887 * @param pos int[2] - coordinates for the dialog's position within the screen or
7888 * event - with x/y coordinates or
7889 * leave empty for default (screen centre)
7890 * @return the manager object
7891 */
7892 _dialogDatepicker: function(input, date, onSelect, settings, pos) {
7893 var id, browserWidth, browserHeight, scrollX, scrollY,
7894 inst = this._dialogInst; // internal instance
7895
7896 if (!inst) {
7897 this.uuid += 1;
7898 id = "dp" + this.uuid;
7899 this._dialogInput = $("<input type='text' id='" + id +
7900 "' style='position: absolute; top: -100px; width: 0px;'/>");
7901 this._dialogInput.keydown(this._doKeyDown);
7902 $("body").append(this._dialogInput);
7903 inst = this._dialogInst = this._newInst(this._dialogInput, false);
7904 inst.settings = {};
7905 $.data(this._dialogInput[0], PROP_NAME, inst);
7906 }
7907 extendRemove(inst.settings, settings || {});
7908 date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
7909 this._dialogInput.val(date);
7910
7911 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
7912 if (!this._pos) {
7913 browserWidth = document.documentElement.clientWidth;
7914 browserHeight = document.documentElement.clientHeight;
7915 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7916 scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7917 this._pos = // should use actual width/height below
7918 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
7919 }
7920
7921 // move input on screen for focus, but hidden behind dialog
7922 this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
7923 inst.settings.onSelect = onSelect;
7924 this._inDialog = true;
7925 this.dpDiv.addClass(this._dialogClass);
7926 this._showDatepicker(this._dialogInput[0]);
7927 if ($.blockUI) {
7928 $.blockUI(this.dpDiv);
7929 }
7930 $.data(this._dialogInput[0], PROP_NAME, inst);
7931 return this;
7932 },
7933
7934 /* Detach a datepicker from its control.
7935 * @param target element - the target input field or division or span
7936 */
7937 _destroyDatepicker: function(target) {
7938 var nodeName,
7939 $target = $(target),
7940 inst = $.data(target, PROP_NAME);
7941
7942 if (!$target.hasClass(this.markerClassName)) {
7943 return;
7944 }
7945
7946 nodeName = target.nodeName.toLowerCase();
7947 $.removeData(target, PROP_NAME);
7948 if (nodeName === "input") {
7949 inst.append.remove();
7950 inst.trigger.remove();
7951 $target.removeClass(this.markerClassName).
7952 unbind("focus", this._showDatepicker).
7953 unbind("keydown", this._doKeyDown).
7954 unbind("keypress", this._doKeyPress).
7955 unbind("keyup", this._doKeyUp);
7956 } else if (nodeName === "div" || nodeName === "span") {
7957 $target.removeClass(this.markerClassName).empty();
7958 }
7959 },
7960
7961 /* Enable the date picker to a jQuery selection.
7962 * @param target element - the target input field or division or span
7963 */
7964 _enableDatepicker: function(target) {
7965 var nodeName, inline,
7966 $target = $(target),
7967 inst = $.data(target, PROP_NAME);
7968
7969 if (!$target.hasClass(this.markerClassName)) {
7970 return;
7971 }
7972
7973 nodeName = target.nodeName.toLowerCase();
7974 if (nodeName === "input") {
7975 target.disabled = false;
7976 inst.trigger.filter("button").
7977 each(function() { this.disabled = false; }).end().
7978 filter("img").css({opacity: "1.0", cursor: ""});
7979 } else if (nodeName === "div" || nodeName === "span") {
7980 inline = $target.children("." + this._inlineClass);
7981 inline.children().removeClass("ui-state-disabled");
7982 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
7983 prop("disabled", false);
7984 }
7985 this._disabledInputs = $.map(this._disabledInputs,
7986 function(value) { return (value === target ? null : value); }); // delete entry
7987 },
7988
7989 /* Disable the date picker to a jQuery selection.
7990 * @param target element - the target input field or division or span
7991 */
7992 _disableDatepicker: function(target) {
7993 var nodeName, inline,
7994 $target = $(target),
7995 inst = $.data(target, PROP_NAME);
7996
7997 if (!$target.hasClass(this.markerClassName)) {
7998 return;
7999 }
8000
8001 nodeName = target.nodeName.toLowerCase();
8002 if (nodeName === "input") {
8003 target.disabled = true;
8004 inst.trigger.filter("button").
8005 each(function() { this.disabled = true; }).end().
8006 filter("img").css({opacity: "0.5", cursor: "default"});
8007 } else if (nodeName === "div" || nodeName === "span") {
8008 inline = $target.children("." + this._inlineClass);
8009 inline.children().addClass("ui-state-disabled");
8010 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
8011 prop("disabled", true);
8012 }
8013 this._disabledInputs = $.map(this._disabledInputs,
8014 function(value) { return (value === target ? null : value); }); // delete entry
8015 this._disabledInputs[this._disabledInputs.length] = target;
8016 },
8017
8018 /* Is the first field in a jQuery collection disabled as a datepicker?
8019 * @param target element - the target input field or division or span
8020 * @return boolean - true if disabled, false if enabled
8021 */
8022 _isDisabledDatepicker: function(target) {
8023 if (!target) {
8024 return false;
8025 }
8026 for (var i = 0; i < this._disabledInputs.length; i++) {
8027 if (this._disabledInputs[i] === target) {
8028 return true;
8029 }
8030 }
8031 return false;
8032 },
8033
8034 /* Retrieve the instance data for the target control.
8035 * @param target element - the target input field or division or span
8036 * @return object - the associated instance data
8037 * @throws error if a jQuery problem getting data
8038 */
8039 _getInst: function(target) {
8040 try {
8041 return $.data(target, PROP_NAME);
8042 }
8043 catch (err) {
8044 throw "Missing instance data for this datepicker";
8045 }
8046 },
8047
8048 /* Update or retrieve the settings for a date picker attached to an input field or division.
8049 * @param target element - the target input field or division or span
8050 * @param name object - the new settings to update or
8051 * string - the name of the setting to change or retrieve,
8052 * when retrieving also "all" for all instance settings or
8053 * "defaults" for all global defaults
8054 * @param value any - the new value for the setting
8055 * (omit if above is an object or to retrieve a value)
8056 */
8057 _optionDatepicker: function(target, name, value) {
8058 var settings, date, minDate, maxDate,
8059 inst = this._getInst(target);
8060
8061 if (arguments.length === 2 && typeof name === "string") {
8062 return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
8063 (inst ? (name === "all" ? $.extend({}, inst.settings) :
8064 this._get(inst, name)) : null));
8065 }
8066
8067 settings = name || {};
8068 if (typeof name === "string") {
8069 settings = {};
8070 settings[name] = value;
8071 }
8072
8073 if (inst) {
8074 if (this._curInst === inst) {
8075 this._hideDatepicker();
8076 }
8077
8078 date = this._getDateDatepicker(target, true);
8079 minDate = this._getMinMaxDate(inst, "min");
8080 maxDate = this._getMinMaxDate(inst, "max");
8081 extendRemove(inst.settings, settings);
8082 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
8083 if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
8084 inst.settings.minDate = this._formatDate(inst, minDate);
8085 }
8086 if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
8087 inst.settings.maxDate = this._formatDate(inst, maxDate);
8088 }
8089 if ( "disabled" in settings ) {
8090 if ( settings.disabled ) {
8091 this._disableDatepicker(target);
8092 } else {
8093 this._enableDatepicker(target);
8094 }
8095 }
8096 this._attachments($(target), inst);
8097 this._autoSize(inst);
8098 this._setDate(inst, date);
8099 this._updateAlternate(inst);
8100 this._updateDatepicker(inst);
8101 }
8102 },
8103
8104 // change method deprecated
8105 _changeDatepicker: function(target, name, value) {
8106 this._optionDatepicker(target, name, value);
8107 },
8108
8109 /* Redraw the date picker attached to an input field or division.
8110 * @param target element - the target input field or division or span
8111 */
8112 _refreshDatepicker: function(target) {
8113 var inst = this._getInst(target);
8114 if (inst) {
8115 this._updateDatepicker(inst);
8116 }
8117 },
8118
8119 /* Set the dates for a jQuery selection.
8120 * @param target element - the target input field or division or span
8121 * @param date Date - the new date
8122 */
8123 _setDateDatepicker: function(target, date) {
8124 var inst = this._getInst(target);
8125 if (inst) {
8126 this._setDate(inst, date);
8127 this._updateDatepicker(inst);
8128 this._updateAlternate(inst);
8129 }
8130 },
8131
8132 /* Get the date(s) for the first entry in a jQuery selection.
8133 * @param target element - the target input field or division or span
8134 * @param noDefault boolean - true if no default date is to be used
8135 * @return Date - the current date
8136 */
8137 _getDateDatepicker: function(target, noDefault) {
8138 var inst = this._getInst(target);
8139 if (inst && !inst.inline) {
8140 this._setDateFromField(inst, noDefault);
8141 }
8142 return (inst ? this._getDate(inst) : null);
8143 },
8144
8145 /* Handle keystrokes. */
8146 _doKeyDown: function(event) {
8147 var onSelect, dateStr, sel,
8148 inst = $.datepicker._getInst(event.target),
8149 handled = true,
8150 isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
8151
8152 inst._keyEvent = true;
8153 if ($.datepicker._datepickerShowing) {
8154 switch (event.keyCode) {
8155 case 9: $.datepicker._hideDatepicker();
8156 handled = false;
8157 break; // hide on tab out
8158 case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
8159 $.datepicker._currentClass + ")", inst.dpDiv);
8160 if (sel[0]) {
8161 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
8162 }
8163
8164 onSelect = $.datepicker._get(inst, "onSelect");
8165 if (onSelect) {
8166 dateStr = $.datepicker._formatDate(inst);
8167
8168 // trigger custom callback
8169 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
8170 } else {
8171 $.datepicker._hideDatepicker();
8172 }
8173
8174 return false; // don't submit the form
8175 case 27: $.datepicker._hideDatepicker();
8176 break; // hide on escape
8177 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8178 -$.datepicker._get(inst, "stepBigMonths") :
8179 -$.datepicker._get(inst, "stepMonths")), "M");
8180 break; // previous month/year on page up/+ ctrl
8181 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8182 +$.datepicker._get(inst, "stepBigMonths") :
8183 +$.datepicker._get(inst, "stepMonths")), "M");
8184 break; // next month/year on page down/+ ctrl
8185 case 35: if (event.ctrlKey || event.metaKey) {
8186 $.datepicker._clearDate(event.target);
8187 }
8188 handled = event.ctrlKey || event.metaKey;
8189 break; // clear on ctrl or command +end
8190 case 36: if (event.ctrlKey || event.metaKey) {
8191 $.datepicker._gotoToday(event.target);
8192 }
8193 handled = event.ctrlKey || event.metaKey;
8194 break; // current on ctrl or command +home
8195 case 37: if (event.ctrlKey || event.metaKey) {
8196 $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
8197 }
8198 handled = event.ctrlKey || event.metaKey;
8199 // -1 day on ctrl or command +left
8200 if (event.originalEvent.altKey) {
8201 $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8202 -$.datepicker._get(inst, "stepBigMonths") :
8203 -$.datepicker._get(inst, "stepMonths")), "M");
8204 }
8205 // next month/year on alt +left on Mac
8206 break;
8207 case 38: if (event.ctrlKey || event.metaKey) {
8208 $.datepicker._adjustDate(event.target, -7, "D");
8209 }
8210 handled = event.ctrlKey || event.metaKey;
8211 break; // -1 week on ctrl or command +up
8212 case 39: if (event.ctrlKey || event.metaKey) {
8213 $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
8214 }
8215 handled = event.ctrlKey || event.metaKey;
8216 // +1 day on ctrl or command +right
8217 if (event.originalEvent.altKey) {
8218 $.datepicker._adjustDate(event.target, (event.ctrlKey ?
8219 +$.datepicker._get(inst, "stepBigMonths") :
8220 +$.datepicker._get(inst, "stepMonths")), "M");
8221 }
8222 // next month/year on alt +right
8223 break;
8224 case 40: if (event.ctrlKey || event.metaKey) {
8225 $.datepicker._adjustDate(event.target, +7, "D");
8226 }
8227 handled = event.ctrlKey || event.metaKey;
8228 break; // +1 week on ctrl or command +down
8229 default: handled = false;
8230 }
8231 } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
8232 $.datepicker._showDatepicker(this);
8233 } else {
8234 handled = false;
8235 }
8236
8237 if (handled) {
8238 event.preventDefault();
8239 event.stopPropagation();
8240 }
8241 },
8242
8243 /* Filter entered characters - based on date format. */
8244 _doKeyPress: function(event) {
8245 var chars, chr,
8246 inst = $.datepicker._getInst(event.target);
8247
8248 if ($.datepicker._get(inst, "constrainInput")) {
8249 chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
8250 chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
8251 return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
8252 }
8253 },
8254
8255 /* Synchronise manual entry and field/alternate field. */
8256 _doKeyUp: function(event) {
8257 var date,
8258 inst = $.datepicker._getInst(event.target);
8259
8260 if (inst.input.val() !== inst.lastVal) {
8261 try {
8262 date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
8263 (inst.input ? inst.input.val() : null),
8264 $.datepicker._getFormatConfig(inst));
8265
8266 if (date) { // only if valid
8267 $.datepicker._setDateFromField(inst);
8268 $.datepicker._updateAlternate(inst);
8269 $.datepicker._updateDatepicker(inst);
8270 }
8271 }
8272 catch (err) {
8273 }
8274 }
8275 return true;
8276 },
8277
8278 /* Pop-up the date picker for a given input field.
8279 * If false returned from beforeShow event handler do not show.
8280 * @param input element - the input field attached to the date picker or
8281 * event - if triggered by focus
8282 */
8283 _showDatepicker: function(input) {
8284 input = input.target || input;
8285 if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
8286 input = $("input", input.parentNode)[0];
8287 }
8288
8289 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
8290 return;
8291 }
8292
8293 var inst, beforeShow, beforeShowSettings, isFixed,
8294 offset, showAnim, duration;
8295
8296 inst = $.datepicker._getInst(input);
8297 if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
8298 $.datepicker._curInst.dpDiv.stop(true, true);
8299 if ( inst && $.datepicker._datepickerShowing ) {
8300 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
8301 }
8302 }
8303
8304 beforeShow = $.datepicker._get(inst, "beforeShow");
8305 beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
8306 if(beforeShowSettings === false){
8307 return;
8308 }
8309 extendRemove(inst.settings, beforeShowSettings);
8310
8311 inst.lastVal = null;
8312 $.datepicker._lastInput = input;
8313 $.datepicker._setDateFromField(inst);
8314
8315 if ($.datepicker._inDialog) { // hide cursor
8316 input.value = "";
8317 }
8318 if (!$.datepicker._pos) { // position below input
8319 $.datepicker._pos = $.datepicker._findPos(input);
8320 $.datepicker._pos[1] += input.offsetHeight; // add the height
8321 }
8322
8323 isFixed = false;
8324 $(input).parents().each(function() {
8325 isFixed |= $(this).css("position") === "fixed";
8326 return !isFixed;
8327 });
8328
8329 offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
8330 $.datepicker._pos = null;
8331 //to avoid flashes on Firefox
8332 inst.dpDiv.empty();
8333 // determine sizing offscreen
8334 inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
8335 $.datepicker._updateDatepicker(inst);
8336 // fix width for dynamic number of date pickers
8337 // and adjust position before showing
8338 offset = $.datepicker._checkOffset(inst, offset, isFixed);
8339 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
8340 "static" : (isFixed ? "fixed" : "absolute")), display: "none",
8341 left: offset.left + "px", top: offset.top + "px"});
8342
8343 if (!inst.inline) {
8344 showAnim = $.datepicker._get(inst, "showAnim");
8345 duration = $.datepicker._get(inst, "duration");
8346 inst.dpDiv.zIndex($(input).zIndex()+1);
8347 $.datepicker._datepickerShowing = true;
8348
8349 if ( $.effects && $.effects.effect[ showAnim ] ) {
8350 inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
8351 } else {
8352 inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
8353 }
8354
8355 if ( $.datepicker._shouldFocusInput( inst ) ) {
8356 inst.input.focus();
8357 }
8358
8359 $.datepicker._curInst = inst;
8360 }
8361 },
8362
8363 /* Generate the date picker content. */
8364 _updateDatepicker: function(inst) {
8365 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
8366 instActive = inst; // for delegate hover events
8367 inst.dpDiv.empty().append(this._generateHTML(inst));
8368 this._attachHandlers(inst);
8369 inst.dpDiv.find("." + this._dayOverClass + " a").mouseover();
8370
8371 var origyearshtml,
8372 numMonths = this._getNumberOfMonths(inst),
8373 cols = numMonths[1],
8374 width = 17;
8375
8376 inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
8377 if (cols > 1) {
8378 inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
8379 }
8380 inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
8381 "Class"]("ui-datepicker-multi");
8382 inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
8383 "Class"]("ui-datepicker-rtl");
8384
8385 if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
8386 inst.input.focus();
8387 }
8388
8389 // deffered render of the years select (to avoid flashes on Firefox)
8390 if( inst.yearshtml ){
8391 origyearshtml = inst.yearshtml;
8392 setTimeout(function(){
8393 //assure that inst.yearshtml didn't change.
8394 if( origyearshtml === inst.yearshtml && inst.yearshtml ){
8395 inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
8396 }
8397 origyearshtml = inst.yearshtml = null;
8398 }, 0);
8399 }
8400 },
8401
8402 // #6694 - don't focus the input if it's already focused
8403 // this breaks the change event in IE
8404 // Support: IE and jQuery <1.9
8405 _shouldFocusInput: function( inst ) {
8406 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
8407 },
8408
8409 /* Check positioning to remain on screen. */
8410 _checkOffset: function(inst, offset, isFixed) {
8411 var dpWidth = inst.dpDiv.outerWidth(),
8412 dpHeight = inst.dpDiv.outerHeight(),
8413 inputWidth = inst.input ? inst.input.outerWidth() : 0,
8414 inputHeight = inst.input ? inst.input.outerHeight() : 0,
8415 viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
8416 viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
8417
8418 offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
8419 offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
8420 offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
8421
8422 // now check if datepicker is showing outside window viewport - move to a better place if so.
8423 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
8424 Math.abs(offset.left + dpWidth - viewWidth) : 0);
8425 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
8426 Math.abs(dpHeight + inputHeight) : 0);
8427
8428 return offset;
8429 },
8430
8431 /* Find an object's position on the screen. */
8432 _findPos: function(obj) {
8433 var position,
8434 inst = this._getInst(obj),
8435 isRTL = this._get(inst, "isRTL");
8436
8437 while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
8438 obj = obj[isRTL ? "previousSibling" : "nextSibling"];
8439 }
8440
8441 position = $(obj).offset();
8442 return [position.left, position.top];
8443 },
8444
8445 /* Hide the date picker from view.
8446 * @param input element - the input field attached to the date picker
8447 */
8448 _hideDatepicker: function(input) {
8449 var showAnim, duration, postProcess, onClose,
8450 inst = this._curInst;
8451
8452 if (!inst || (input && inst !== $.data(input, PROP_NAME))) {
8453 return;
8454 }
8455
8456 if (this._datepickerShowing) {
8457 showAnim = this._get(inst, "showAnim");
8458 duration = this._get(inst, "duration");
8459 postProcess = function() {
8460 $.datepicker._tidyDialog(inst);
8461 };
8462
8463 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
8464 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
8465 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
8466 } else {
8467 inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
8468 (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
8469 }
8470
8471 if (!showAnim) {
8472 postProcess();
8473 }
8474 this._datepickerShowing = false;
8475
8476 onClose = this._get(inst, "onClose");
8477 if (onClose) {
8478 onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
8479 }
8480
8481 this._lastInput = null;
8482 if (this._inDialog) {
8483 this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
8484 if ($.blockUI) {
8485 $.unblockUI();
8486 $("body").append(this.dpDiv);
8487 }
8488 }
8489 this._inDialog = false;
8490 }
8491 },
8492
8493 /* Tidy up after a dialog display. */
8494 _tidyDialog: function(inst) {
8495 inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
8496 },
8497
8498 /* Close date picker if clicked elsewhere. */
8499 _checkExternalClick: function(event) {
8500 if (!$.datepicker._curInst) {
8501 return;
8502 }
8503
8504 var $target = $(event.target),
8505 inst = $.datepicker._getInst($target[0]);
8506
8507 if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
8508 $target.parents("#" + $.datepicker._mainDivId).length === 0 &&
8509 !$target.hasClass($.datepicker.markerClassName) &&
8510 !$target.closest("." + $.datepicker._triggerClass).length &&
8511 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
8512 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
8513 $.datepicker._hideDatepicker();
8514 }
8515 },
8516
8517 /* Adjust one of the date sub-fields. */
8518 _adjustDate: function(id, offset, period) {
8519 var target = $(id),
8520 inst = this._getInst(target[0]);
8521
8522 if (this._isDisabledDatepicker(target[0])) {
8523 return;
8524 }
8525 this._adjustInstDate(inst, offset +
8526 (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
8527 period);
8528 this._updateDatepicker(inst);
8529 },
8530
8531 /* Action for current link. */
8532 _gotoToday: function(id) {
8533 var date,
8534 target = $(id),
8535 inst = this._getInst(target[0]);
8536
8537 if (this._get(inst, "gotoCurrent") && inst.currentDay) {
8538 inst.selectedDay = inst.currentDay;
8539 inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8540 inst.drawYear = inst.selectedYear = inst.currentYear;
8541 } else {
8542 date = new Date();
8543 inst.selectedDay = date.getDate();
8544 inst.drawMonth = inst.selectedMonth = date.getMonth();
8545 inst.drawYear = inst.selectedYear = date.getFullYear();
8546 }
8547 this._notifyChange(inst);
8548 this._adjustDate(target);
8549 },
8550
8551 /* Action for selecting a new month/year. */
8552 _selectMonthYear: function(id, select, period) {
8553 var target = $(id),
8554 inst = this._getInst(target[0]);
8555
8556 inst["selected" + (period === "M" ? "Month" : "Year")] =
8557 inst["draw" + (period === "M" ? "Month" : "Year")] =
8558 parseInt(select.options[select.selectedIndex].value,10);
8559
8560 this._notifyChange(inst);
8561 this._adjustDate(target);
8562 },
8563
8564 /* Action for selecting a day. */
8565 _selectDay: function(id, month, year, td) {
8566 var inst,
8567 target = $(id);
8568
8569 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
8570 return;
8571 }
8572
8573 inst = this._getInst(target[0]);
8574 inst.selectedDay = inst.currentDay = $("a", td).html();
8575 inst.selectedMonth = inst.currentMonth = month;
8576 inst.selectedYear = inst.currentYear = year;
8577 this._selectDate(id, this._formatDate(inst,
8578 inst.currentDay, inst.currentMonth, inst.currentYear));
8579 },
8580
8581 /* Erase the input field and hide the date picker. */
8582 _clearDate: function(id) {
8583 var target = $(id);
8584 this._selectDate(target, "");
8585 },
8586
8587 /* Update the input field with the selected date. */
8588 _selectDate: function(id, dateStr) {
8589 var onSelect,
8590 target = $(id),
8591 inst = this._getInst(target[0]);
8592
8593 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
8594 if (inst.input) {
8595 inst.input.val(dateStr);
8596 }
8597 this._updateAlternate(inst);
8598
8599 onSelect = this._get(inst, "onSelect");
8600 if (onSelect) {
8601 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
8602 } else if (inst.input) {
8603 inst.input.trigger("change"); // fire the change event
8604 }
8605
8606 if (inst.inline){
8607 this._updateDatepicker(inst);
8608 } else {
8609 this._hideDatepicker();
8610 this._lastInput = inst.input[0];
8611 if (typeof(inst.input[0]) !== "object") {
8612 inst.input.focus(); // restore focus
8613 }
8614 this._lastInput = null;
8615 }
8616 },
8617
8618 /* Update any alternate field to synchronise with the main field. */
8619 _updateAlternate: function(inst) {
8620 var altFormat, date, dateStr,
8621 altField = this._get(inst, "altField");
8622
8623 if (altField) { // update alternate field too
8624 altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
8625 date = this._getDate(inst);
8626 dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
8627 $(altField).each(function() { $(this).val(dateStr); });
8628 }
8629 },
8630
8631 /* Set as beforeShowDay function to prevent selection of weekends.
8632 * @param date Date - the date to customise
8633 * @return [boolean, string] - is this date selectable?, what is its CSS class?
8634 */
8635 noWeekends: function(date) {
8636 var day = date.getDay();
8637 return [(day > 0 && day < 6), ""];
8638 },
8639
8640 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8641 * @param date Date - the date to get the week for
8642 * @return number - the number of the week within the year that contains this date
8643 */
8644 iso8601Week: function(date) {
8645 var time,
8646 checkDate = new Date(date.getTime());
8647
8648 // Find Thursday of this week starting on Monday
8649 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
8650
8651 time = checkDate.getTime();
8652 checkDate.setMonth(0); // Compare with Jan 1
8653 checkDate.setDate(1);
8654 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
8655 },
8656
8657 /* Parse a string value into a date object.
8658 * See formatDate below for the possible formats.
8659 *
8660 * @param format string - the expected format of the date
8661 * @param value string - the date in the above format
8662 * @param settings Object - attributes include:
8663 * shortYearCutoff number - the cutoff year for determining the century (optional)
8664 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8665 * dayNames string[7] - names of the days from Sunday (optional)
8666 * monthNamesShort string[12] - abbreviated names of the months (optional)
8667 * monthNames string[12] - names of the months (optional)
8668 * @return Date - the extracted date value or null if value is blank
8669 */
8670 parseDate: function (format, value, settings) {
8671 if (format == null || value == null) {
8672 throw "Invalid arguments";
8673 }
8674
8675 value = (typeof value === "object" ? value.toString() : value + "");
8676 if (value === "") {
8677 return null;
8678 }
8679
8680 var iFormat, dim, extra,
8681 iValue = 0,
8682 shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
8683 shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
8684 new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
8685 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
8686 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
8687 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
8688 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
8689 year = -1,
8690 month = -1,
8691 day = -1,
8692 doy = -1,
8693 literal = false,
8694 date,
8695 // Check whether a format character is doubled
8696 lookAhead = function(match) {
8697 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
8698 if (matches) {
8699 iFormat++;
8700 }
8701 return matches;
8702 },
8703 // Extract a number from the string value
8704 getNumber = function(match) {
8705 var isDoubled = lookAhead(match),
8706 size = (match === "@" ? 14 : (match === "!" ? 20 :
8707 (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
8708 digits = new RegExp("^\\d{1," + size + "}"),
8709 num = value.substring(iValue).match(digits);
8710 if (!num) {
8711 throw "Missing number at position " + iValue;
8712 }
8713 iValue += num[0].length;
8714 return parseInt(num[0], 10);
8715 },
8716 // Extract a name from the string value and convert to an index
8717 getName = function(match, shortNames, longNames) {
8718 var index = -1,
8719 names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
8720 return [ [k, v] ];
8721 }).sort(function (a, b) {
8722 return -(a[1].length - b[1].length);
8723 });
8724
8725 $.each(names, function (i, pair) {
8726 var name = pair[1];
8727 if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
8728 index = pair[0];
8729 iValue += name.length;
8730 return false;
8731 }
8732 });
8733 if (index !== -1) {
8734 return index + 1;
8735 } else {
8736 throw "Unknown name at position " + iValue;
8737 }
8738 },
8739 // Confirm that a literal character matches the string value
8740 checkLiteral = function() {
8741 if (value.charAt(iValue) !== format.charAt(iFormat)) {
8742 throw "Unexpected literal at position " + iValue;
8743 }
8744 iValue++;
8745 };
8746
8747 for (iFormat = 0; iFormat < format.length; iFormat++) {
8748 if (literal) {
8749 if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
8750 literal = false;
8751 } else {
8752 checkLiteral();
8753 }
8754 } else {
8755 switch (format.charAt(iFormat)) {
8756 case "d":
8757 day = getNumber("d");
8758 break;
8759 case "D":
8760 getName("D", dayNamesShort, dayNames);
8761 break;
8762 case "o":
8763 doy = getNumber("o");
8764 break;
8765 case "m":
8766 month = getNumber("m");
8767 break;
8768 case "M":
8769 month = getName("M", monthNamesShort, monthNames);
8770 break;
8771 case "y":
8772 year = getNumber("y");
8773 break;
8774 case "@":
8775 date = new Date(getNumber("@"));
8776 year = date.getFullYear();
8777 month = date.getMonth() + 1;
8778 day = date.getDate();
8779 break;
8780 case "!":
8781 date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
8782 year = date.getFullYear();
8783 month = date.getMonth() + 1;
8784 day = date.getDate();
8785 break;
8786 case "'":
8787 if (lookAhead("'")){
8788 checkLiteral();
8789 } else {
8790 literal = true;
8791 }
8792 break;
8793 default:
8794 checkLiteral();
8795 }
8796 }
8797 }
8798
8799 if (iValue < value.length){
8800 extra = value.substr(iValue);
8801 if (!/^\s+/.test(extra)) {
8802 throw "Extra/unparsed characters found in date: " + extra;
8803 }
8804 }
8805
8806 if (year === -1) {
8807 year = new Date().getFullYear();
8808 } else if (year < 100) {
8809 year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8810 (year <= shortYearCutoff ? 0 : -100);
8811 }
8812
8813 if (doy > -1) {
8814 month = 1;
8815 day = doy;
8816 do {
8817 dim = this._getDaysInMonth(year, month - 1);
8818 if (day <= dim) {
8819 break;
8820 }
8821 month++;
8822 day -= dim;
8823 } while (true);
8824 }
8825
8826 date = this._daylightSavingAdjust(new Date(year, month - 1, day));
8827 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
8828 throw "Invalid date"; // E.g. 31/02/00
8829 }
8830 return date;
8831 },
8832
8833 /* Standard date formats. */
8834 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
8835 COOKIE: "D, dd M yy",
8836 ISO_8601: "yy-mm-dd",
8837 RFC_822: "D, d M y",
8838 RFC_850: "DD, dd-M-y",
8839 RFC_1036: "D, d M y",
8840 RFC_1123: "D, d M yy",
8841 RFC_2822: "D, d M yy",
8842 RSS: "D, d M y", // RFC 822
8843 TICKS: "!",
8844 TIMESTAMP: "@",
8845 W3C: "yy-mm-dd", // ISO 8601
8846
8847 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
8848 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
8849
8850 /* Format a date object into a string value.
8851 * The format can be combinations of the following:
8852 * d - day of month (no leading zero)
8853 * dd - day of month (two digit)
8854 * o - day of year (no leading zeros)
8855 * oo - day of year (three digit)
8856 * D - day name short
8857 * DD - day name long
8858 * m - month of year (no leading zero)
8859 * mm - month of year (two digit)
8860 * M - month name short
8861 * MM - month name long
8862 * y - year (two digit)
8863 * yy - year (four digit)
8864 * @ - Unix timestamp (ms since 01/01/1970)
8865 * ! - Windows ticks (100ns since 01/01/0001)
8866 * "..." - literal text
8867 * '' - single quote
8868 *
8869 * @param format string - the desired format of the date
8870 * @param date Date - the date value to format
8871 * @param settings Object - attributes include:
8872 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8873 * dayNames string[7] - names of the days from Sunday (optional)
8874 * monthNamesShort string[12] - abbreviated names of the months (optional)
8875 * monthNames string[12] - names of the months (optional)
8876 * @return string - the date in the above format
8877 */
8878 formatDate: function (format, date, settings) {
8879 if (!date) {
8880 return "";
8881 }
8882
8883 var iFormat,
8884 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
8885 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
8886 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
8887 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
8888 // Check whether a format character is doubled
8889 lookAhead = function(match) {
8890 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
8891 if (matches) {
8892 iFormat++;
8893 }
8894 return matches;
8895 },
8896 // Format a number, with leading zero if necessary
8897 formatNumber = function(match, value, len) {
8898 var num = "" + value;
8899 if (lookAhead(match)) {
8900 while (num.length < len) {
8901 num = "0" + num;
8902 }
8903 }
8904 return num;
8905 },
8906 // Format a name, short or long as requested
8907 formatName = function(match, value, shortNames, longNames) {
8908 return (lookAhead(match) ? longNames[value] : shortNames[value]);
8909 },
8910 output = "",
8911 literal = false;
8912
8913 if (date) {
8914 for (iFormat = 0; iFormat < format.length; iFormat++) {
8915 if (literal) {
8916 if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
8917 literal = false;
8918 } else {
8919 output += format.charAt(iFormat);
8920 }
8921 } else {
8922 switch (format.charAt(iFormat)) {
8923 case "d":
8924 output += formatNumber("d", date.getDate(), 2);
8925 break;
8926 case "D":
8927 output += formatName("D", date.getDay(), dayNamesShort, dayNames);
8928 break;
8929 case "o":
8930 output += formatNumber("o",
8931 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
8932 break;
8933 case "m":
8934 output += formatNumber("m", date.getMonth() + 1, 2);
8935 break;
8936 case "M":
8937 output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
8938 break;
8939 case "y":
8940 output += (lookAhead("y") ? date.getFullYear() :
8941 (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
8942 break;
8943 case "@":
8944 output += date.getTime();
8945 break;
8946 case "!":
8947 output += date.getTime() * 10000 + this._ticksTo1970;
8948 break;
8949 case "'":
8950 if (lookAhead("'")) {
8951 output += "'";
8952 } else {
8953 literal = true;
8954 }
8955 break;
8956 default:
8957 output += format.charAt(iFormat);
8958 }
8959 }
8960 }
8961 }
8962 return output;
8963 },
8964
8965 /* Extract all possible characters from the date format. */
8966 _possibleChars: function (format) {
8967 var iFormat,
8968 chars = "",
8969 literal = false,
8970 // Check whether a format character is doubled
8971 lookAhead = function(match) {
8972 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
8973 if (matches) {
8974 iFormat++;
8975 }
8976 return matches;
8977 };
8978
8979 for (iFormat = 0; iFormat < format.length; iFormat++) {
8980 if (literal) {
8981 if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
8982 literal = false;
8983 } else {
8984 chars += format.charAt(iFormat);
8985 }
8986 } else {
8987 switch (format.charAt(iFormat)) {
8988 case "d": case "m": case "y": case "@":
8989 chars += "0123456789";
8990 break;
8991 case "D": case "M":
8992 return null; // Accept anything
8993 case "'":
8994 if (lookAhead("'")) {
8995 chars += "'";
8996 } else {
8997 literal = true;
8998 }
8999 break;
9000 default:
9001 chars += format.charAt(iFormat);
9002 }
9003 }
9004 }
9005 return chars;
9006 },
9007
9008 /* Get a setting value, defaulting if necessary. */
9009 _get: function(inst, name) {
9010 return inst.settings[name] !== undefined ?
9011 inst.settings[name] : this._defaults[name];
9012 },
9013
9014 /* Parse existing date and initialise date picker. */
9015 _setDateFromField: function(inst, noDefault) {
9016 if (inst.input.val() === inst.lastVal) {
9017 return;
9018 }
9019
9020 var dateFormat = this._get(inst, "dateFormat"),
9021 dates = inst.lastVal = inst.input ? inst.input.val() : null,
9022 defaultDate = this._getDefaultDate(inst),
9023 date = defaultDate,
9024 settings = this._getFormatConfig(inst);
9025
9026 try {
9027 date = this.parseDate(dateFormat, dates, settings) || defaultDate;
9028 } catch (event) {
9029 dates = (noDefault ? "" : dates);
9030 }
9031 inst.selectedDay = date.getDate();
9032 inst.drawMonth = inst.selectedMonth = date.getMonth();
9033 inst.drawYear = inst.selectedYear = date.getFullYear();
9034 inst.currentDay = (dates ? date.getDate() : 0);
9035 inst.currentMonth = (dates ? date.getMonth() : 0);
9036 inst.currentYear = (dates ? date.getFullYear() : 0);
9037 this._adjustInstDate(inst);
9038 },
9039
9040 /* Retrieve the default date shown on opening. */
9041 _getDefaultDate: function(inst) {
9042 return this._restrictMinMax(inst,
9043 this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
9044 },
9045
9046 /* A date may be specified as an exact value or a relative one. */
9047 _determineDate: function(inst, date, defaultDate) {
9048 var offsetNumeric = function(offset) {
9049 var date = new Date();
9050 date.setDate(date.getDate() + offset);
9051 return date;
9052 },
9053 offsetString = function(offset) {
9054 try {
9055 return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
9056 offset, $.datepicker._getFormatConfig(inst));
9057 }
9058 catch (e) {
9059 // Ignore
9060 }
9061
9062 var date = (offset.toLowerCase().match(/^c/) ?
9063 $.datepicker._getDate(inst) : null) || new Date(),
9064 year = date.getFullYear(),
9065 month = date.getMonth(),
9066 day = date.getDate(),
9067 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
9068 matches = pattern.exec(offset);
9069
9070 while (matches) {
9071 switch (matches[2] || "d") {
9072 case "d" : case "D" :
9073 day += parseInt(matches[1],10); break;
9074 case "w" : case "W" :
9075 day += parseInt(matches[1],10) * 7; break;
9076 case "m" : case "M" :
9077 month += parseInt(matches[1],10);
9078 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9079 break;
9080 case "y": case "Y" :
9081 year += parseInt(matches[1],10);
9082 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
9083 break;
9084 }
9085 matches = pattern.exec(offset);
9086 }
9087 return new Date(year, month, day);
9088 },
9089 newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
9090 (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
9091
9092 newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
9093 if (newDate) {
9094 newDate.setHours(0);
9095 newDate.setMinutes(0);
9096 newDate.setSeconds(0);
9097 newDate.setMilliseconds(0);
9098 }
9099 return this._daylightSavingAdjust(newDate);
9100 },
9101
9102 /* Handle switch to/from daylight saving.
9103 * Hours may be non-zero on daylight saving cut-over:
9104 * > 12 when midnight changeover, but then cannot generate
9105 * midnight datetime, so jump to 1AM, otherwise reset.
9106 * @param date (Date) the date to check
9107 * @return (Date) the corrected date
9108 */
9109 _daylightSavingAdjust: function(date) {
9110 if (!date) {
9111 return null;
9112 }
9113 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
9114 return date;
9115 },
9116
9117 /* Set the date(s) directly. */
9118 _setDate: function(inst, date, noChange) {
9119 var clear = !date,
9120 origMonth = inst.selectedMonth,
9121 origYear = inst.selectedYear,
9122 newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
9123
9124 inst.selectedDay = inst.currentDay = newDate.getDate();
9125 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
9126 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
9127 if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
9128 this._notifyChange(inst);
9129 }
9130 this._adjustInstDate(inst);
9131 if (inst.input) {
9132 inst.input.val(clear ? "" : this._formatDate(inst));
9133 }
9134 },
9135
9136 /* Retrieve the date(s) directly. */
9137 _getDate: function(inst) {
9138 var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
9139 this._daylightSavingAdjust(new Date(
9140 inst.currentYear, inst.currentMonth, inst.currentDay)));
9141 return startDate;
9142 },
9143
9144 /* Attach the onxxx handlers. These are declared statically so
9145 * they work with static code transformers like Caja.
9146 */
9147 _attachHandlers: function(inst) {
9148 var stepMonths = this._get(inst, "stepMonths"),
9149 id = "#" + inst.id.replace( /\\\\/g, "\\" );
9150 inst.dpDiv.find("[data-handler]").map(function () {
9151 var handler = {
9152 prev: function () {
9153 $.datepicker._adjustDate(id, -stepMonths, "M");
9154 },
9155 next: function () {
9156 $.datepicker._adjustDate(id, +stepMonths, "M");
9157 },
9158 hide: function () {
9159 $.datepicker._hideDatepicker();
9160 },
9161 today: function () {
9162 $.datepicker._gotoToday(id);
9163 },
9164 selectDay: function () {
9165 $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
9166 return false;
9167 },
9168 selectMonth: function () {
9169 $.datepicker._selectMonthYear(id, this, "M");
9170 return false;
9171 },
9172 selectYear: function () {
9173 $.datepicker._selectMonthYear(id, this, "Y");
9174 return false;
9175 }
9176 };
9177 $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
9178 });
9179 },
9180
9181 /* Generate the HTML for the current state of the date picker. */
9182 _generateHTML: function(inst) {
9183 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
9184 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
9185 monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
9186 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
9187 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
9188 printDate, dRow, tbody, daySettings, otherMonth, unselectable,
9189 tempDate = new Date(),
9190 today = this._daylightSavingAdjust(
9191 new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
9192 isRTL = this._get(inst, "isRTL"),
9193 showButtonPanel = this._get(inst, "showButtonPanel"),
9194 hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
9195 navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
9196 numMonths = this._getNumberOfMonths(inst),
9197 showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
9198 stepMonths = this._get(inst, "stepMonths"),
9199 isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
9200 currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
9201 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
9202 minDate = this._getMinMaxDate(inst, "min"),
9203 maxDate = this._getMinMaxDate(inst, "max"),
9204 drawMonth = inst.drawMonth - showCurrentAtPos,
9205 drawYear = inst.drawYear;
9206
9207 if (drawMonth < 0) {
9208 drawMonth += 12;
9209 drawYear--;
9210 }
9211 if (maxDate) {
9212 maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
9213 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
9214 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
9215 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
9216 drawMonth--;
9217 if (drawMonth < 0) {
9218 drawMonth = 11;
9219 drawYear--;
9220 }
9221 }
9222 }
9223 inst.drawMonth = drawMonth;
9224 inst.drawYear = drawYear;
9225
9226 prevText = this._get(inst, "prevText");
9227 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
9228 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
9229 this._getFormatConfig(inst)));
9230
9231 prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
9232 "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
9233 " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
9234 (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>"));
9235
9236 nextText = this._get(inst, "nextText");
9237 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
9238 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
9239 this._getFormatConfig(inst)));
9240
9241 next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
9242 "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
9243 " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
9244 (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>"));
9245
9246 currentText = this._get(inst, "currentText");
9247 gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
9248 currentText = (!navigationAsDateFormat ? currentText :
9249 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
9250
9251 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'>" +
9252 this._get(inst, "closeText") + "</button>" : "");
9253
9254 buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
9255 (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'" +
9256 ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
9257
9258 firstDay = parseInt(this._get(inst, "firstDay"),10);
9259 firstDay = (isNaN(firstDay) ? 0 : firstDay);
9260
9261 showWeek = this._get(inst, "showWeek");
9262 dayNames = this._get(inst, "dayNames");
9263 dayNamesMin = this._get(inst, "dayNamesMin");
9264 monthNames = this._get(inst, "monthNames");
9265 monthNamesShort = this._get(inst, "monthNamesShort");
9266 beforeShowDay = this._get(inst, "beforeShowDay");
9267 showOtherMonths = this._get(inst, "showOtherMonths");
9268 selectOtherMonths = this._get(inst, "selectOtherMonths");
9269 defaultDate = this._getDefaultDate(inst);
9270 html = "";
9271 dow;
9272 for (row = 0; row < numMonths[0]; row++) {
9273 group = "";
9274 this.maxRows = 4;
9275 for (col = 0; col < numMonths[1]; col++) {
9276 selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
9277 cornerClass = " ui-corner-all";
9278 calender = "";
9279 if (isMultiMonth) {
9280 calender += "<div class='ui-datepicker-group";
9281 if (numMonths[1] > 1) {
9282 switch (col) {
9283 case 0: calender += " ui-datepicker-group-first";
9284 cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
9285 case numMonths[1]-1: calender += " ui-datepicker-group-last";
9286 cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
9287 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
9288 }
9289 }
9290 calender += "'>";
9291 }
9292 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
9293 (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
9294 (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
9295 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
9296 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
9297 "</div><table class='ui-datepicker-calendar'><thead>" +
9298 "<tr>";
9299 thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
9300 for (dow = 0; dow < 7; dow++) { // days of the week
9301 day = (dow + firstDay) % 7;
9302 thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
9303 "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
9304 }
9305 calender += thead + "</tr></thead><tbody>";
9306 daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
9307 if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
9308 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
9309 }
9310 leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
9311 curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
9312 numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
9313 this.maxRows = numRows;
9314 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
9315 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
9316 calender += "<tr>";
9317 tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
9318 this._get(inst, "calculateWeek")(printDate) + "</td>");
9319 for (dow = 0; dow < 7; dow++) { // create date picker days
9320 daySettings = (beforeShowDay ?
9321 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
9322 otherMonth = (printDate.getMonth() !== drawMonth);
9323 unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
9324 (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
9325 tbody += "<td class='" +
9326 ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
9327 (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
9328 ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
9329 (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
9330 // or defaultDate is current printedDate and defaultDate is selectedDate
9331 " " + this._dayOverClass : "") + // highlight selected day
9332 (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days
9333 (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
9334 (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
9335 (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
9336 ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + // cell title
9337 (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
9338 (otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
9339 (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
9340 (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
9341 (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
9342 (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
9343 "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
9344 printDate.setDate(printDate.getDate() + 1);
9345 printDate = this._daylightSavingAdjust(printDate);
9346 }
9347 calender += tbody + "</tr>";
9348 }
9349 drawMonth++;
9350 if (drawMonth > 11) {
9351 drawMonth = 0;
9352 drawYear++;
9353 }
9354 calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
9355 ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
9356 group += calender;
9357 }
9358 html += group;
9359 }
9360 html += buttonPanel;
9361 inst._keyEvent = false;
9362 return html;
9363 },
9364
9365 /* Generate the month and year header. */
9366 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
9367 secondary, monthNames, monthNamesShort) {
9368
9369 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
9370 changeMonth = this._get(inst, "changeMonth"),
9371 changeYear = this._get(inst, "changeYear"),
9372 showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
9373 html = "<div class='ui-datepicker-title'>",
9374 monthHtml = "";
9375
9376 // month selection
9377 if (secondary || !changeMonth) {
9378 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
9379 } else {
9380 inMinYear = (minDate && minDate.getFullYear() === drawYear);
9381 inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
9382 monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
9383 for ( month = 0; month < 12; month++) {
9384 if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
9385 monthHtml += "<option value='" + month + "'" +
9386 (month === drawMonth ? " selected='selected'" : "") +
9387 ">" + monthNamesShort[month] + "</option>";
9388 }
9389 }
9390 monthHtml += "</select>";
9391 }
9392
9393 if (!showMonthAfterYear) {
9394 html += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");
9395 }
9396
9397 // year selection
9398 if ( !inst.yearshtml ) {
9399 inst.yearshtml = "";
9400 if (secondary || !changeYear) {
9401 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
9402 } else {
9403 // determine range of years to display
9404 years = this._get(inst, "yearRange").split(":");
9405 thisYear = new Date().getFullYear();
9406 determineYear = function(value) {
9407 var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
9408 (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
9409 parseInt(value, 10)));
9410 return (isNaN(year) ? thisYear : year);
9411 };
9412 year = determineYear(years[0]);
9413 endYear = Math.max(year, determineYear(years[1] || ""));
9414 year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
9415 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
9416 inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
9417 for (; year <= endYear; year++) {
9418 inst.yearshtml += "<option value='" + year + "'" +
9419 (year === drawYear ? " selected='selected'" : "") +
9420 ">" + year + "</option>";
9421 }
9422 inst.yearshtml += "</select>";
9423
9424 html += inst.yearshtml;
9425 inst.yearshtml = null;
9426 }
9427 }
9428
9429 html += this._get(inst, "yearSuffix");
9430 if (showMonthAfterYear) {
9431 html += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;
9432 }
9433 html += "</div>"; // Close datepicker_header
9434 return html;
9435 },
9436
9437 /* Adjust one of the date sub-fields. */
9438 _adjustInstDate: function(inst, offset, period) {
9439 var year = inst.drawYear + (period === "Y" ? offset : 0),
9440 month = inst.drawMonth + (period === "M" ? offset : 0),
9441 day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
9442 date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
9443
9444 inst.selectedDay = date.getDate();
9445 inst.drawMonth = inst.selectedMonth = date.getMonth();
9446 inst.drawYear = inst.selectedYear = date.getFullYear();
9447 if (period === "M" || period === "Y") {
9448 this._notifyChange(inst);
9449 }
9450 },
9451
9452 /* Ensure a date is within any min/max bounds. */
9453 _restrictMinMax: function(inst, date) {
9454 var minDate = this._getMinMaxDate(inst, "min"),
9455 maxDate = this._getMinMaxDate(inst, "max"),
9456 newDate = (minDate && date < minDate ? minDate : date);
9457 return (maxDate && newDate > maxDate ? maxDate : newDate);
9458 },
9459
9460 /* Notify change of month/year. */
9461 _notifyChange: function(inst) {
9462 var onChange = this._get(inst, "onChangeMonthYear");
9463 if (onChange) {
9464 onChange.apply((inst.input ? inst.input[0] : null),
9465 [inst.selectedYear, inst.selectedMonth + 1, inst]);
9466 }
9467 },
9468
9469 /* Determine the number of months to show. */
9470 _getNumberOfMonths: function(inst) {
9471 var numMonths = this._get(inst, "numberOfMonths");
9472 return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
9473 },
9474
9475 /* Determine the current maximum date - ensure no time components are set. */
9476 _getMinMaxDate: function(inst, minMax) {
9477 return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
9478 },
9479
9480 /* Find the number of days in a given month. */
9481 _getDaysInMonth: function(year, month) {
9482 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
9483 },
9484
9485 /* Find the day of the week of the first of a month. */
9486 _getFirstDayOfMonth: function(year, month) {
9487 return new Date(year, month, 1).getDay();
9488 },
9489
9490 /* Determines if we should allow a "next/prev" month display change. */
9491 _canAdjustMonth: function(inst, offset, curYear, curMonth) {
9492 var numMonths = this._getNumberOfMonths(inst),
9493 date = this._daylightSavingAdjust(new Date(curYear,
9494 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
9495
9496 if (offset < 0) {
9497 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
9498 }
9499 return this._isInRange(inst, date);
9500 },
9501
9502 /* Is the given date in the accepted range? */
9503 _isInRange: function(inst, date) {
9504 var yearSplit, currentYear,
9505 minDate = this._getMinMaxDate(inst, "min"),
9506 maxDate = this._getMinMaxDate(inst, "max"),
9507 minYear = null,
9508 maxYear = null,
9509 years = this._get(inst, "yearRange");
9510 if (years){
9511 yearSplit = years.split(":");
9512 currentYear = new Date().getFullYear();
9513 minYear = parseInt(yearSplit[0], 10);
9514 maxYear = parseInt(yearSplit[1], 10);
9515 if ( yearSplit[0].match(/[+\-].*/) ) {
9516 minYear += currentYear;
9517 }
9518 if ( yearSplit[1].match(/[+\-].*/) ) {
9519 maxYear += currentYear;
9520 }
9521 }
9522
9523 return ((!minDate || date.getTime() >= minDate.getTime()) &&
9524 (!maxDate || date.getTime() <= maxDate.getTime()) &&
9525 (!minYear || date.getFullYear() >= minYear) &&
9526 (!maxYear || date.getFullYear() <= maxYear));
9527 },
9528
9529 /* Provide the configuration settings for formatting/parsing. */
9530 _getFormatConfig: function(inst) {
9531 var shortYearCutoff = this._get(inst, "shortYearCutoff");
9532 shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
9533 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
9534 return {shortYearCutoff: shortYearCutoff,
9535 dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
9536 monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
9537 },
9538
9539 /* Format the given date for display. */
9540 _formatDate: function(inst, day, month, year) {
9541 if (!day) {
9542 inst.currentDay = inst.selectedDay;
9543 inst.currentMonth = inst.selectedMonth;
9544 inst.currentYear = inst.selectedYear;
9545 }
9546 var date = (day ? (typeof day === "object" ? day :
9547 this._daylightSavingAdjust(new Date(year, month, day))) :
9548 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9549 return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
9550 }
9551});
9552
9553/*
9554 * Bind hover events for datepicker elements.
9555 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9556 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9557 */
9558function bindHover(dpDiv) {
9559 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
9560 return dpDiv.delegate(selector, "mouseout", function() {
9561 $(this).removeClass("ui-state-hover");
9562 if (this.className.indexOf("ui-datepicker-prev") !== -1) {
9563 $(this).removeClass("ui-datepicker-prev-hover");
9564 }
9565 if (this.className.indexOf("ui-datepicker-next") !== -1) {
9566 $(this).removeClass("ui-datepicker-next-hover");
9567 }
9568 })
9569 .delegate(selector, "mouseover", function(){
9570 if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
9571 $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
9572 $(this).addClass("ui-state-hover");
9573 if (this.className.indexOf("ui-datepicker-prev") !== -1) {
9574 $(this).addClass("ui-datepicker-prev-hover");
9575 }
9576 if (this.className.indexOf("ui-datepicker-next") !== -1) {
9577 $(this).addClass("ui-datepicker-next-hover");
9578 }
9579 }
9580 });
9581}
9582
9583/* jQuery extend now ignores nulls! */
9584function extendRemove(target, props) {
9585 $.extend(target, props);
9586 for (var name in props) {
9587 if (props[name] == null) {
9588 target[name] = props[name];
9589 }
9590 }
9591 return target;
9592}
9593
9594/* Invoke the datepicker functionality.
9595 @param options string - a command, optionally followed by additional parameters or
9596 Object - settings for attaching new datepicker functionality
9597 @return jQuery object */
9598$.fn.datepicker = function(options){
9599
9600 /* Verify an empty collection wasn't passed - Fixes #6976 */
9601 if ( !this.length ) {
9602 return this;
9603 }
9604
9605 /* Initialise the date picker. */
9606 if (!$.datepicker.initialized) {
9607 $(document).mousedown($.datepicker._checkExternalClick);
9608 $.datepicker.initialized = true;
9609 }
9610
9611 /* Append datepicker main container to body if not exist. */
9612 if ($("#"+$.datepicker._mainDivId).length === 0) {
9613 $("body").append($.datepicker.dpDiv);
9614 }
9615
9616 var otherArgs = Array.prototype.slice.call(arguments, 1);
9617 if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
9618 return $.datepicker["_" + options + "Datepicker"].
9619 apply($.datepicker, [this[0]].concat(otherArgs));
9620 }
9621 if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
9622 return $.datepicker["_" + options + "Datepicker"].
9623 apply($.datepicker, [this[0]].concat(otherArgs));
9624 }
9625 return this.each(function() {
9626 typeof options === "string" ?
9627 $.datepicker["_" + options + "Datepicker"].
9628 apply($.datepicker, [this].concat(otherArgs)) :
9629 $.datepicker._attachDatepicker(this, options);
9630 });
9631};
9632
9633$.datepicker = new Datepicker(); // singleton instance
9634$.datepicker.initialized = false;
9635$.datepicker.uuid = new Date().getTime();
9636$.datepicker.version = "1.10.3";
9637
9638})(jQuery);
9639
9640(function( $, undefined ) {
9641
9642var sizeRelatedOptions = {
9643 buttons: true,
9644 height: true,
9645 maxHeight: true,
9646 maxWidth: true,
9647 minHeight: true,
9648 minWidth: true,
9649 width: true
9650 },
9651 resizableRelatedOptions = {
9652 maxHeight: true,
9653 maxWidth: true,
9654 minHeight: true,
9655 minWidth: true
9656 };
9657
9658$.widget( "ui.dialog", {
9659 version: "1.10.3",
9660 options: {
9661 appendTo: "body",
9662 autoOpen: true,
9663 buttons: [],
9664 closeOnEscape: true,
9665 closeText: "close",
9666 dialogClass: "",
9667 draggable: true,
9668 hide: null,
9669 height: "auto",
9670 maxHeight: null,
9671 maxWidth: null,
9672 minHeight: 150,
9673 minWidth: 150,
9674 modal: false,
9675 position: {
9676 my: "center",
9677 at: "center",
9678 of: window,
9679 collision: "fit",
9680 // Ensure the titlebar is always visible
9681 using: function( pos ) {
9682 var topOffset = $( this ).css( pos ).offset().top;
9683 if ( topOffset < 0 ) {
9684 $( this ).css( "top", pos.top - topOffset );
9685 }
9686 }
9687 },
9688 resizable: true,
9689 show: null,
9690 title: null,
9691 width: 300,
9692
9693 // callbacks
9694 beforeClose: null,
9695 close: null,
9696 drag: null,
9697 dragStart: null,
9698 dragStop: null,
9699 focus: null,
9700 open: null,
9701 resize: null,
9702 resizeStart: null,
9703 resizeStop: null
9704 },
9705
9706 _create: function() {
9707 this.originalCss = {
9708 display: this.element[0].style.display,
9709 width: this.element[0].style.width,
9710 minHeight: this.element[0].style.minHeight,
9711 maxHeight: this.element[0].style.maxHeight,
9712 height: this.element[0].style.height
9713 };
9714 this.originalPosition = {
9715 parent: this.element.parent(),
9716 index: this.element.parent().children().index( this.element )
9717 };
9718 this.originalTitle = this.element.attr("title");
9719 this.options.title = this.options.title || this.originalTitle;
9720
9721 this._createWrapper();
9722
9723 this.element
9724 .show()
9725 .removeAttr("title")
9726 .addClass("ui-dialog-content ui-widget-content")
9727 .appendTo( this.uiDialog );
9728
9729 this._createTitlebar();
9730 this._createButtonPane();
9731
9732 if ( this.options.draggable && $.fn.draggable ) {
9733 this._makeDraggable();
9734 }
9735 if ( this.options.resizable && $.fn.resizable ) {
9736 this._makeResizable();
9737 }
9738
9739 this._isOpen = false;
9740 },
9741
9742 _init: function() {
9743 if ( this.options.autoOpen ) {
9744 this.open();
9745 }
9746 },
9747
9748 _appendTo: function() {
9749 var element = this.options.appendTo;
9750 if ( element && (element.jquery || element.nodeType) ) {
9751 return $( element );
9752 }
9753 return this.document.find( element || "body" ).eq( 0 );
9754 },
9755
9756 _destroy: function() {
9757 var next,
9758 originalPosition = this.originalPosition;
9759
9760 this._destroyOverlay();
9761
9762 this.element
9763 .removeUniqueId()
9764 .removeClass("ui-dialog-content ui-widget-content")
9765 .css( this.originalCss )
9766 // Without detaching first, the following becomes really slow
9767 .detach();
9768
9769 this.uiDialog.stop( true, true ).remove();
9770
9771 if ( this.originalTitle ) {
9772 this.element.attr( "title", this.originalTitle );
9773 }
9774
9775 next = originalPosition.parent.children().eq( originalPosition.index );
9776 // Don't try to place the dialog next to itself (#8613)
9777 if ( next.length && next[0] !== this.element[0] ) {
9778 next.before( this.element );
9779 } else {
9780 originalPosition.parent.append( this.element );
9781 }
9782 },
9783
9784 widget: function() {
9785 return this.uiDialog;
9786 },
9787
9788 disable: $.noop,
9789 enable: $.noop,
9790
9791 close: function( event ) {
9792 var that = this;
9793
9794 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
9795 return;
9796 }
9797
9798 this._isOpen = false;
9799 this._destroyOverlay();
9800
9801 if ( !this.opener.filter(":focusable").focus().length ) {
9802 // Hiding a focused element doesn't trigger blur in WebKit
9803 // so in case we have nothing to focus on, explicitly blur the active element
9804 // https://bugs.webkit.org/show_bug.cgi?id=47182
9805 $( this.document[0].activeElement ).blur();
9806 }
9807
9808 this._hide( this.uiDialog, this.options.hide, function() {
9809 that._trigger( "close", event );
9810 });
9811 },
9812
9813 isOpen: function() {
9814 return this._isOpen;
9815 },
9816
9817 moveToTop: function() {
9818 this._moveToTop();
9819 },
9820
9821 _moveToTop: function( event, silent ) {
9822 var moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length;
9823 if ( moved && !silent ) {
9824 this._trigger( "focus", event );
9825 }
9826 return moved;
9827 },
9828
9829 open: function() {
9830 var that = this;
9831 if ( this._isOpen ) {
9832 if ( this._moveToTop() ) {
9833 this._focusTabbable();
9834 }
9835 return;
9836 }
9837
9838 this._isOpen = true;
9839 this.opener = $( this.document[0].activeElement );
9840
9841 this._size();
9842 this._position();
9843 this._createOverlay();
9844 this._moveToTop( null, true );
9845 this._show( this.uiDialog, this.options.show, function() {
9846 that._focusTabbable();
9847 that._trigger("focus");
9848 });
9849
9850 this._trigger("open");
9851 },
9852
9853 _focusTabbable: function() {
9854 // Set focus to the first match:
9855 // 1. First element inside the dialog matching [autofocus]
9856 // 2. Tabbable element inside the content element
9857 // 3. Tabbable element inside the buttonpane
9858 // 4. The close button
9859 // 5. The dialog itself
9860 var hasFocus = this.element.find("[autofocus]");
9861 if ( !hasFocus.length ) {
9862 hasFocus = this.element.find(":tabbable");
9863 }
9864 if ( !hasFocus.length ) {
9865 hasFocus = this.uiDialogButtonPane.find(":tabbable");
9866 }
9867 if ( !hasFocus.length ) {
9868 hasFocus = this.uiDialogTitlebarClose.filter(":tabbable");
9869 }
9870 if ( !hasFocus.length ) {
9871 hasFocus = this.uiDialog;
9872 }
9873 hasFocus.eq( 0 ).focus();
9874 },
9875
9876 _keepFocus: function( event ) {
9877 function checkFocus() {
9878 var activeElement = this.document[0].activeElement,
9879 isActive = this.uiDialog[0] === activeElement ||
9880 $.contains( this.uiDialog[0], activeElement );
9881 if ( !isActive ) {
9882 this._focusTabbable();
9883 }
9884 }
9885 event.preventDefault();
9886 checkFocus.call( this );
9887 // support: IE
9888 // IE <= 8 doesn't prevent moving focus even with event.preventDefault()
9889 // so we check again later
9890 this._delay( checkFocus );
9891 },
9892
9893 _createWrapper: function() {
9894 this.uiDialog = $("<div>")
9895 .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
9896 this.options.dialogClass )
9897 .hide()
9898 .attr({
9899 // Setting tabIndex makes the div focusable
9900 tabIndex: -1,
9901 role: "dialog"
9902 })
9903 .appendTo( this._appendTo() );
9904
9905 this._on( this.uiDialog, {
9906 keydown: function( event ) {
9907 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
9908 event.keyCode === $.ui.keyCode.ESCAPE ) {
9909 event.preventDefault();
9910 this.close( event );
9911 return;
9912 }
9913
9914 // prevent tabbing out of dialogs
9915 if ( event.keyCode !== $.ui.keyCode.TAB ) {
9916 return;
9917 }
9918 var tabbables = this.uiDialog.find(":tabbable"),
9919 first = tabbables.filter(":first"),
9920 last = tabbables.filter(":last");
9921
9922 if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
9923 first.focus( 1 );
9924 event.preventDefault();
9925 } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
9926 last.focus( 1 );
9927 event.preventDefault();
9928 }
9929 },
9930 mousedown: function( event ) {
9931 if ( this._moveToTop( event ) ) {
9932 this._focusTabbable();
9933 }
9934 }
9935 });
9936
9937 // We assume that any existing aria-describedby attribute means
9938 // that the dialog content is marked up properly
9939 // otherwise we brute force the content as the description
9940 if ( !this.element.find("[aria-describedby]").length ) {
9941 this.uiDialog.attr({
9942 "aria-describedby": this.element.uniqueId().attr("id")
9943 });
9944 }
9945 },
9946
9947 _createTitlebar: function() {
9948 var uiDialogTitle;
9949
9950 this.uiDialogTitlebar = $("<div>")
9951 .addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix")
9952 .prependTo( this.uiDialog );
9953 this._on( this.uiDialogTitlebar, {
9954 mousedown: function( event ) {
9955 // Don't prevent click on close button (#8838)
9956 // Focusing a dialog that is partially scrolled out of view
9957 // causes the browser to scroll it into view, preventing the click event
9958 if ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) {
9959 // Dialog isn't getting focus when dragging (#8063)
9960 this.uiDialog.focus();
9961 }
9962 }
9963 });
9964
9965 this.uiDialogTitlebarClose = $("<button></button>")
9966 .button({
9967 label: this.options.closeText,
9968 icons: {
9969 primary: "ui-icon-closethick"
9970 },
9971 text: false
9972 })
9973 .addClass("ui-dialog-titlebar-close")
9974 .appendTo( this.uiDialogTitlebar );
9975 this._on( this.uiDialogTitlebarClose, {
9976 click: function( event ) {
9977 event.preventDefault();
9978 this.close( event );
9979 }
9980 });
9981
9982 uiDialogTitle = $("<span>")
9983 .uniqueId()
9984 .addClass("ui-dialog-title")
9985 .prependTo( this.uiDialogTitlebar );
9986 this._title( uiDialogTitle );
9987
9988 this.uiDialog.attr({
9989 "aria-labelledby": uiDialogTitle.attr("id")
9990 });
9991 },
9992
9993 _title: function( title ) {
9994 if ( !this.options.title ) {
9995 title.html("&#160;");
9996 }
9997 title.text( this.options.title );
9998 },
9999
10000 _createButtonPane: function() {
10001 this.uiDialogButtonPane = $("<div>")
10002 .addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");
10003
10004 this.uiButtonSet = $("<div>")
10005 .addClass("ui-dialog-buttonset")
10006 .appendTo( this.uiDialogButtonPane );
10007
10008 this._createButtons();
10009 },
10010
10011 _createButtons: function() {
10012 var that = this,
10013 buttons = this.options.buttons;
10014
10015 // if we already have a button pane, remove it
10016 this.uiDialogButtonPane.remove();
10017 this.uiButtonSet.empty();
10018
10019 if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {
10020 this.uiDialog.removeClass("ui-dialog-buttons");
10021 return;
10022 }
10023
10024 $.each( buttons, function( name, props ) {
10025 var click, buttonOptions;
10026 props = $.isFunction( props ) ?
10027 { click: props, text: name } :
10028 props;
10029 // Default to a non-submitting button
10030 props = $.extend( { type: "button" }, props );
10031 // Change the context for the click callback to be the main element
10032 click = props.click;
10033 props.click = function() {
10034 click.apply( that.element[0], arguments );
10035 };
10036 buttonOptions = {
10037 icons: props.icons,
10038 text: props.showText
10039 };
10040 delete props.icons;
10041 delete props.showText;
10042 $( "<button></button>", props )
10043 .button( buttonOptions )
10044 .appendTo( that.uiButtonSet );
10045 });
10046 this.uiDialog.addClass("ui-dialog-buttons");
10047 this.uiDialogButtonPane.appendTo( this.uiDialog );
10048 },
10049
10050 _makeDraggable: function() {
10051 var that = this,
10052 options = this.options;
10053
10054 function filteredUi( ui ) {
10055 return {
10056 position: ui.position,
10057 offset: ui.offset
10058 };
10059 }
10060
10061 this.uiDialog.draggable({
10062 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
10063 handle: ".ui-dialog-titlebar",
10064 containment: "document",
10065 start: function( event, ui ) {
10066 $( this ).addClass("ui-dialog-dragging");
10067 that._blockFrames();
10068 that._trigger( "dragStart", event, filteredUi( ui ) );
10069 },
10070 drag: function( event, ui ) {
10071 that._trigger( "drag", event, filteredUi( ui ) );
10072 },
10073 stop: function( event, ui ) {
10074 options.position = [
10075 ui.position.left - that.document.scrollLeft(),
10076 ui.position.top - that.document.scrollTop()
10077 ];
10078 $( this ).removeClass("ui-dialog-dragging");
10079 that._unblockFrames();
10080 that._trigger( "dragStop", event, filteredUi( ui ) );
10081 }
10082 });
10083 },
10084
10085 _makeResizable: function() {
10086 var that = this,
10087 options = this.options,
10088 handles = options.resizable,
10089 // .ui-resizable has position: relative defined in the stylesheet
10090 // but dialogs have to use absolute or fixed positioning
10091 position = this.uiDialog.css("position"),
10092 resizeHandles = typeof handles === "string" ?
10093 handles :
10094 "n,e,s,w,se,sw,ne,nw";
10095
10096 function filteredUi( ui ) {
10097 return {
10098 originalPosition: ui.originalPosition,
10099 originalSize: ui.originalSize,
10100 position: ui.position,
10101 size: ui.size
10102 };
10103 }
10104
10105 this.uiDialog.resizable({
10106 cancel: ".ui-dialog-content",
10107 containment: "document",
10108 alsoResize: this.element,
10109 maxWidth: options.maxWidth,
10110 maxHeight: options.maxHeight,
10111 minWidth: options.minWidth,
10112 minHeight: this._minHeight(),
10113 handles: resizeHandles,
10114 start: function( event, ui ) {
10115 $( this ).addClass("ui-dialog-resizing");
10116 that._blockFrames();
10117 that._trigger( "resizeStart", event, filteredUi( ui ) );
10118 },
10119 resize: function( event, ui ) {
10120 that._trigger( "resize", event, filteredUi( ui ) );
10121 },
10122 stop: function( event, ui ) {
10123 options.height = $( this ).height();
10124 options.width = $( this ).width();
10125 $( this ).removeClass("ui-dialog-resizing");
10126 that._unblockFrames();
10127 that._trigger( "resizeStop", event, filteredUi( ui ) );
10128 }
10129 })
10130 .css( "position", position );
10131 },
10132
10133 _minHeight: function() {
10134 var options = this.options;
10135
10136 return options.height === "auto" ?
10137 options.minHeight :
10138 Math.min( options.minHeight, options.height );
10139 },
10140
10141 _position: function() {
10142 // Need to show the dialog to get the actual offset in the position plugin
10143 var isVisible = this.uiDialog.is(":visible");
10144 if ( !isVisible ) {
10145 this.uiDialog.show();
10146 }
10147 this.uiDialog.position( this.options.position );
10148 if ( !isVisible ) {
10149 this.uiDialog.hide();
10150 }
10151 },
10152
10153 _setOptions: function( options ) {
10154 var that = this,
10155 resize = false,
10156 resizableOptions = {};
10157
10158 $.each( options, function( key, value ) {
10159 that._setOption( key, value );
10160
10161 if ( key in sizeRelatedOptions ) {
10162 resize = true;
10163 }
10164 if ( key in resizableRelatedOptions ) {
10165 resizableOptions[ key ] = value;
10166 }
10167 });
10168
10169 if ( resize ) {
10170 this._size();
10171 this._position();
10172 }
10173 if ( this.uiDialog.is(":data(ui-resizable)") ) {
10174 this.uiDialog.resizable( "option", resizableOptions );
10175 }
10176 },
10177
10178 _setOption: function( key, value ) {
10179 /*jshint maxcomplexity:15*/
10180 var isDraggable, isResizable,
10181 uiDialog = this.uiDialog;
10182
10183 if ( key === "dialogClass" ) {
10184 uiDialog
10185 .removeClass( this.options.dialogClass )
10186 .addClass( value );
10187 }
10188
10189 if ( key === "disabled" ) {
10190 return;
10191 }
10192
10193 this._super( key, value );
10194
10195 if ( key === "appendTo" ) {
10196 this.uiDialog.appendTo( this._appendTo() );
10197 }
10198
10199 if ( key === "buttons" ) {
10200 this._createButtons();
10201 }
10202
10203 if ( key === "closeText" ) {
10204 this.uiDialogTitlebarClose.button({
10205 // Ensure that we always pass a string
10206 label: "" + value
10207 });
10208 }
10209
10210 if ( key === "draggable" ) {
10211 isDraggable = uiDialog.is(":data(ui-draggable)");
10212 if ( isDraggable && !value ) {
10213 uiDialog.draggable("destroy");
10214 }
10215
10216 if ( !isDraggable && value ) {
10217 this._makeDraggable();
10218 }
10219 }
10220
10221 if ( key === "position" ) {
10222 this._position();
10223 }
10224
10225 if ( key === "resizable" ) {
10226 // currently resizable, becoming non-resizable
10227 isResizable = uiDialog.is(":data(ui-resizable)");
10228 if ( isResizable && !value ) {
10229 uiDialog.resizable("destroy");
10230 }
10231
10232 // currently resizable, changing handles
10233 if ( isResizable && typeof value === "string" ) {
10234 uiDialog.resizable( "option", "handles", value );
10235 }
10236
10237 // currently non-resizable, becoming resizable
10238 if ( !isResizable && value !== false ) {
10239 this._makeResizable();
10240 }
10241 }
10242
10243 if ( key === "title" ) {
10244 this._title( this.uiDialogTitlebar.find(".ui-dialog-title") );
10245 }
10246 },
10247
10248 _size: function() {
10249 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
10250 // divs will both have width and height set, so we need to reset them
10251 var nonContentHeight, minContentHeight, maxContentHeight,
10252 options = this.options;
10253
10254 // Reset content sizing
10255 this.element.show().css({
10256 width: "auto",
10257 minHeight: 0,
10258 maxHeight: "none",
10259 height: 0
10260 });
10261
10262 if ( options.minWidth > options.width ) {
10263 options.width = options.minWidth;
10264 }
10265
10266 // reset wrapper sizing
10267 // determine the height of all the non-content elements
10268 nonContentHeight = this.uiDialog.css({
10269 height: "auto",
10270 width: options.width
10271 })
10272 .outerHeight();
10273 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
10274 maxContentHeight = typeof options.maxHeight === "number" ?
10275 Math.max( 0, options.maxHeight - nonContentHeight ) :
10276 "none";
10277
10278 if ( options.height === "auto" ) {
10279 this.element.css({
10280 minHeight: minContentHeight,
10281 maxHeight: maxContentHeight,
10282 height: "auto"
10283 });
10284 } else {
10285 this.element.height( Math.max( 0, options.height - nonContentHeight ) );
10286 }
10287
10288 if (this.uiDialog.is(":data(ui-resizable)") ) {
10289 this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
10290 }
10291 },
10292
10293 _blockFrames: function() {
10294 this.iframeBlocks = this.document.find( "iframe" ).map(function() {
10295 var iframe = $( this );
10296
10297 return $( "<div>" )
10298 .css({
10299 position: "absolute",
10300 width: iframe.outerWidth(),
10301 height: iframe.outerHeight()
10302 })
10303 .appendTo( iframe.parent() )
10304 .offset( iframe.offset() )[0];
10305 });
10306 },
10307
10308 _unblockFrames: function() {
10309 if ( this.iframeBlocks ) {
10310 this.iframeBlocks.remove();
10311 delete this.iframeBlocks;
10312 }
10313 },
10314
10315 _allowInteraction: function( event ) {
10316 if ( $( event.target ).closest(".ui-dialog").length ) {
10317 return true;
10318 }
10319
10320 // TODO: Remove hack when datepicker implements
10321 // the .ui-front logic (#8989)
10322 return !!$( event.target ).closest(".ui-datepicker").length;
10323 },
10324
10325 _createOverlay: function() {
10326 if ( !this.options.modal ) {
10327 return;
10328 }
10329
10330 var that = this,
10331 widgetFullName = this.widgetFullName;
10332 if ( !$.ui.dialog.overlayInstances ) {
10333 // Prevent use of anchors and inputs.
10334 // We use a delay in case the overlay is created from an
10335 // event that we're going to be cancelling. (#2804)
10336 this._delay(function() {
10337 // Handle .dialog().dialog("close") (#4065)
10338 if ( $.ui.dialog.overlayInstances ) {
10339 this.document.bind( "focusin.dialog", function( event ) {
10340 if ( !that._allowInteraction( event ) ) {
10341 event.preventDefault();
10342 $(".ui-dialog:visible:last .ui-dialog-content")
10343 .data( widgetFullName )._focusTabbable();
10344 }
10345 });
10346 }
10347 });
10348 }
10349
10350 this.overlay = $("<div>")
10351 .addClass("ui-widget-overlay ui-front")
10352 .appendTo( this._appendTo() );
10353 this._on( this.overlay, {
10354 mousedown: "_keepFocus"
10355 });
10356 $.ui.dialog.overlayInstances++;
10357 },
10358
10359 _destroyOverlay: function() {
10360 if ( !this.options.modal ) {
10361 return;
10362 }
10363
10364 if ( this.overlay ) {
10365 $.ui.dialog.overlayInstances--;
10366
10367 if ( !$.ui.dialog.overlayInstances ) {
10368 this.document.unbind( "focusin.dialog" );
10369 }
10370 this.overlay.remove();
10371 this.overlay = null;
10372 }
10373 }
10374});
10375
10376$.ui.dialog.overlayInstances = 0;
10377
10378// DEPRECATED
10379if ( $.uiBackCompat !== false ) {
10380 // position option with array notation
10381 // just override with old implementation
10382 $.widget( "ui.dialog", $.ui.dialog, {
10383 _position: function() {
10384 var position = this.options.position,
10385 myAt = [],
10386 offset = [ 0, 0 ],
10387 isVisible;
10388
10389 if ( position ) {
10390 if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) {
10391 myAt = position.split ? position.split(" ") : [ position[0], position[1] ];
10392 if ( myAt.length === 1 ) {
10393 myAt[1] = myAt[0];
10394 }
10395
10396 $.each( [ "left", "top" ], function( i, offsetPosition ) {
10397 if ( +myAt[ i ] === myAt[ i ] ) {
10398 offset[ i ] = myAt[ i ];
10399 myAt[ i ] = offsetPosition;
10400 }
10401 });
10402
10403 position = {
10404 my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " +
10405 myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]),
10406 at: myAt.join(" ")
10407 };
10408 }
10409
10410 position = $.extend( {}, $.ui.dialog.prototype.options.position, position );
10411 } else {
10412 position = $.ui.dialog.prototype.options.position;
10413 }
10414
10415 // need to show the dialog to get the actual offset in the position plugin
10416 isVisible = this.uiDialog.is(":visible");
10417 if ( !isVisible ) {
10418 this.uiDialog.show();
10419 }
10420 this.uiDialog.position( position );
10421 if ( !isVisible ) {
10422 this.uiDialog.hide();
10423 }
10424 }
10425 });
10426}
10427
10428}( jQuery ) );
10429
10430(function( $, undefined ) {
10431
10432var rvertical = /up|down|vertical/,
10433 rpositivemotion = /up|left|vertical|horizontal/;
10434
10435$.effects.effect.blind = function( o, done ) {
10436 // Create element
10437 var el = $( this ),
10438 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10439 mode = $.effects.setMode( el, o.mode || "hide" ),
10440 direction = o.direction || "up",
10441 vertical = rvertical.test( direction ),
10442 ref = vertical ? "height" : "width",
10443 ref2 = vertical ? "top" : "left",
10444 motion = rpositivemotion.test( direction ),
10445 animation = {},
10446 show = mode === "show",
10447 wrapper, distance, margin;
10448
10449 // if already wrapped, the wrapper's properties are my property. #6245
10450 if ( el.parent().is( ".ui-effects-wrapper" ) ) {
10451 $.effects.save( el.parent(), props );
10452 } else {
10453 $.effects.save( el, props );
10454 }
10455 el.show();
10456 wrapper = $.effects.createWrapper( el ).css({
10457 overflow: "hidden"
10458 });
10459
10460 distance = wrapper[ ref ]();
10461 margin = parseFloat( wrapper.css( ref2 ) ) || 0;
10462
10463 animation[ ref ] = show ? distance : 0;
10464 if ( !motion ) {
10465 el
10466 .css( vertical ? "bottom" : "right", 0 )
10467 .css( vertical ? "top" : "left", "auto" )
10468 .css({ position: "absolute" });
10469
10470 animation[ ref2 ] = show ? margin : distance + margin;
10471 }
10472
10473 // start at 0 if we are showing
10474 if ( show ) {
10475 wrapper.css( ref, 0 );
10476 if ( ! motion ) {
10477 wrapper.css( ref2, margin + distance );
10478 }
10479 }
10480
10481 // Animate
10482 wrapper.animate( animation, {
10483 duration: o.duration,
10484 easing: o.easing,
10485 queue: false,
10486 complete: function() {
10487 if ( mode === "hide" ) {
10488 el.hide();
10489 }
10490 $.effects.restore( el, props );
10491 $.effects.removeWrapper( el );
10492 done();
10493 }
10494 });
10495
10496};
10497
10498})(jQuery);
10499
10500(function( $, undefined ) {
10501
10502$.effects.effect.bounce = function( o, done ) {
10503 var el = $( this ),
10504 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10505
10506 // defaults:
10507 mode = $.effects.setMode( el, o.mode || "effect" ),
10508 hide = mode === "hide",
10509 show = mode === "show",
10510 direction = o.direction || "up",
10511 distance = o.distance,
10512 times = o.times || 5,
10513
10514 // number of internal animations
10515 anims = times * 2 + ( show || hide ? 1 : 0 ),
10516 speed = o.duration / anims,
10517 easing = o.easing,
10518
10519 // utility:
10520 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10521 motion = ( direction === "up" || direction === "left" ),
10522 i,
10523 upAnim,
10524 downAnim,
10525
10526 // we will need to re-assemble the queue to stack our animations in place
10527 queue = el.queue(),
10528 queuelen = queue.length;
10529
10530 // Avoid touching opacity to prevent clearType and PNG issues in IE
10531 if ( show || hide ) {
10532 props.push( "opacity" );
10533 }
10534
10535 $.effects.save( el, props );
10536 el.show();
10537 $.effects.createWrapper( el ); // Create Wrapper
10538
10539 // default distance for the BIGGEST bounce is the outer Distance / 3
10540 if ( !distance ) {
10541 distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
10542 }
10543
10544 if ( show ) {
10545 downAnim = { opacity: 1 };
10546 downAnim[ ref ] = 0;
10547
10548 // if we are showing, force opacity 0 and set the initial position
10549 // then do the "first" animation
10550 el.css( "opacity", 0 )
10551 .css( ref, motion ? -distance * 2 : distance * 2 )
10552 .animate( downAnim, speed, easing );
10553 }
10554
10555 // start at the smallest distance if we are hiding
10556 if ( hide ) {
10557 distance = distance / Math.pow( 2, times - 1 );
10558 }
10559
10560 downAnim = {};
10561 downAnim[ ref ] = 0;
10562 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
10563 for ( i = 0; i < times; i++ ) {
10564 upAnim = {};
10565 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10566
10567 el.animate( upAnim, speed, easing )
10568 .animate( downAnim, speed, easing );
10569
10570 distance = hide ? distance * 2 : distance / 2;
10571 }
10572
10573 // Last Bounce when Hiding
10574 if ( hide ) {
10575 upAnim = { opacity: 0 };
10576 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10577
10578 el.animate( upAnim, speed, easing );
10579 }
10580
10581 el.queue(function() {
10582 if ( hide ) {
10583 el.hide();
10584 }
10585 $.effects.restore( el, props );
10586 $.effects.removeWrapper( el );
10587 done();
10588 });
10589
10590 // inject all the animations we just queued to be first in line (after "inprogress")
10591 if ( queuelen > 1) {
10592 queue.splice.apply( queue,
10593 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
10594 }
10595 el.dequeue();
10596
10597};
10598
10599})(jQuery);
10600
10601(function( $, undefined ) {
10602
10603$.effects.effect.clip = function( o, done ) {
10604 // Create element
10605 var el = $( this ),
10606 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10607 mode = $.effects.setMode( el, o.mode || "hide" ),
10608 show = mode === "show",
10609 direction = o.direction || "vertical",
10610 vert = direction === "vertical",
10611 size = vert ? "height" : "width",
10612 position = vert ? "top" : "left",
10613 animation = {},
10614 wrapper, animate, distance;
10615
10616 // Save & Show
10617 $.effects.save( el, props );
10618 el.show();
10619
10620 // Create Wrapper
10621 wrapper = $.effects.createWrapper( el ).css({
10622 overflow: "hidden"
10623 });
10624 animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
10625 distance = animate[ size ]();
10626
10627 // Shift
10628 if ( show ) {
10629 animate.css( size, 0 );
10630 animate.css( position, distance / 2 );
10631 }
10632
10633 // Create Animation Object:
10634 animation[ size ] = show ? distance : 0;
10635 animation[ position ] = show ? 0 : distance / 2;
10636
10637 // Animate
10638 animate.animate( animation, {
10639 queue: false,
10640 duration: o.duration,
10641 easing: o.easing,
10642 complete: function() {
10643 if ( !show ) {
10644 el.hide();
10645 }
10646 $.effects.restore( el, props );
10647 $.effects.removeWrapper( el );
10648 done();
10649 }
10650 });
10651
10652};
10653
10654})(jQuery);
10655
10656(function( $, undefined ) {
10657
10658$.effects.effect.drop = function( o, done ) {
10659
10660 var el = $( this ),
10661 props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
10662 mode = $.effects.setMode( el, o.mode || "hide" ),
10663 show = mode === "show",
10664 direction = o.direction || "left",
10665 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10666 motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
10667 animation = {
10668 opacity: show ? 1 : 0
10669 },
10670 distance;
10671
10672 // Adjust
10673 $.effects.save( el, props );
10674 el.show();
10675 $.effects.createWrapper( el );
10676
10677 distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2;
10678
10679 if ( show ) {
10680 el
10681 .css( "opacity", 0 )
10682 .css( ref, motion === "pos" ? -distance : distance );
10683 }
10684
10685 // Animation
10686 animation[ ref ] = ( show ?
10687 ( motion === "pos" ? "+=" : "-=" ) :
10688 ( motion === "pos" ? "-=" : "+=" ) ) +
10689 distance;
10690
10691 // Animate
10692 el.animate( animation, {
10693 queue: false,
10694 duration: o.duration,
10695 easing: o.easing,
10696 complete: function() {
10697 if ( mode === "hide" ) {
10698 el.hide();
10699 }
10700 $.effects.restore( el, props );
10701 $.effects.removeWrapper( el );
10702 done();
10703 }
10704 });
10705};
10706
10707})(jQuery);
10708
10709(function( $, undefined ) {
10710
10711$.effects.effect.explode = function( o, done ) {
10712
10713 var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
10714 cells = rows,
10715 el = $( this ),
10716 mode = $.effects.setMode( el, o.mode || "hide" ),
10717 show = mode === "show",
10718
10719 // show and then visibility:hidden the element before calculating offset
10720 offset = el.show().css( "visibility", "hidden" ).offset(),
10721
10722 // width and height of a piece
10723 width = Math.ceil( el.outerWidth() / cells ),
10724 height = Math.ceil( el.outerHeight() / rows ),
10725 pieces = [],
10726
10727 // loop
10728 i, j, left, top, mx, my;
10729
10730 // children animate complete:
10731 function childComplete() {
10732 pieces.push( this );
10733 if ( pieces.length === rows * cells ) {
10734 animComplete();
10735 }
10736 }
10737
10738 // clone the element for each row and cell.
10739 for( i = 0; i < rows ; i++ ) { // ===>
10740 top = offset.top + i * height;
10741 my = i - ( rows - 1 ) / 2 ;
10742
10743 for( j = 0; j < cells ; j++ ) { // |||
10744 left = offset.left + j * width;
10745 mx = j - ( cells - 1 ) / 2 ;
10746
10747 // Create a clone of the now hidden main element that will be absolute positioned
10748 // within a wrapper div off the -left and -top equal to size of our pieces
10749 el
10750 .clone()
10751 .appendTo( "body" )
10752 .wrap( "<div></div>" )
10753 .css({
10754 position: "absolute",
10755 visibility: "visible",
10756 left: -j * width,
10757 top: -i * height
10758 })
10759
10760 // select the wrapper - make it overflow: hidden and absolute positioned based on
10761 // where the original was located +left and +top equal to the size of pieces
10762 .parent()
10763 .addClass( "ui-effects-explode" )
10764 .css({
10765 position: "absolute",
10766 overflow: "hidden",
10767 width: width,
10768 height: height,
10769 left: left + ( show ? mx * width : 0 ),
10770 top: top + ( show ? my * height : 0 ),
10771 opacity: show ? 0 : 1
10772 }).animate({
10773 left: left + ( show ? 0 : mx * width ),
10774 top: top + ( show ? 0 : my * height ),
10775 opacity: show ? 1 : 0
10776 }, o.duration || 500, o.easing, childComplete );
10777 }
10778 }
10779
10780 function animComplete() {
10781 el.css({
10782 visibility: "visible"
10783 });
10784 $( pieces ).remove();
10785 if ( !show ) {
10786 el.hide();
10787 }
10788 done();
10789 }
10790};
10791
10792})(jQuery);
10793
10794(function( $, undefined ) {
10795
10796$.effects.effect.fade = function( o, done ) {
10797 var el = $( this ),
10798 mode = $.effects.setMode( el, o.mode || "toggle" );
10799
10800 el.animate({
10801 opacity: mode
10802 }, {
10803 queue: false,
10804 duration: o.duration,
10805 easing: o.easing,
10806 complete: done
10807 });
10808};
10809
10810})( jQuery );
10811
10812(function( $, undefined ) {
10813
10814$.effects.effect.fold = function( o, done ) {
10815
10816 // Create element
10817 var el = $( this ),
10818 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10819 mode = $.effects.setMode( el, o.mode || "hide" ),
10820 show = mode === "show",
10821 hide = mode === "hide",
10822 size = o.size || 15,
10823 percent = /([0-9]+)%/.exec( size ),
10824 horizFirst = !!o.horizFirst,
10825 widthFirst = show !== horizFirst,
10826 ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
10827 duration = o.duration / 2,
10828 wrapper, distance,
10829 animation1 = {},
10830 animation2 = {};
10831
10832 $.effects.save( el, props );
10833 el.show();
10834
10835 // Create Wrapper
10836 wrapper = $.effects.createWrapper( el ).css({
10837 overflow: "hidden"
10838 });
10839 distance = widthFirst ?
10840 [ wrapper.width(), wrapper.height() ] :
10841 [ wrapper.height(), wrapper.width() ];
10842
10843 if ( percent ) {
10844 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
10845 }
10846 if ( show ) {
10847 wrapper.css( horizFirst ? {
10848 height: 0,
10849 width: size
10850 } : {
10851 height: size,
10852 width: 0
10853 });
10854 }
10855
10856 // Animation
10857 animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
10858 animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
10859
10860 // Animate
10861 wrapper
10862 .animate( animation1, duration, o.easing )
10863 .animate( animation2, duration, o.easing, function() {
10864 if ( hide ) {
10865 el.hide();
10866 }
10867 $.effects.restore( el, props );
10868 $.effects.removeWrapper( el );
10869 done();
10870 });
10871
10872};
10873
10874})(jQuery);
10875
10876(function( $, undefined ) {
10877
10878$.effects.effect.highlight = function( o, done ) {
10879 var elem = $( this ),
10880 props = [ "backgroundImage", "backgroundColor", "opacity" ],
10881 mode = $.effects.setMode( elem, o.mode || "show" ),
10882 animation = {
10883 backgroundColor: elem.css( "backgroundColor" )
10884 };
10885
10886 if (mode === "hide") {
10887 animation.opacity = 0;
10888 }
10889
10890 $.effects.save( elem, props );
10891
10892 elem
10893 .show()
10894 .css({
10895 backgroundImage: "none",
10896 backgroundColor: o.color || "#ffff99"
10897 })
10898 .animate( animation, {
10899 queue: false,
10900 duration: o.duration,
10901 easing: o.easing,
10902 complete: function() {
10903 if ( mode === "hide" ) {
10904 elem.hide();
10905 }
10906 $.effects.restore( elem, props );
10907 done();
10908 }
10909 });
10910};
10911
10912})(jQuery);
10913
10914(function( $, undefined ) {
10915
10916$.effects.effect.pulsate = function( o, done ) {
10917 var elem = $( this ),
10918 mode = $.effects.setMode( elem, o.mode || "show" ),
10919 show = mode === "show",
10920 hide = mode === "hide",
10921 showhide = ( show || mode === "hide" ),
10922
10923 // showing or hiding leaves of the "last" animation
10924 anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
10925 duration = o.duration / anims,
10926 animateTo = 0,
10927 queue = elem.queue(),
10928 queuelen = queue.length,
10929 i;
10930
10931 if ( show || !elem.is(":visible")) {
10932 elem.css( "opacity", 0 ).show();
10933 animateTo = 1;
10934 }
10935
10936 // anims - 1 opacity "toggles"
10937 for ( i = 1; i < anims; i++ ) {
10938 elem.animate({
10939 opacity: animateTo
10940 }, duration, o.easing );
10941 animateTo = 1 - animateTo;
10942 }
10943
10944 elem.animate({
10945 opacity: animateTo
10946 }, duration, o.easing);
10947
10948 elem.queue(function() {
10949 if ( hide ) {
10950 elem.hide();
10951 }
10952 done();
10953 });
10954
10955 // We just queued up "anims" animations, we need to put them next in the queue
10956 if ( queuelen > 1 ) {
10957 queue.splice.apply( queue,
10958 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
10959 }
10960 elem.dequeue();
10961};
10962
10963})(jQuery);
10964
10965(function( $, undefined ) {
10966
10967$.effects.effect.puff = function( o, done ) {
10968 var elem = $( this ),
10969 mode = $.effects.setMode( elem, o.mode || "hide" ),
10970 hide = mode === "hide",
10971 percent = parseInt( o.percent, 10 ) || 150,
10972 factor = percent / 100,
10973 original = {
10974 height: elem.height(),
10975 width: elem.width(),
10976 outerHeight: elem.outerHeight(),
10977 outerWidth: elem.outerWidth()
10978 };
10979
10980 $.extend( o, {
10981 effect: "scale",
10982 queue: false,
10983 fade: true,
10984 mode: mode,
10985 complete: done,
10986 percent: hide ? percent : 100,
10987 from: hide ?
10988 original :
10989 {
10990 height: original.height * factor,
10991 width: original.width * factor,
10992 outerHeight: original.outerHeight * factor,
10993 outerWidth: original.outerWidth * factor
10994 }
10995 });
10996
10997 elem.effect( o );
10998};
10999
11000$.effects.effect.scale = function( o, done ) {
11001
11002 // Create element
11003 var el = $( this ),
11004 options = $.extend( true, {}, o ),
11005 mode = $.effects.setMode( el, o.mode || "effect" ),
11006 percent = parseInt( o.percent, 10 ) ||
11007 ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
11008 direction = o.direction || "both",
11009 origin = o.origin,
11010 original = {
11011 height: el.height(),
11012 width: el.width(),
11013 outerHeight: el.outerHeight(),
11014 outerWidth: el.outerWidth()
11015 },
11016 factor = {
11017 y: direction !== "horizontal" ? (percent / 100) : 1,
11018 x: direction !== "vertical" ? (percent / 100) : 1
11019 };
11020
11021 // We are going to pass this effect to the size effect:
11022 options.effect = "size";
11023 options.queue = false;
11024 options.complete = done;
11025
11026 // Set default origin and restore for show/hide
11027 if ( mode !== "effect" ) {
11028 options.origin = origin || ["middle","center"];
11029 options.restore = true;
11030 }
11031
11032 options.from = o.from || ( mode === "show" ? {
11033 height: 0,
11034 width: 0,
11035 outerHeight: 0,
11036 outerWidth: 0
11037 } : original );
11038 options.to = {
11039 height: original.height * factor.y,
11040 width: original.width * factor.x,
11041 outerHeight: original.outerHeight * factor.y,
11042 outerWidth: original.outerWidth * factor.x
11043 };
11044
11045 // Fade option to support puff
11046 if ( options.fade ) {
11047 if ( mode === "show" ) {
11048 options.from.opacity = 0;
11049 options.to.opacity = 1;
11050 }
11051 if ( mode === "hide" ) {
11052 options.from.opacity = 1;
11053 options.to.opacity = 0;
11054 }
11055 }
11056
11057 // Animate
11058 el.effect( options );
11059
11060};
11061
11062$.effects.effect.size = function( o, done ) {
11063
11064 // Create element
11065 var original, baseline, factor,
11066 el = $( this ),
11067 props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
11068
11069 // Always restore
11070 props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
11071
11072 // Copy for children
11073 props2 = [ "width", "height", "overflow" ],
11074 cProps = [ "fontSize" ],
11075 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
11076 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
11077
11078 // Set options
11079 mode = $.effects.setMode( el, o.mode || "effect" ),
11080 restore = o.restore || mode !== "effect",
11081 scale = o.scale || "both",
11082 origin = o.origin || [ "middle", "center" ],
11083 position = el.css( "position" ),
11084 props = restore ? props0 : props1,
11085 zero = {
11086 height: 0,
11087 width: 0,
11088 outerHeight: 0,
11089 outerWidth: 0
11090 };
11091
11092 if ( mode === "show" ) {
11093 el.show();
11094 }
11095 original = {
11096 height: el.height(),
11097 width: el.width(),
11098 outerHeight: el.outerHeight(),
11099 outerWidth: el.outerWidth()
11100 };
11101
11102 if ( o.mode === "toggle" && mode === "show" ) {
11103 el.from = o.to || zero;
11104 el.to = o.from || original;
11105 } else {
11106 el.from = o.from || ( mode === "show" ? zero : original );
11107 el.to = o.to || ( mode === "hide" ? zero : original );
11108 }
11109
11110 // Set scaling factor
11111 factor = {
11112 from: {
11113 y: el.from.height / original.height,
11114 x: el.from.width / original.width
11115 },
11116 to: {
11117 y: el.to.height / original.height,
11118 x: el.to.width / original.width
11119 }
11120 };
11121
11122 // Scale the css box
11123 if ( scale === "box" || scale === "both" ) {
11124
11125 // Vertical props scaling
11126 if ( factor.from.y !== factor.to.y ) {
11127 props = props.concat( vProps );
11128 el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
11129 el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
11130 }
11131
11132 // Horizontal props scaling
11133 if ( factor.from.x !== factor.to.x ) {
11134 props = props.concat( hProps );
11135 el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
11136 el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
11137 }
11138 }
11139
11140 // Scale the content
11141 if ( scale === "content" || scale === "both" ) {
11142
11143 // Vertical props scaling
11144 if ( factor.from.y !== factor.to.y ) {
11145 props = props.concat( cProps ).concat( props2 );
11146 el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
11147 el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
11148 }
11149 }
11150
11151 $.effects.save( el, props );
11152 el.show();
11153 $.effects.createWrapper( el );
11154 el.css( "overflow", "hidden" ).css( el.from );
11155
11156 // Adjust
11157 if (origin) { // Calculate baseline shifts
11158 baseline = $.effects.getBaseline( origin, original );
11159 el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
11160 el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
11161 el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
11162 el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
11163 }
11164 el.css( el.from ); // set top & left
11165
11166 // Animate
11167 if ( scale === "content" || scale === "both" ) { // Scale the children
11168
11169 // Add margins/font-size
11170 vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
11171 hProps = hProps.concat([ "marginLeft", "marginRight" ]);
11172 props2 = props0.concat(vProps).concat(hProps);
11173
11174 el.find( "*[width]" ).each( function(){
11175 var child = $( this ),
11176 c_original = {
11177 height: child.height(),
11178 width: child.width(),
11179 outerHeight: child.outerHeight(),
11180 outerWidth: child.outerWidth()
11181 };
11182 if (restore) {
11183 $.effects.save(child, props2);
11184 }
11185
11186 child.from = {
11187 height: c_original.height * factor.from.y,
11188 width: c_original.width * factor.from.x,
11189 outerHeight: c_original.outerHeight * factor.from.y,
11190 outerWidth: c_original.outerWidth * factor.from.x
11191 };
11192 child.to = {
11193 height: c_original.height * factor.to.y,
11194 width: c_original.width * factor.to.x,
11195 outerHeight: c_original.height * factor.to.y,
11196 outerWidth: c_original.width * factor.to.x
11197 };
11198
11199 // Vertical props scaling
11200 if ( factor.from.y !== factor.to.y ) {
11201 child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
11202 child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
11203 }
11204
11205 // Horizontal props scaling
11206 if ( factor.from.x !== factor.to.x ) {
11207 child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
11208 child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
11209 }
11210
11211 // Animate children
11212 child.css( child.from );
11213 child.animate( child.to, o.duration, o.easing, function() {
11214
11215 // Restore children
11216 if ( restore ) {
11217 $.effects.restore( child, props2 );
11218 }
11219 });
11220 });
11221 }
11222
11223 // Animate
11224 el.animate( el.to, {
11225 queue: false,
11226 duration: o.duration,
11227 easing: o.easing,
11228 complete: function() {
11229 if ( el.to.opacity === 0 ) {
11230 el.css( "opacity", el.from.opacity );
11231 }
11232 if( mode === "hide" ) {
11233 el.hide();
11234 }
11235 $.effects.restore( el, props );
11236 if ( !restore ) {
11237
11238 // we need to calculate our new positioning based on the scaling
11239 if ( position === "static" ) {
11240 el.css({
11241 position: "relative",
11242 top: el.to.top,
11243 left: el.to.left
11244 });
11245 } else {
11246 $.each([ "top", "left" ], function( idx, pos ) {
11247 el.css( pos, function( _, str ) {
11248 var val = parseInt( str, 10 ),
11249 toRef = idx ? el.to.left : el.to.top;
11250
11251 // if original was "auto", recalculate the new value from wrapper
11252 if ( str === "auto" ) {
11253 return toRef + "px";
11254 }
11255
11256 return val + toRef + "px";
11257 });
11258 });
11259 }
11260 }
11261
11262 $.effects.removeWrapper( el );
11263 done();
11264 }
11265 });
11266
11267};
11268
11269})(jQuery);
11270
11271(function( $, undefined ) {
11272
11273$.effects.effect.shake = function( o, done ) {
11274
11275 var el = $( this ),
11276 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
11277 mode = $.effects.setMode( el, o.mode || "effect" ),
11278 direction = o.direction || "left",
11279 distance = o.distance || 20,
11280 times = o.times || 3,
11281 anims = times * 2 + 1,
11282 speed = Math.round(o.duration/anims),
11283 ref = (direction === "up" || direction === "down") ? "top" : "left",
11284 positiveMotion = (direction === "up" || direction === "left"),
11285 animation = {},
11286 animation1 = {},
11287 animation2 = {},
11288 i,
11289
11290 // we will need to re-assemble the queue to stack our animations in place
11291 queue = el.queue(),
11292 queuelen = queue.length;
11293
11294 $.effects.save( el, props );
11295 el.show();
11296 $.effects.createWrapper( el );
11297
11298 // Animation
11299 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
11300 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
11301 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
11302
11303 // Animate
11304 el.animate( animation, speed, o.easing );
11305
11306 // Shakes
11307 for ( i = 1; i < times; i++ ) {
11308 el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
11309 }
11310 el
11311 .animate( animation1, speed, o.easing )
11312 .animate( animation, speed / 2, o.easing )
11313 .queue(function() {
11314 if ( mode === "hide" ) {
11315 el.hide();
11316 }
11317 $.effects.restore( el, props );
11318 $.effects.removeWrapper( el );
11319 done();
11320 });
11321
11322 // inject all the animations we just queued to be first in line (after "inprogress")
11323 if ( queuelen > 1) {
11324 queue.splice.apply( queue,
11325 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
11326 }
11327 el.dequeue();
11328
11329};
11330
11331})(jQuery);
11332
11333(function( $, undefined ) {
11334
11335$.effects.effect.slide = function( o, done ) {
11336
11337 // Create element
11338 var el = $( this ),
11339 props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
11340 mode = $.effects.setMode( el, o.mode || "show" ),
11341 show = mode === "show",
11342 direction = o.direction || "left",
11343 ref = (direction === "up" || direction === "down") ? "top" : "left",
11344 positiveMotion = (direction === "up" || direction === "left"),
11345 distance,
11346 animation = {};
11347
11348 // Adjust
11349 $.effects.save( el, props );
11350 el.show();
11351 distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
11352
11353 $.effects.createWrapper( el ).css({
11354 overflow: "hidden"
11355 });
11356
11357 if ( show ) {
11358 el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
11359 }
11360
11361 // Animation
11362 animation[ ref ] = ( show ?
11363 ( positiveMotion ? "+=" : "-=") :
11364 ( positiveMotion ? "-=" : "+=")) +
11365 distance;
11366
11367 // Animate
11368 el.animate( animation, {
11369 queue: false,
11370 duration: o.duration,
11371 easing: o.easing,
11372 complete: function() {
11373 if ( mode === "hide" ) {
11374 el.hide();
11375 }
11376 $.effects.restore( el, props );
11377 $.effects.removeWrapper( el );
11378 done();
11379 }
11380 });
11381};
11382
11383})(jQuery);
11384
11385(function( $, undefined ) {
11386
11387$.effects.effect.transfer = function( o, done ) {
11388 var elem = $( this ),
11389 target = $( o.to ),
11390 targetFixed = target.css( "position" ) === "fixed",
11391 body = $("body"),
11392 fixTop = targetFixed ? body.scrollTop() : 0,
11393 fixLeft = targetFixed ? body.scrollLeft() : 0,
11394 endPosition = target.offset(),
11395 animation = {
11396 top: endPosition.top - fixTop ,
11397 left: endPosition.left - fixLeft ,
11398 height: target.innerHeight(),
11399 width: target.innerWidth()
11400 },
11401 startPosition = elem.offset(),
11402 transfer = $( "<div class='ui-effects-transfer'></div>" )
11403 .appendTo( document.body )
11404 .addClass( o.className )
11405 .css({
11406 top: startPosition.top - fixTop ,
11407 left: startPosition.left - fixLeft ,
11408 height: elem.innerHeight(),
11409 width: elem.innerWidth(),
11410 position: targetFixed ? "fixed" : "absolute"
11411 })
11412 .animate( animation, o.duration, o.easing, function() {
11413 transfer.remove();
11414 done();
11415 });
11416};
11417
11418})(jQuery);
11419
11420(function( $, undefined ) {
11421
11422$.widget( "ui.menu", {
11423 version: "1.10.3",
11424 defaultElement: "<ul>",
11425 delay: 300,
11426 options: {
11427 icons: {
11428 submenu: "ui-icon-carat-1-e"
11429 },
11430 menus: "ul",
11431 position: {
11432 my: "left top",
11433 at: "right top"
11434 },
11435 role: "menu",
11436
11437 // callbacks
11438 blur: null,
11439 focus: null,
11440 select: null
11441 },
11442
11443 _create: function() {
11444 this.activeMenu = this.element;
11445 // flag used to prevent firing of the click handler
11446 // as the event bubbles up through nested menus
11447 this.mouseHandled = false;
11448 this.element
11449 .uniqueId()
11450 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
11451 .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
11452 .attr({
11453 role: this.options.role,
11454 tabIndex: 0
11455 })
11456 // need to catch all clicks on disabled menu
11457 // not possible through _on
11458 .bind( "click" + this.eventNamespace, $.proxy(function( event ) {
11459 if ( this.options.disabled ) {
11460 event.preventDefault();
11461 }
11462 }, this ));
11463
11464 if ( this.options.disabled ) {
11465 this.element
11466 .addClass( "ui-state-disabled" )
11467 .attr( "aria-disabled", "true" );
11468 }
11469
11470 this._on({
11471 // Prevent focus from sticking to links inside menu after clicking
11472 // them (focus should always stay on UL during navigation).
11473 "mousedown .ui-menu-item > a": function( event ) {
11474 event.preventDefault();
11475 },
11476 "click .ui-state-disabled > a": function( event ) {
11477 event.preventDefault();
11478 },
11479 "click .ui-menu-item:has(a)": function( event ) {
11480 var target = $( event.target ).closest( ".ui-menu-item" );
11481 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
11482 this.mouseHandled = true;
11483
11484 this.select( event );
11485 // Open submenu on click
11486 if ( target.has( ".ui-menu" ).length ) {
11487 this.expand( event );
11488 } else if ( !this.element.is( ":focus" ) ) {
11489 // Redirect focus to the menu
11490 this.element.trigger( "focus", [ true ] );
11491
11492 // If the active item is on the top level, let it stay active.
11493 // Otherwise, blur the active item since it is no longer visible.
11494 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
11495 clearTimeout( this.timer );
11496 }
11497 }
11498 }
11499 },
11500 "mouseenter .ui-menu-item": function( event ) {
11501 var target = $( event.currentTarget );
11502 // Remove ui-state-active class from siblings of the newly focused menu item
11503 // to avoid a jump caused by adjacent elements both having a class with a border
11504 target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" );
11505 this.focus( event, target );
11506 },
11507 mouseleave: "collapseAll",
11508 "mouseleave .ui-menu": "collapseAll",
11509 focus: function( event, keepActiveItem ) {
11510 // If there's already an active item, keep it active
11511 // If not, activate the first item
11512 var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 );
11513
11514 if ( !keepActiveItem ) {
11515 this.focus( event, item );
11516 }
11517 },
11518 blur: function( event ) {
11519 this._delay(function() {
11520 if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
11521 this.collapseAll( event );
11522 }
11523 });
11524 },
11525 keydown: "_keydown"
11526 });
11527
11528 this.refresh();
11529
11530 // Clicks outside of a menu collapse any open menus
11531 this._on( this.document, {
11532 click: function( event ) {
11533 if ( !$( event.target ).closest( ".ui-menu" ).length ) {
11534 this.collapseAll( event );
11535 }
11536
11537 // Reset the mouseHandled flag
11538 this.mouseHandled = false;
11539 }
11540 });
11541 },
11542
11543 _destroy: function() {
11544 // Destroy (sub)menus
11545 this.element
11546 .removeAttr( "aria-activedescendant" )
11547 .find( ".ui-menu" ).addBack()
11548 .removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" )
11549 .removeAttr( "role" )
11550 .removeAttr( "tabIndex" )
11551 .removeAttr( "aria-labelledby" )
11552 .removeAttr( "aria-expanded" )
11553 .removeAttr( "aria-hidden" )
11554 .removeAttr( "aria-disabled" )
11555 .removeUniqueId()
11556 .show();
11557
11558 // Destroy menu items
11559 this.element.find( ".ui-menu-item" )
11560 .removeClass( "ui-menu-item" )
11561 .removeAttr( "role" )
11562 .removeAttr( "aria-disabled" )
11563 .children( "a" )
11564 .removeUniqueId()
11565 .removeClass( "ui-corner-all ui-state-hover" )
11566 .removeAttr( "tabIndex" )
11567 .removeAttr( "role" )
11568 .removeAttr( "aria-haspopup" )
11569 .children().each( function() {
11570 var elem = $( this );
11571 if ( elem.data( "ui-menu-submenu-carat" ) ) {
11572 elem.remove();
11573 }
11574 });
11575
11576 // Destroy menu dividers
11577 this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
11578 },
11579
11580 _keydown: function( event ) {
11581 /*jshint maxcomplexity:20*/
11582 var match, prev, character, skip, regex,
11583 preventDefault = true;
11584
11585 function escape( value ) {
11586 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
11587 }
11588
11589 switch ( event.keyCode ) {
11590 case $.ui.keyCode.PAGE_UP:
11591 this.previousPage( event );
11592 break;
11593 case $.ui.keyCode.PAGE_DOWN:
11594 this.nextPage( event );
11595 break;
11596 case $.ui.keyCode.HOME:
11597 this._move( "first", "first", event );
11598 break;
11599 case $.ui.keyCode.END:
11600 this._move( "last", "last", event );
11601 break;
11602 case $.ui.keyCode.UP:
11603 this.previous( event );
11604 break;
11605 case $.ui.keyCode.DOWN:
11606 this.next( event );
11607 break;
11608 case $.ui.keyCode.LEFT:
11609 this.collapse( event );
11610 break;
11611 case $.ui.keyCode.RIGHT:
11612 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
11613 this.expand( event );
11614 }
11615 break;
11616 case $.ui.keyCode.ENTER:
11617 case $.ui.keyCode.SPACE:
11618 this._activate( event );
11619 break;
11620 case $.ui.keyCode.ESCAPE:
11621 this.collapse( event );
11622 break;
11623 default:
11624 preventDefault = false;
11625 prev = this.previousFilter || "";
11626 character = String.fromCharCode( event.keyCode );
11627 skip = false;
11628
11629 clearTimeout( this.filterTimer );
11630
11631 if ( character === prev ) {
11632 skip = true;
11633 } else {
11634 character = prev + character;
11635 }
11636
11637 regex = new RegExp( "^" + escape( character ), "i" );
11638 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
11639 return regex.test( $( this ).children( "a" ).text() );
11640 });
11641 match = skip && match.index( this.active.next() ) !== -1 ?
11642 this.active.nextAll( ".ui-menu-item" ) :
11643 match;
11644
11645 // If no matches on the current filter, reset to the last character pressed
11646 // to move down the menu to the first item that starts with that character
11647 if ( !match.length ) {
11648 character = String.fromCharCode( event.keyCode );
11649 regex = new RegExp( "^" + escape( character ), "i" );
11650 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
11651 return regex.test( $( this ).children( "a" ).text() );
11652 });
11653 }
11654
11655 if ( match.length ) {
11656 this.focus( event, match );
11657 if ( match.length > 1 ) {
11658 this.previousFilter = character;
11659 this.filterTimer = this._delay(function() {
11660 delete this.previousFilter;
11661 }, 1000 );
11662 } else {
11663 delete this.previousFilter;
11664 }
11665 } else {
11666 delete this.previousFilter;
11667 }
11668 }
11669
11670 if ( preventDefault ) {
11671 event.preventDefault();
11672 }
11673 },
11674
11675 _activate: function( event ) {
11676 if ( !this.active.is( ".ui-state-disabled" ) ) {
11677 if ( this.active.children( "a[aria-haspopup='true']" ).length ) {
11678 this.expand( event );
11679 } else {
11680 this.select( event );
11681 }
11682 }
11683 },
11684
11685 refresh: function() {
11686 var menus,
11687 icon = this.options.icons.submenu,
11688 submenus = this.element.find( this.options.menus );
11689
11690 // Initialize nested menus
11691 submenus.filter( ":not(.ui-menu)" )
11692 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
11693 .hide()
11694 .attr({
11695 role: this.options.role,
11696 "aria-hidden": "true",
11697 "aria-expanded": "false"
11698 })
11699 .each(function() {
11700 var menu = $( this ),
11701 item = menu.prev( "a" ),
11702 submenuCarat = $( "<span>" )
11703 .addClass( "ui-menu-icon ui-icon " + icon )
11704 .data( "ui-menu-submenu-carat", true );
11705
11706 item
11707 .attr( "aria-haspopup", "true" )
11708 .prepend( submenuCarat );
11709 menu.attr( "aria-labelledby", item.attr( "id" ) );
11710 });
11711
11712 menus = submenus.add( this.element );
11713
11714 // Don't refresh list items that are already adapted
11715 menus.children( ":not(.ui-menu-item):has(a)" )
11716 .addClass( "ui-menu-item" )
11717 .attr( "role", "presentation" )
11718 .children( "a" )
11719 .uniqueId()
11720 .addClass( "ui-corner-all" )
11721 .attr({
11722 tabIndex: -1,
11723 role: this._itemRole()
11724 });
11725
11726 // Initialize unlinked menu-items containing spaces and/or dashes only as dividers
11727 menus.children( ":not(.ui-menu-item)" ).each(function() {
11728 var item = $( this );
11729 // hyphen, em dash, en dash
11730 if ( !/[^\-\u2014\u2013\s]/.test( item.text() ) ) {
11731 item.addClass( "ui-widget-content ui-menu-divider" );
11732 }
11733 });
11734
11735 // Add aria-disabled attribute to any disabled menu item
11736 menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
11737
11738 // If the active item has been removed, blur the menu
11739 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
11740 this.blur();
11741 }
11742 },
11743
11744 _itemRole: function() {
11745 return {
11746 menu: "menuitem",
11747 listbox: "option"
11748 }[ this.options.role ];
11749 },
11750
11751 _setOption: function( key, value ) {
11752 if ( key === "icons" ) {
11753 this.element.find( ".ui-menu-icon" )
11754 .removeClass( this.options.icons.submenu )
11755 .addClass( value.submenu );
11756 }
11757 this._super( key, value );
11758 },
11759
11760 focus: function( event, item ) {
11761 var nested, focused;
11762 this.blur( event, event && event.type === "focus" );
11763
11764 this._scrollIntoView( item );
11765
11766 this.active = item.first();
11767 focused = this.active.children( "a" ).addClass( "ui-state-focus" );
11768 // Only update aria-activedescendant if there's a role
11769 // otherwise we assume focus is managed elsewhere
11770 if ( this.options.role ) {
11771 this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
11772 }
11773
11774 // Highlight active parent menu item, if any
11775 this.active
11776 .parent()
11777 .closest( ".ui-menu-item" )
11778 .children( "a:first" )
11779 .addClass( "ui-state-active" );
11780
11781 if ( event && event.type === "keydown" ) {
11782 this._close();
11783 } else {
11784 this.timer = this._delay(function() {
11785 this._close();
11786 }, this.delay );
11787 }
11788
11789 nested = item.children( ".ui-menu" );
11790 if ( nested.length && ( /^mouse/.test( event.type ) ) ) {
11791 this._startOpening(nested);
11792 }
11793 this.activeMenu = item.parent();
11794
11795 this._trigger( "focus", event, { item: item } );
11796 },
11797
11798 _scrollIntoView: function( item ) {
11799 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
11800 if ( this._hasScroll() ) {
11801 borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
11802 paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
11803 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
11804 scroll = this.activeMenu.scrollTop();
11805 elementHeight = this.activeMenu.height();
11806 itemHeight = item.height();
11807
11808 if ( offset < 0 ) {
11809 this.activeMenu.scrollTop( scroll + offset );
11810 } else if ( offset + itemHeight > elementHeight ) {
11811 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
11812 }
11813 }
11814 },
11815
11816 blur: function( event, fromFocus ) {
11817 if ( !fromFocus ) {
11818 clearTimeout( this.timer );
11819 }
11820
11821 if ( !this.active ) {
11822 return;
11823 }
11824
11825 this.active.children( "a" ).removeClass( "ui-state-focus" );
11826 this.active = null;
11827
11828 this._trigger( "blur", event, { item: this.active } );
11829 },
11830
11831 _startOpening: function( submenu ) {
11832 clearTimeout( this.timer );
11833
11834 // Don't open if already open fixes a Firefox bug that caused a .5 pixel
11835 // shift in the submenu position when mousing over the carat icon
11836 if ( submenu.attr( "aria-hidden" ) !== "true" ) {
11837 return;
11838 }
11839
11840 this.timer = this._delay(function() {
11841 this._close();
11842 this._open( submenu );
11843 }, this.delay );
11844 },
11845
11846 _open: function( submenu ) {
11847 var position = $.extend({
11848 of: this.active
11849 }, this.options.position );
11850
11851 clearTimeout( this.timer );
11852 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
11853 .hide()
11854 .attr( "aria-hidden", "true" );
11855
11856 submenu
11857 .show()
11858 .removeAttr( "aria-hidden" )
11859 .attr( "aria-expanded", "true" )
11860 .position( position );
11861 },
11862
11863 collapseAll: function( event, all ) {
11864 clearTimeout( this.timer );
11865 this.timer = this._delay(function() {
11866 // If we were passed an event, look for the submenu that contains the event
11867 var currentMenu = all ? this.element :
11868 $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
11869
11870 // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
11871 if ( !currentMenu.length ) {
11872 currentMenu = this.element;
11873 }
11874
11875 this._close( currentMenu );
11876
11877 this.blur( event );
11878 this.activeMenu = currentMenu;
11879 }, this.delay );
11880 },
11881
11882 // With no arguments, closes the currently active menu - if nothing is active
11883 // it closes all menus. If passed an argument, it will search for menus BELOW
11884 _close: function( startMenu ) {
11885 if ( !startMenu ) {
11886 startMenu = this.active ? this.active.parent() : this.element;
11887 }
11888
11889 startMenu
11890 .find( ".ui-menu" )
11891 .hide()
11892 .attr( "aria-hidden", "true" )
11893 .attr( "aria-expanded", "false" )
11894 .end()
11895 .find( "a.ui-state-active" )
11896 .removeClass( "ui-state-active" );
11897 },
11898
11899 collapse: function( event ) {
11900 var newItem = this.active &&
11901 this.active.parent().closest( ".ui-menu-item", this.element );
11902 if ( newItem && newItem.length ) {
11903 this._close();
11904 this.focus( event, newItem );
11905 }
11906 },
11907
11908 expand: function( event ) {
11909 var newItem = this.active &&
11910 this.active
11911 .children( ".ui-menu " )
11912 .children( ".ui-menu-item" )
11913 .first();
11914
11915 if ( newItem && newItem.length ) {
11916 this._open( newItem.parent() );
11917
11918 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
11919 this._delay(function() {
11920 this.focus( event, newItem );
11921 });
11922 }
11923 },
11924
11925 next: function( event ) {
11926 this._move( "next", "first", event );
11927 },
11928
11929 previous: function( event ) {
11930 this._move( "prev", "last", event );
11931 },
11932
11933 isFirstItem: function() {
11934 return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
11935 },
11936
11937 isLastItem: function() {
11938 return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
11939 },
11940
11941 _move: function( direction, filter, event ) {
11942 var next;
11943 if ( this.active ) {
11944 if ( direction === "first" || direction === "last" ) {
11945 next = this.active
11946 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
11947 .eq( -1 );
11948 } else {
11949 next = this.active
11950 [ direction + "All" ]( ".ui-menu-item" )
11951 .eq( 0 );
11952 }
11953 }
11954 if ( !next || !next.length || !this.active ) {
11955 next = this.activeMenu.children( ".ui-menu-item" )[ filter ]();
11956 }
11957
11958 this.focus( event, next );
11959 },
11960
11961 nextPage: function( event ) {
11962 var item, base, height;
11963
11964 if ( !this.active ) {
11965 this.next( event );
11966 return;
11967 }
11968 if ( this.isLastItem() ) {
11969 return;
11970 }
11971 if ( this._hasScroll() ) {
11972 base = this.active.offset().top;
11973 height = this.element.height();
11974 this.active.nextAll( ".ui-menu-item" ).each(function() {
11975 item = $( this );
11976 return item.offset().top - base - height < 0;
11977 });
11978
11979 this.focus( event, item );
11980 } else {
11981 this.focus( event, this.activeMenu.children( ".ui-menu-item" )
11982 [ !this.active ? "first" : "last" ]() );
11983 }
11984 },
11985
11986 previousPage: function( event ) {
11987 var item, base, height;
11988 if ( !this.active ) {
11989 this.next( event );
11990 return;
11991 }
11992 if ( this.isFirstItem() ) {
11993 return;
11994 }
11995 if ( this._hasScroll() ) {
11996 base = this.active.offset().top;
11997 height = this.element.height();
11998 this.active.prevAll( ".ui-menu-item" ).each(function() {
11999 item = $( this );
12000 return item.offset().top - base + height > 0;
12001 });
12002
12003 this.focus( event, item );
12004 } else {
12005 this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() );
12006 }
12007 },
12008
12009 _hasScroll: function() {
12010 return this.element.outerHeight() < this.element.prop( "scrollHeight" );
12011 },
12012
12013 select: function( event ) {
12014 // TODO: It should never be possible to not have an active item at this
12015 // point, but the tests don't trigger mouseenter before click.
12016 this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
12017 var ui = { item: this.active };
12018 if ( !this.active.has( ".ui-menu" ).length ) {
12019 this.collapseAll( event, true );
12020 }
12021 this._trigger( "select", event, ui );
12022 }
12023});
12024
12025}( jQuery ));
12026
12027(function( $, undefined ) {
12028
12029$.ui = $.ui || {};
12030
12031var cachedScrollbarWidth,
12032 max = Math.max,
12033 abs = Math.abs,
12034 round = Math.round,
12035 rhorizontal = /left|center|right/,
12036 rvertical = /top|center|bottom/,
12037 roffset = /[\+\-]\d+(\.[\d]+)?%?/,
12038 rposition = /^\w+/,
12039 rpercent = /%$/,
12040 _position = $.fn.position;
12041
12042function getOffsets( offsets, width, height ) {
12043 return [
12044 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
12045 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
12046 ];
12047}
12048
12049function parseCss( element, property ) {
12050 return parseInt( $.css( element, property ), 10 ) || 0;
12051}
12052
12053function getDimensions( elem ) {
12054 var raw = elem[0];
12055 if ( raw.nodeType === 9 ) {
12056 return {
12057 width: elem.width(),
12058 height: elem.height(),
12059 offset: { top: 0, left: 0 }
12060 };
12061 }
12062 if ( $.isWindow( raw ) ) {
12063 return {
12064 width: elem.width(),
12065 height: elem.height(),
12066 offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
12067 };
12068 }
12069 if ( raw.preventDefault ) {
12070 return {
12071 width: 0,
12072 height: 0,
12073 offset: { top: raw.pageY, left: raw.pageX }
12074 };
12075 }
12076 return {
12077 width: elem.outerWidth(),
12078 height: elem.outerHeight(),
12079 offset: elem.offset()
12080 };
12081}
12082
12083$.position = {
12084 scrollbarWidth: function() {
12085 if ( cachedScrollbarWidth !== undefined ) {
12086 return cachedScrollbarWidth;
12087 }
12088 var w1, w2,
12089 div = $( "<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
12090 innerDiv = div.children()[0];
12091
12092 $( "body" ).append( div );
12093 w1 = innerDiv.offsetWidth;
12094 div.css( "overflow", "scroll" );
12095
12096 w2 = innerDiv.offsetWidth;
12097
12098 if ( w1 === w2 ) {
12099 w2 = div[0].clientWidth;
12100 }
12101
12102 div.remove();
12103
12104 return (cachedScrollbarWidth = w1 - w2);
12105 },
12106 getScrollInfo: function( within ) {
12107 var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ),
12108 overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ),
12109 hasOverflowX = overflowX === "scroll" ||
12110 ( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
12111 hasOverflowY = overflowY === "scroll" ||
12112 ( overflowY === "auto" && within.height < within.element[0].scrollHeight );
12113 return {
12114 width: hasOverflowY ? $.position.scrollbarWidth() : 0,
12115 height: hasOverflowX ? $.position.scrollbarWidth() : 0
12116 };
12117 },
12118 getWithinInfo: function( element ) {
12119 var withinElement = $( element || window ),
12120 isWindow = $.isWindow( withinElement[0] );
12121 return {
12122 element: withinElement,
12123 isWindow: isWindow,
12124 offset: withinElement.offset() || { left: 0, top: 0 },
12125 scrollLeft: withinElement.scrollLeft(),
12126 scrollTop: withinElement.scrollTop(),
12127 width: isWindow ? withinElement.width() : withinElement.outerWidth(),
12128 height: isWindow ? withinElement.height() : withinElement.outerHeight()
12129 };
12130 }
12131};
12132
12133$.fn.position = function( options ) {
12134 if ( !options || !options.of ) {
12135 return _position.apply( this, arguments );
12136 }
12137
12138 // make a copy, we don't want to modify arguments
12139 options = $.extend( {}, options );
12140
12141 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
12142 target = $( options.of ),
12143 within = $.position.getWithinInfo( options.within ),
12144 scrollInfo = $.position.getScrollInfo( within ),
12145 collision = ( options.collision || "flip" ).split( " " ),
12146 offsets = {};
12147
12148 dimensions = getDimensions( target );
12149 if ( target[0].preventDefault ) {
12150 // force left top to allow flipping
12151 options.at = "left top";
12152 }
12153 targetWidth = dimensions.width;
12154 targetHeight = dimensions.height;
12155 targetOffset = dimensions.offset;
12156 // clone to reuse original targetOffset later
12157 basePosition = $.extend( {}, targetOffset );
12158
12159 // force my and at to have valid horizontal and vertical positions
12160 // if a value is missing or invalid, it will be converted to center
12161 $.each( [ "my", "at" ], function() {
12162 var pos = ( options[ this ] || "" ).split( " " ),
12163 horizontalOffset,
12164 verticalOffset;
12165
12166 if ( pos.length === 1) {
12167 pos = rhorizontal.test( pos[ 0 ] ) ?
12168 pos.concat( [ "center" ] ) :
12169 rvertical.test( pos[ 0 ] ) ?
12170 [ "center" ].concat( pos ) :
12171 [ "center", "center" ];
12172 }
12173 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
12174 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
12175
12176 // calculate offsets
12177 horizontalOffset = roffset.exec( pos[ 0 ] );
12178 verticalOffset = roffset.exec( pos[ 1 ] );
12179 offsets[ this ] = [
12180 horizontalOffset ? horizontalOffset[ 0 ] : 0,
12181 verticalOffset ? verticalOffset[ 0 ] : 0
12182 ];
12183
12184 // reduce to just the positions without the offsets
12185 options[ this ] = [
12186 rposition.exec( pos[ 0 ] )[ 0 ],
12187 rposition.exec( pos[ 1 ] )[ 0 ]
12188 ];
12189 });
12190
12191 // normalize collision option
12192 if ( collision.length === 1 ) {
12193 collision[ 1 ] = collision[ 0 ];
12194 }
12195
12196 if ( options.at[ 0 ] === "right" ) {
12197 basePosition.left += targetWidth;
12198 } else if ( options.at[ 0 ] === "center" ) {
12199 basePosition.left += targetWidth / 2;
12200 }
12201
12202 if ( options.at[ 1 ] === "bottom" ) {
12203 basePosition.top += targetHeight;
12204 } else if ( options.at[ 1 ] === "center" ) {
12205 basePosition.top += targetHeight / 2;
12206 }
12207
12208 atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
12209 basePosition.left += atOffset[ 0 ];
12210 basePosition.top += atOffset[ 1 ];
12211
12212 return this.each(function() {
12213 var collisionPosition, using,
12214 elem = $( this ),
12215 elemWidth = elem.outerWidth(),
12216 elemHeight = elem.outerHeight(),
12217 marginLeft = parseCss( this, "marginLeft" ),
12218 marginTop = parseCss( this, "marginTop" ),
12219 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
12220 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
12221 position = $.extend( {}, basePosition ),
12222 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
12223
12224 if ( options.my[ 0 ] === "right" ) {
12225 position.left -= elemWidth;
12226 } else if ( options.my[ 0 ] === "center" ) {
12227 position.left -= elemWidth / 2;
12228 }
12229
12230 if ( options.my[ 1 ] === "bottom" ) {
12231 position.top -= elemHeight;
12232 } else if ( options.my[ 1 ] === "center" ) {
12233 position.top -= elemHeight / 2;
12234 }
12235
12236 position.left += myOffset[ 0 ];
12237 position.top += myOffset[ 1 ];
12238
12239 // if the browser doesn't support fractions, then round for consistent results
12240 if ( !$.support.offsetFractions ) {
12241 position.left = round( position.left );
12242 position.top = round( position.top );
12243 }
12244
12245 collisionPosition = {
12246 marginLeft: marginLeft,
12247 marginTop: marginTop
12248 };
12249
12250 $.each( [ "left", "top" ], function( i, dir ) {
12251 if ( $.ui.position[ collision[ i ] ] ) {
12252 $.ui.position[ collision[ i ] ][ dir ]( position, {
12253 targetWidth: targetWidth,
12254 targetHeight: targetHeight,
12255 elemWidth: elemWidth,
12256 elemHeight: elemHeight,
12257 collisionPosition: collisionPosition,
12258 collisionWidth: collisionWidth,
12259 collisionHeight: collisionHeight,
12260 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
12261 my: options.my,
12262 at: options.at,
12263 within: within,
12264 elem : elem
12265 });
12266 }
12267 });
12268
12269 if ( options.using ) {
12270 // adds feedback as second argument to using callback, if present
12271 using = function( props ) {
12272 var left = targetOffset.left - position.left,
12273 right = left + targetWidth - elemWidth,
12274 top = targetOffset.top - position.top,
12275 bottom = top + targetHeight - elemHeight,
12276 feedback = {
12277 target: {
12278 element: target,
12279 left: targetOffset.left,
12280 top: targetOffset.top,
12281 width: targetWidth,
12282 height: targetHeight
12283 },
12284 element: {
12285 element: elem,
12286 left: position.left,
12287 top: position.top,
12288 width: elemWidth,
12289 height: elemHeight
12290 },
12291 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
12292 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
12293 };
12294 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
12295 feedback.horizontal = "center";
12296 }
12297 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
12298 feedback.vertical = "middle";
12299 }
12300 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
12301 feedback.important = "horizontal";
12302 } else {
12303 feedback.important = "vertical";
12304 }
12305 options.using.call( this, props, feedback );
12306 };
12307 }
12308
12309 elem.offset( $.extend( position, { using: using } ) );
12310 });
12311};
12312
12313$.ui.position = {
12314 fit: {
12315 left: function( position, data ) {
12316 var within = data.within,
12317 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
12318 outerWidth = within.width,
12319 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
12320 overLeft = withinOffset - collisionPosLeft,
12321 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
12322 newOverRight;
12323
12324 // element is wider than within
12325 if ( data.collisionWidth > outerWidth ) {
12326 // element is initially over the left side of within
12327 if ( overLeft > 0 && overRight <= 0 ) {
12328 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
12329 position.left += overLeft - newOverRight;
12330 // element is initially over right side of within
12331 } else if ( overRight > 0 && overLeft <= 0 ) {
12332 position.left = withinOffset;
12333 // element is initially over both left and right sides of within
12334 } else {
12335 if ( overLeft > overRight ) {
12336 position.left = withinOffset + outerWidth - data.collisionWidth;
12337 } else {
12338 position.left = withinOffset;
12339 }
12340 }
12341 // too far left -> align with left edge
12342 } else if ( overLeft > 0 ) {
12343 position.left += overLeft;
12344 // too far right -> align with right edge
12345 } else if ( overRight > 0 ) {
12346 position.left -= overRight;
12347 // adjust based on position and margin
12348 } else {
12349 position.left = max( position.left - collisionPosLeft, position.left );
12350 }
12351 },
12352 top: function( position, data ) {
12353 var within = data.within,
12354 withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
12355 outerHeight = data.within.height,
12356 collisionPosTop = position.top - data.collisionPosition.marginTop,
12357 overTop = withinOffset - collisionPosTop,
12358 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
12359 newOverBottom;
12360
12361 // element is taller than within
12362 if ( data.collisionHeight > outerHeight ) {
12363 // element is initially over the top of within
12364 if ( overTop > 0 && overBottom <= 0 ) {
12365 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
12366 position.top += overTop - newOverBottom;
12367 // element is initially over bottom of within
12368 } else if ( overBottom > 0 && overTop <= 0 ) {
12369 position.top = withinOffset;
12370 // element is initially over both top and bottom of within
12371 } else {
12372 if ( overTop > overBottom ) {
12373 position.top = withinOffset + outerHeight - data.collisionHeight;
12374 } else {
12375 position.top = withinOffset;
12376 }
12377 }
12378 // too far up -> align with top
12379 } else if ( overTop > 0 ) {
12380 position.top += overTop;
12381 // too far down -> align with bottom edge
12382 } else if ( overBottom > 0 ) {
12383 position.top -= overBottom;
12384 // adjust based on position and margin
12385 } else {
12386 position.top = max( position.top - collisionPosTop, position.top );
12387 }
12388 }
12389 },
12390 flip: {
12391 left: function( position, data ) {
12392 var within = data.within,
12393 withinOffset = within.offset.left + within.scrollLeft,
12394 outerWidth = within.width,
12395 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
12396 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
12397 overLeft = collisionPosLeft - offsetLeft,
12398 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
12399 myOffset = data.my[ 0 ] === "left" ?
12400 -data.elemWidth :
12401 data.my[ 0 ] === "right" ?
12402 data.elemWidth :
12403 0,
12404 atOffset = data.at[ 0 ] === "left" ?
12405 data.targetWidth :
12406 data.at[ 0 ] === "right" ?
12407 -data.targetWidth :
12408 0,
12409 offset = -2 * data.offset[ 0 ],
12410 newOverRight,
12411 newOverLeft;
12412
12413 if ( overLeft < 0 ) {
12414 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
12415 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
12416 position.left += myOffset + atOffset + offset;
12417 }
12418 }
12419 else if ( overRight > 0 ) {
12420 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
12421 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
12422 position.left += myOffset + atOffset + offset;
12423 }
12424 }
12425 },
12426 top: function( position, data ) {
12427 var within = data.within,
12428 withinOffset = within.offset.top + within.scrollTop,
12429 outerHeight = within.height,
12430 offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
12431 collisionPosTop = position.top - data.collisionPosition.marginTop,
12432 overTop = collisionPosTop - offsetTop,
12433 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
12434 top = data.my[ 1 ] === "top",
12435 myOffset = top ?
12436 -data.elemHeight :
12437 data.my[ 1 ] === "bottom" ?
12438 data.elemHeight :
12439 0,
12440 atOffset = data.at[ 1 ] === "top" ?
12441 data.targetHeight :
12442 data.at[ 1 ] === "bottom" ?
12443 -data.targetHeight :
12444 0,
12445 offset = -2 * data.offset[ 1 ],
12446 newOverTop,
12447 newOverBottom;
12448 if ( overTop < 0 ) {
12449 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
12450 if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
12451 position.top += myOffset + atOffset + offset;
12452 }
12453 }
12454 else if ( overBottom > 0 ) {
12455 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
12456 if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
12457 position.top += myOffset + atOffset + offset;
12458 }
12459 }
12460 }
12461 },
12462 flipfit: {
12463 left: function() {
12464 $.ui.position.flip.left.apply( this, arguments );
12465 $.ui.position.fit.left.apply( this, arguments );
12466 },
12467 top: function() {
12468 $.ui.position.flip.top.apply( this, arguments );
12469 $.ui.position.fit.top.apply( this, arguments );
12470 }
12471 }
12472};
12473
12474// fraction support test
12475(function () {
12476 var testElement, testElementParent, testElementStyle, offsetLeft, i,
12477 body = document.getElementsByTagName( "body" )[ 0 ],
12478 div = document.createElement( "div" );
12479
12480 //Create a "fake body" for testing based on method used in jQuery.support
12481 testElement = document.createElement( body ? "div" : "body" );
12482 testElementStyle = {
12483 visibility: "hidden",
12484 width: 0,
12485 height: 0,
12486 border: 0,
12487 margin: 0,
12488 background: "none"
12489 };
12490 if ( body ) {
12491 $.extend( testElementStyle, {
12492 position: "absolute",
12493 left: "-1000px",
12494 top: "-1000px"
12495 });
12496 }
12497 for ( i in testElementStyle ) {
12498 testElement.style[ i ] = testElementStyle[ i ];
12499 }
12500 testElement.appendChild( div );
12501 testElementParent = body || document.documentElement;
12502 testElementParent.insertBefore( testElement, testElementParent.firstChild );
12503
12504 div.style.cssText = "position: absolute; left: 10.7432222px;";
12505
12506 offsetLeft = $( div ).offset().left;
12507 $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;
12508
12509 testElement.innerHTML = "";
12510 testElementParent.removeChild( testElement );
12511})();
12512
12513}( jQuery ) );
12514
12515(function( $, undefined ) {
12516
12517$.widget( "ui.progressbar", {
12518 version: "1.10.3",
12519 options: {
12520 max: 100,
12521 value: 0,
12522
12523 change: null,
12524 complete: null
12525 },
12526
12527 min: 0,
12528
12529 _create: function() {
12530 // Constrain initial value
12531 this.oldValue = this.options.value = this._constrainedValue();
12532
12533 this.element
12534 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
12535 .attr({
12536 // Only set static values, aria-valuenow and aria-valuemax are
12537 // set inside _refreshValue()
12538 role: "progressbar",
12539 "aria-valuemin": this.min
12540 });
12541
12542 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
12543 .appendTo( this.element );
12544
12545 this._refreshValue();
12546 },
12547
12548 _destroy: function() {
12549 this.element
12550 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
12551 .removeAttr( "role" )
12552 .removeAttr( "aria-valuemin" )
12553 .removeAttr( "aria-valuemax" )
12554 .removeAttr( "aria-valuenow" );
12555
12556 this.valueDiv.remove();
12557 },
12558
12559 value: function( newValue ) {
12560 if ( newValue === undefined ) {
12561 return this.options.value;
12562 }
12563
12564 this.options.value = this._constrainedValue( newValue );
12565 this._refreshValue();
12566 },
12567
12568 _constrainedValue: function( newValue ) {
12569 if ( newValue === undefined ) {
12570 newValue = this.options.value;
12571 }
12572
12573 this.indeterminate = newValue === false;
12574
12575 // sanitize value
12576 if ( typeof newValue !== "number" ) {
12577 newValue = 0;
12578 }
12579
12580 return this.indeterminate ? false :
12581 Math.min( this.options.max, Math.max( this.min, newValue ) );
12582 },
12583
12584 _setOptions: function( options ) {
12585 // Ensure "value" option is set after other values (like max)
12586 var value = options.value;
12587 delete options.value;
12588
12589 this._super( options );
12590
12591 this.options.value = this._constrainedValue( value );
12592 this._refreshValue();
12593 },
12594
12595 _setOption: function( key, value ) {
12596 if ( key === "max" ) {
12597 // Don't allow a max less than min
12598 value = Math.max( this.min, value );
12599 }
12600
12601 this._super( key, value );
12602 },
12603
12604 _percentage: function() {
12605 return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
12606 },
12607
12608 _refreshValue: function() {
12609 var value = this.options.value,
12610 percentage = this._percentage();
12611
12612 this.valueDiv
12613 .toggle( this.indeterminate || value > this.min )
12614 .toggleClass( "ui-corner-right", value === this.options.max )
12615 .width( percentage.toFixed(0) + "%" );
12616
12617 this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate );
12618
12619 if ( this.indeterminate ) {
12620 this.element.removeAttr( "aria-valuenow" );
12621 if ( !this.overlayDiv ) {
12622 this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv );
12623 }
12624 } else {
12625 this.element.attr({
12626 "aria-valuemax": this.options.max,
12627 "aria-valuenow": value
12628 });
12629 if ( this.overlayDiv ) {
12630 this.overlayDiv.remove();
12631 this.overlayDiv = null;
12632 }
12633 }
12634
12635 if ( this.oldValue !== value ) {
12636 this.oldValue = value;
12637 this._trigger( "change" );
12638 }
12639 if ( value === this.options.max ) {
12640 this._trigger( "complete" );
12641 }
12642 }
12643});
12644
12645})( jQuery );
12646
12647(function( $, undefined ) {
12648
12649// number of pages in a slider
12650// (how many times can you page up/down to go through the whole range)
12651var numPages = 5;
12652
12653$.widget( "ui.slider", $.ui.mouse, {
12654 version: "1.10.3",
12655 widgetEventPrefix: "slide",
12656
12657 options: {
12658 animate: false,
12659 distance: 0,
12660 max: 100,
12661 min: 0,
12662 orientation: "horizontal",
12663 range: false,
12664 step: 1,
12665 value: 0,
12666 values: null,
12667
12668 // callbacks
12669 change: null,
12670 slide: null,
12671 start: null,
12672 stop: null
12673 },
12674
12675 _create: function() {
12676 this._keySliding = false;
12677 this._mouseSliding = false;
12678 this._animateOff = true;
12679 this._handleIndex = null;
12680 this._detectOrientation();
12681 this._mouseInit();
12682
12683 this.element
12684 .addClass( "ui-slider" +
12685 " ui-slider-" + this.orientation +
12686 " ui-widget" +
12687 " ui-widget-content" +
12688 " ui-corner-all");
12689
12690 this._refresh();
12691 this._setOption( "disabled", this.options.disabled );
12692
12693 this._animateOff = false;
12694 },
12695
12696 _refresh: function() {
12697 this._createRange();
12698 this._createHandles();
12699 this._setupEvents();
12700 this._refreshValue();
12701 },
12702
12703 _createHandles: function() {
12704 var i, handleCount,
12705 options = this.options,
12706 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
12707 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
12708 handles = [];
12709
12710 handleCount = ( options.values && options.values.length ) || 1;
12711
12712 if ( existingHandles.length > handleCount ) {
12713 existingHandles.slice( handleCount ).remove();
12714 existingHandles = existingHandles.slice( 0, handleCount );
12715 }
12716
12717 for ( i = existingHandles.length; i < handleCount; i++ ) {
12718 handles.push( handle );
12719 }
12720
12721 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
12722
12723 this.handle = this.handles.eq( 0 );
12724
12725 this.handles.each(function( i ) {
12726 $( this ).data( "ui-slider-handle-index", i );
12727 });
12728 },
12729
12730 _createRange: function() {
12731 var options = this.options,
12732 classes = "";
12733
12734 if ( options.range ) {
12735 if ( options.range === true ) {
12736 if ( !options.values ) {
12737 options.values = [ this._valueMin(), this._valueMin() ];
12738 } else if ( options.values.length && options.values.length !== 2 ) {
12739 options.values = [ options.values[0], options.values[0] ];
12740 } else if ( $.isArray( options.values ) ) {
12741 options.values = options.values.slice(0);
12742 }
12743 }
12744
12745 if ( !this.range || !this.range.length ) {
12746 this.range = $( "<div></div>" )
12747 .appendTo( this.element );
12748
12749 classes = "ui-slider-range" +
12750 // note: this isn't the most fittingly semantic framework class for this element,
12751 // but worked best visually with a variety of themes
12752 " ui-widget-header ui-corner-all";
12753 } else {
12754 this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
12755 // Handle range switching from true to min/max
12756 .css({
12757 "left": "",
12758 "bottom": ""
12759 });
12760 }
12761
12762 this.range.addClass( classes +
12763 ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
12764 } else {
12765 this.range = $([]);
12766 }
12767 },
12768
12769 _setupEvents: function() {
12770 var elements = this.handles.add( this.range ).filter( "a" );
12771 this._off( elements );
12772 this._on( elements, this._handleEvents );
12773 this._hoverable( elements );
12774 this._focusable( elements );
12775 },
12776
12777 _destroy: function() {
12778 this.handles.remove();
12779 this.range.remove();
12780
12781 this.element
12782 .removeClass( "ui-slider" +
12783 " ui-slider-horizontal" +
12784 " ui-slider-vertical" +
12785 " ui-widget" +
12786 " ui-widget-content" +
12787 " ui-corner-all" );
12788
12789 this._mouseDestroy();
12790 },
12791
12792 _mouseCapture: function( event ) {
12793 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
12794 that = this,
12795 o = this.options;
12796
12797 if ( o.disabled ) {
12798 return false;
12799 }
12800
12801 this.elementSize = {
12802 width: this.element.outerWidth(),
12803 height: this.element.outerHeight()
12804 };
12805 this.elementOffset = this.element.offset();
12806
12807 position = { x: event.pageX, y: event.pageY };
12808 normValue = this._normValueFromMouse( position );
12809 distance = this._valueMax() - this._valueMin() + 1;
12810 this.handles.each(function( i ) {
12811 var thisDistance = Math.abs( normValue - that.values(i) );
12812 if (( distance > thisDistance ) ||
12813 ( distance === thisDistance &&
12814 (i === that._lastChangedValue || that.values(i) === o.min ))) {
12815 distance = thisDistance;
12816 closestHandle = $( this );
12817 index = i;
12818 }
12819 });
12820
12821 allowed = this._start( event, index );
12822 if ( allowed === false ) {
12823 return false;
12824 }
12825 this._mouseSliding = true;
12826
12827 this._handleIndex = index;
12828
12829 closestHandle
12830 .addClass( "ui-state-active" )
12831 .focus();
12832
12833 offset = closestHandle.offset();
12834 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
12835 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
12836 left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
12837 top: event.pageY - offset.top -
12838 ( closestHandle.height() / 2 ) -
12839 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
12840 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
12841 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
12842 };
12843
12844 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
12845 this._slide( event, index, normValue );
12846 }
12847 this._animateOff = true;
12848 return true;
12849 },
12850
12851 _mouseStart: function() {
12852 return true;
12853 },
12854
12855 _mouseDrag: function( event ) {
12856 var position = { x: event.pageX, y: event.pageY },
12857 normValue = this._normValueFromMouse( position );
12858
12859 this._slide( event, this._handleIndex, normValue );
12860
12861 return false;
12862 },
12863
12864 _mouseStop: function( event ) {
12865 this.handles.removeClass( "ui-state-active" );
12866 this._mouseSliding = false;
12867
12868 this._stop( event, this._handleIndex );
12869 this._change( event, this._handleIndex );
12870
12871 this._handleIndex = null;
12872 this._clickOffset = null;
12873 this._animateOff = false;
12874
12875 return false;
12876 },
12877
12878 _detectOrientation: function() {
12879 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
12880 },
12881
12882 _normValueFromMouse: function( position ) {
12883 var pixelTotal,
12884 pixelMouse,
12885 percentMouse,
12886 valueTotal,
12887 valueMouse;
12888
12889 if ( this.orientation === "horizontal" ) {
12890 pixelTotal = this.elementSize.width;
12891 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
12892 } else {
12893 pixelTotal = this.elementSize.height;
12894 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
12895 }
12896
12897 percentMouse = ( pixelMouse / pixelTotal );
12898 if ( percentMouse > 1 ) {
12899 percentMouse = 1;
12900 }
12901 if ( percentMouse < 0 ) {
12902 percentMouse = 0;
12903 }
12904 if ( this.orientation === "vertical" ) {
12905 percentMouse = 1 - percentMouse;
12906 }
12907
12908 valueTotal = this._valueMax() - this._valueMin();
12909 valueMouse = this._valueMin() + percentMouse * valueTotal;
12910
12911 return this._trimAlignValue( valueMouse );
12912 },
12913
12914 _start: function( event, index ) {
12915 var uiHash = {
12916 handle: this.handles[ index ],
12917 value: this.value()
12918 };
12919 if ( this.options.values && this.options.values.length ) {
12920 uiHash.value = this.values( index );
12921 uiHash.values = this.values();
12922 }
12923 return this._trigger( "start", event, uiHash );
12924 },
12925
12926 _slide: function( event, index, newVal ) {
12927 var otherVal,
12928 newValues,
12929 allowed;
12930
12931 if ( this.options.values && this.options.values.length ) {
12932 otherVal = this.values( index ? 0 : 1 );
12933
12934 if ( ( this.options.values.length === 2 && this.options.range === true ) &&
12935 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
12936 ) {
12937 newVal = otherVal;
12938 }
12939
12940 if ( newVal !== this.values( index ) ) {
12941 newValues = this.values();
12942 newValues[ index ] = newVal;
12943 // A slide can be canceled by returning false from the slide callback
12944 allowed = this._trigger( "slide", event, {
12945 handle: this.handles[ index ],
12946 value: newVal,
12947 values: newValues
12948 } );
12949 otherVal = this.values( index ? 0 : 1 );
12950 if ( allowed !== false ) {
12951 this.values( index, newVal, true );
12952 }
12953 }
12954 } else {
12955 if ( newVal !== this.value() ) {
12956 // A slide can be canceled by returning false from the slide callback
12957 allowed = this._trigger( "slide", event, {
12958 handle: this.handles[ index ],
12959 value: newVal
12960 } );
12961 if ( allowed !== false ) {
12962 this.value( newVal );
12963 }
12964 }
12965 }
12966 },
12967
12968 _stop: function( event, index ) {
12969 var uiHash = {
12970 handle: this.handles[ index ],
12971 value: this.value()
12972 };
12973 if ( this.options.values && this.options.values.length ) {
12974 uiHash.value = this.values( index );
12975 uiHash.values = this.values();
12976 }
12977
12978 this._trigger( "stop", event, uiHash );
12979 },
12980
12981 _change: function( event, index ) {
12982 if ( !this._keySliding && !this._mouseSliding ) {
12983 var uiHash = {
12984 handle: this.handles[ index ],
12985 value: this.value()
12986 };
12987 if ( this.options.values && this.options.values.length ) {
12988 uiHash.value = this.values( index );
12989 uiHash.values = this.values();
12990 }
12991
12992 //store the last changed value index for reference when handles overlap
12993 this._lastChangedValue = index;
12994
12995 this._trigger( "change", event, uiHash );
12996 }
12997 },
12998
12999 value: function( newValue ) {
13000 if ( arguments.length ) {
13001 this.options.value = this._trimAlignValue( newValue );
13002 this._refreshValue();
13003 this._change( null, 0 );
13004 return;
13005 }
13006
13007 return this._value();
13008 },
13009
13010 values: function( index, newValue ) {
13011 var vals,
13012 newValues,
13013 i;
13014
13015 if ( arguments.length > 1 ) {
13016 this.options.values[ index ] = this._trimAlignValue( newValue );
13017 this._refreshValue();
13018 this._change( null, index );
13019 return;
13020 }
13021
13022 if ( arguments.length ) {
13023 if ( $.isArray( arguments[ 0 ] ) ) {
13024 vals = this.options.values;
13025 newValues = arguments[ 0 ];
13026 for ( i = 0; i < vals.length; i += 1 ) {
13027 vals[ i ] = this._trimAlignValue( newValues[ i ] );
13028 this._change( null, i );
13029 }
13030 this._refreshValue();
13031 } else {
13032 if ( this.options.values && this.options.values.length ) {
13033 return this._values( index );
13034 } else {
13035 return this.value();
13036 }
13037 }
13038 } else {
13039 return this._values();
13040 }
13041 },
13042
13043 _setOption: function( key, value ) {
13044 var i,
13045 valsLength = 0;
13046
13047 if ( key === "range" && this.options.range === true ) {
13048 if ( value === "min" ) {
13049 this.options.value = this._values( 0 );
13050 this.options.values = null;
13051 } else if ( value === "max" ) {
13052 this.options.value = this._values( this.options.values.length-1 );
13053 this.options.values = null;
13054 }
13055 }
13056
13057 if ( $.isArray( this.options.values ) ) {
13058 valsLength = this.options.values.length;
13059 }
13060
13061 $.Widget.prototype._setOption.apply( this, arguments );
13062
13063 switch ( key ) {
13064 case "orientation":
13065 this._detectOrientation();
13066 this.element
13067 .removeClass( "ui-slider-horizontal ui-slider-vertical" )
13068 .addClass( "ui-slider-" + this.orientation );
13069 this._refreshValue();
13070 break;
13071 case "value":
13072 this._animateOff = true;
13073 this._refreshValue();
13074 this._change( null, 0 );
13075 this._animateOff = false;
13076 break;
13077 case "values":
13078 this._animateOff = true;
13079 this._refreshValue();
13080 for ( i = 0; i < valsLength; i += 1 ) {
13081 this._change( null, i );
13082 }
13083 this._animateOff = false;
13084 break;
13085 case "min":
13086 case "max":
13087 this._animateOff = true;
13088 this._refreshValue();
13089 this._animateOff = false;
13090 break;
13091 case "range":
13092 this._animateOff = true;
13093 this._refresh();
13094 this._animateOff = false;
13095 break;
13096 }
13097 },
13098
13099 //internal value getter
13100 // _value() returns value trimmed by min and max, aligned by step
13101 _value: function() {
13102 var val = this.options.value;
13103 val = this._trimAlignValue( val );
13104
13105 return val;
13106 },
13107
13108 //internal values getter
13109 // _values() returns array of values trimmed by min and max, aligned by step
13110 // _values( index ) returns single value trimmed by min and max, aligned by step
13111 _values: function( index ) {
13112 var val,
13113 vals,
13114 i;
13115
13116 if ( arguments.length ) {
13117 val = this.options.values[ index ];
13118 val = this._trimAlignValue( val );
13119
13120 return val;
13121 } else if ( this.options.values && this.options.values.length ) {
13122 // .slice() creates a copy of the array
13123 // this copy gets trimmed by min and max and then returned
13124 vals = this.options.values.slice();
13125 for ( i = 0; i < vals.length; i+= 1) {
13126 vals[ i ] = this._trimAlignValue( vals[ i ] );
13127 }
13128
13129 return vals;
13130 } else {
13131 return [];
13132 }
13133 },
13134
13135 // returns the step-aligned value that val is closest to, between (inclusive) min and max
13136 _trimAlignValue: function( val ) {
13137 if ( val <= this._valueMin() ) {
13138 return this._valueMin();
13139 }
13140 if ( val >= this._valueMax() ) {
13141 return this._valueMax();
13142 }
13143 var step = ( this.options.step > 0 ) ? this.options.step : 1,
13144 valModStep = (val - this._valueMin()) % step,
13145 alignValue = val - valModStep;
13146
13147 if ( Math.abs(valModStep) * 2 >= step ) {
13148 alignValue += ( valModStep > 0 ) ? step : ( -step );
13149 }
13150
13151 // Since JavaScript has problems with large floats, round
13152 // the final value to 5 digits after the decimal point (see #4124)
13153 return parseFloat( alignValue.toFixed(5) );
13154 },
13155
13156 _valueMin: function() {
13157 return this.options.min;
13158 },
13159
13160 _valueMax: function() {
13161 return this.options.max;
13162 },
13163
13164 _refreshValue: function() {
13165 var lastValPercent, valPercent, value, valueMin, valueMax,
13166 oRange = this.options.range,
13167 o = this.options,
13168 that = this,
13169 animate = ( !this._animateOff ) ? o.animate : false,
13170 _set = {};
13171
13172 if ( this.options.values && this.options.values.length ) {
13173 this.handles.each(function( i ) {
13174 valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
13175 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
13176 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
13177 if ( that.options.range === true ) {
13178 if ( that.orientation === "horizontal" ) {
13179 if ( i === 0 ) {
13180 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
13181 }
13182 if ( i === 1 ) {
13183 that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
13184 }
13185 } else {
13186 if ( i === 0 ) {
13187 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
13188 }
13189 if ( i === 1 ) {
13190 that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
13191 }
13192 }
13193 }
13194 lastValPercent = valPercent;
13195 });
13196 } else {
13197 value = this.value();
13198 valueMin = this._valueMin();
13199 valueMax = this._valueMax();
13200 valPercent = ( valueMax !== valueMin ) ?
13201 ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
13202 0;
13203 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
13204 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
13205
13206 if ( oRange === "min" && this.orientation === "horizontal" ) {
13207 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
13208 }
13209 if ( oRange === "max" && this.orientation === "horizontal" ) {
13210 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
13211 }
13212 if ( oRange === "min" && this.orientation === "vertical" ) {
13213 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
13214 }
13215 if ( oRange === "max" && this.orientation === "vertical" ) {
13216 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
13217 }
13218 }
13219 },
13220
13221 _handleEvents: {
13222 keydown: function( event ) {
13223 /*jshint maxcomplexity:25*/
13224 var allowed, curVal, newVal, step,
13225 index = $( event.target ).data( "ui-slider-handle-index" );
13226
13227 switch ( event.keyCode ) {
13228 case $.ui.keyCode.HOME:
13229 case $.ui.keyCode.END:
13230 case $.ui.keyCode.PAGE_UP:
13231 case $.ui.keyCode.PAGE_DOWN:
13232 case $.ui.keyCode.UP:
13233 case $.ui.keyCode.RIGHT:
13234 case $.ui.keyCode.DOWN:
13235 case $.ui.keyCode.LEFT:
13236 event.preventDefault();
13237 if ( !this._keySliding ) {
13238 this._keySliding = true;
13239 $( event.target ).addClass( "ui-state-active" );
13240 allowed = this._start( event, index );
13241 if ( allowed === false ) {
13242 return;
13243 }
13244 }
13245 break;
13246 }
13247
13248 step = this.options.step;
13249 if ( this.options.values && this.options.values.length ) {
13250 curVal = newVal = this.values( index );
13251 } else {
13252 curVal = newVal = this.value();
13253 }
13254
13255 switch ( event.keyCode ) {
13256 case $.ui.keyCode.HOME:
13257 newVal = this._valueMin();
13258 break;
13259 case $.ui.keyCode.END:
13260 newVal = this._valueMax();
13261 break;
13262 case $.ui.keyCode.PAGE_UP:
13263 newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) );
13264 break;
13265 case $.ui.keyCode.PAGE_DOWN:
13266 newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) );
13267 break;
13268 case $.ui.keyCode.UP:
13269 case $.ui.keyCode.RIGHT:
13270 if ( curVal === this._valueMax() ) {
13271 return;
13272 }
13273 newVal = this._trimAlignValue( curVal + step );
13274 break;
13275 case $.ui.keyCode.DOWN:
13276 case $.ui.keyCode.LEFT:
13277 if ( curVal === this._valueMin() ) {
13278 return;
13279 }
13280 newVal = this._trimAlignValue( curVal - step );
13281 break;
13282 }
13283
13284 this._slide( event, index, newVal );
13285 },
13286 click: function( event ) {
13287 event.preventDefault();
13288 },
13289 keyup: function( event ) {
13290 var index = $( event.target ).data( "ui-slider-handle-index" );
13291
13292 if ( this._keySliding ) {
13293 this._keySliding = false;
13294 this._stop( event, index );
13295 this._change( event, index );
13296 $( event.target ).removeClass( "ui-state-active" );
13297 }
13298 }
13299 }
13300
13301});
13302
13303}(jQuery));
13304
13305(function( $ ) {
13306
13307function modifier( fn ) {
13308 return function() {
13309 var previous = this.element.val();
13310 fn.apply( this, arguments );
13311 this._refresh();
13312 if ( previous !== this.element.val() ) {
13313 this._trigger( "change" );
13314 }
13315 };
13316}
13317
13318$.widget( "ui.spinner", {
13319 version: "1.10.3",
13320 defaultElement: "<input>",
13321 widgetEventPrefix: "spin",
13322 options: {
13323 culture: null,
13324 icons: {
13325 down: "ui-icon-triangle-1-s",
13326 up: "ui-icon-triangle-1-n"
13327 },
13328 incremental: true,
13329 max: null,
13330 min: null,
13331 numberFormat: null,
13332 page: 10,
13333 step: 1,
13334
13335 change: null,
13336 spin: null,
13337 start: null,
13338 stop: null
13339 },
13340
13341 _create: function() {
13342 // handle string values that need to be parsed
13343 this._setOption( "max", this.options.max );
13344 this._setOption( "min", this.options.min );
13345 this._setOption( "step", this.options.step );
13346
13347 // format the value, but don't constrain
13348 this._value( this.element.val(), true );
13349
13350 this._draw();
13351 this._on( this._events );
13352 this._refresh();
13353
13354 // turning off autocomplete prevents the browser from remembering the
13355 // value when navigating through history, so we re-enable autocomplete
13356 // if the page is unloaded before the widget is destroyed. #7790
13357 this._on( this.window, {
13358 beforeunload: function() {
13359 this.element.removeAttr( "autocomplete" );
13360 }
13361 });
13362 },
13363
13364 _getCreateOptions: function() {
13365 var options = {},
13366 element = this.element;
13367
13368 $.each( [ "min", "max", "step" ], function( i, option ) {
13369 var value = element.attr( option );
13370 if ( value !== undefined && value.length ) {
13371 options[ option ] = value;
13372 }
13373 });
13374
13375 return options;
13376 },
13377
13378 _events: {
13379 keydown: function( event ) {
13380 if ( this._start( event ) && this._keydown( event ) ) {
13381 event.preventDefault();
13382 }
13383 },
13384 keyup: "_stop",
13385 focus: function() {
13386 this.previous = this.element.val();
13387 },
13388 blur: function( event ) {
13389 if ( this.cancelBlur ) {
13390 delete this.cancelBlur;
13391 return;
13392 }
13393
13394 this._stop();
13395 this._refresh();
13396 if ( this.previous !== this.element.val() ) {
13397 this._trigger( "change", event );
13398 }
13399 },
13400 mousewheel: function( event, delta ) {
13401 if ( !delta ) {
13402 return;
13403 }
13404 if ( !this.spinning && !this._start( event ) ) {
13405 return false;
13406 }
13407
13408 this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
13409 clearTimeout( this.mousewheelTimer );
13410 this.mousewheelTimer = this._delay(function() {
13411 if ( this.spinning ) {
13412 this._stop( event );
13413 }
13414 }, 100 );
13415 event.preventDefault();
13416 },
13417 "mousedown .ui-spinner-button": function( event ) {
13418 var previous;
13419
13420 // We never want the buttons to have focus; whenever the user is
13421 // interacting with the spinner, the focus should be on the input.
13422 // If the input is focused then this.previous is properly set from
13423 // when the input first received focus. If the input is not focused
13424 // then we need to set this.previous based on the value before spinning.
13425 previous = this.element[0] === this.document[0].activeElement ?
13426 this.previous : this.element.val();
13427 function checkFocus() {
13428 var isActive = this.element[0] === this.document[0].activeElement;
13429 if ( !isActive ) {
13430 this.element.focus();
13431 this.previous = previous;
13432 // support: IE
13433 // IE sets focus asynchronously, so we need to check if focus
13434 // moved off of the input because the user clicked on the button.
13435 this._delay(function() {
13436 this.previous = previous;
13437 });
13438 }
13439 }
13440
13441 // ensure focus is on (or stays on) the text field
13442 event.preventDefault();
13443 checkFocus.call( this );
13444
13445 // support: IE
13446 // IE doesn't prevent moving focus even with event.preventDefault()
13447 // so we set a flag to know when we should ignore the blur event
13448 // and check (again) if focus moved off of the input.
13449 this.cancelBlur = true;
13450 this._delay(function() {
13451 delete this.cancelBlur;
13452 checkFocus.call( this );
13453 });
13454
13455 if ( this._start( event ) === false ) {
13456 return;
13457 }
13458
13459 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
13460 },
13461 "mouseup .ui-spinner-button": "_stop",
13462 "mouseenter .ui-spinner-button": function( event ) {
13463 // button will add ui-state-active if mouse was down while mouseleave and kept down
13464 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
13465 return;
13466 }
13467
13468 if ( this._start( event ) === false ) {
13469 return false;
13470 }
13471 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
13472 },
13473 // TODO: do we really want to consider this a stop?
13474 // shouldn't we just stop the repeater and wait until mouseup before
13475 // we trigger the stop event?
13476 "mouseleave .ui-spinner-button": "_stop"
13477 },
13478
13479 _draw: function() {
13480 var uiSpinner = this.uiSpinner = this.element
13481 .addClass( "ui-spinner-input" )
13482 .attr( "autocomplete", "off" )
13483 .wrap( this._uiSpinnerHtml() )
13484 .parent()
13485 // add buttons
13486 .append( this._buttonHtml() );
13487
13488 this.element.attr( "role", "spinbutton" );
13489
13490 // button bindings
13491 this.buttons = uiSpinner.find( ".ui-spinner-button" )
13492 .attr( "tabIndex", -1 )
13493 .button()
13494 .removeClass( "ui-corner-all" );
13495
13496 // IE 6 doesn't understand height: 50% for the buttons
13497 // unless the wrapper has an explicit height
13498 if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
13499 uiSpinner.height() > 0 ) {
13500 uiSpinner.height( uiSpinner.height() );
13501 }
13502
13503 // disable spinner if element was already disabled
13504 if ( this.options.disabled ) {
13505 this.disable();
13506 }
13507 },
13508
13509 _keydown: function( event ) {
13510 var options = this.options,
13511 keyCode = $.ui.keyCode;
13512
13513 switch ( event.keyCode ) {
13514 case keyCode.UP:
13515 this._repeat( null, 1, event );
13516 return true;
13517 case keyCode.DOWN:
13518 this._repeat( null, -1, event );
13519 return true;
13520 case keyCode.PAGE_UP:
13521 this._repeat( null, options.page, event );
13522 return true;
13523 case keyCode.PAGE_DOWN:
13524 this._repeat( null, -options.page, event );
13525 return true;
13526 }
13527
13528 return false;
13529 },
13530
13531 _uiSpinnerHtml: function() {
13532 return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
13533 },
13534
13535 _buttonHtml: function() {
13536 return "" +
13537 "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
13538 "<span class='ui-icon " + this.options.icons.up + "'>&#9650;</span>" +
13539 "</a>" +
13540 "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
13541 "<span class='ui-icon " + this.options.icons.down + "'>&#9660;</span>" +
13542 "</a>";
13543 },
13544
13545 _start: function( event ) {
13546 if ( !this.spinning && this._trigger( "start", event ) === false ) {
13547 return false;
13548 }
13549
13550 if ( !this.counter ) {
13551 this.counter = 1;
13552 }
13553 this.spinning = true;
13554 return true;
13555 },
13556
13557 _repeat: function( i, steps, event ) {
13558 i = i || 500;
13559
13560 clearTimeout( this.timer );
13561 this.timer = this._delay(function() {
13562 this._repeat( 40, steps, event );
13563 }, i );
13564
13565 this._spin( steps * this.options.step, event );
13566 },
13567
13568 _spin: function( step, event ) {
13569 var value = this.value() || 0;
13570
13571 if ( !this.counter ) {
13572 this.counter = 1;
13573 }
13574
13575 value = this._adjustValue( value + step * this._increment( this.counter ) );
13576
13577 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
13578 this._value( value );
13579 this.counter++;
13580 }
13581 },
13582
13583 _increment: function( i ) {
13584 var incremental = this.options.incremental;
13585
13586 if ( incremental ) {
13587 return $.isFunction( incremental ) ?
13588 incremental( i ) :
13589 Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 );
13590 }
13591
13592 return 1;
13593 },
13594
13595 _precision: function() {
13596 var precision = this._precisionOf( this.options.step );
13597 if ( this.options.min !== null ) {
13598 precision = Math.max( precision, this._precisionOf( this.options.min ) );
13599 }
13600 return precision;
13601 },
13602
13603 _precisionOf: function( num ) {
13604 var str = num.toString(),
13605 decimal = str.indexOf( "." );
13606 return decimal === -1 ? 0 : str.length - decimal - 1;
13607 },
13608
13609 _adjustValue: function( value ) {
13610 var base, aboveMin,
13611 options = this.options;
13612
13613 // make sure we're at a valid step
13614 // - find out where we are relative to the base (min or 0)
13615 base = options.min !== null ? options.min : 0;
13616 aboveMin = value - base;
13617 // - round to the nearest step
13618 aboveMin = Math.round(aboveMin / options.step) * options.step;
13619 // - rounding is based on 0, so adjust back to our base
13620 value = base + aboveMin;
13621
13622 // fix precision from bad JS floating point math
13623 value = parseFloat( value.toFixed( this._precision() ) );
13624
13625 // clamp the value
13626 if ( options.max !== null && value > options.max) {
13627 return options.max;
13628 }
13629 if ( options.min !== null && value < options.min ) {
13630 return options.min;
13631 }
13632
13633 return value;
13634 },
13635
13636 _stop: function( event ) {
13637 if ( !this.spinning ) {
13638 return;
13639 }
13640
13641 clearTimeout( this.timer );
13642 clearTimeout( this.mousewheelTimer );
13643 this.counter = 0;
13644 this.spinning = false;
13645 this._trigger( "stop", event );
13646 },
13647
13648 _setOption: function( key, value ) {
13649 if ( key === "culture" || key === "numberFormat" ) {
13650 var prevValue = this._parse( this.element.val() );
13651 this.options[ key ] = value;
13652 this.element.val( this._format( prevValue ) );
13653 return;
13654 }
13655
13656 if ( key === "max" || key === "min" || key === "step" ) {
13657 if ( typeof value === "string" ) {
13658 value = this._parse( value );
13659 }
13660 }
13661 if ( key === "icons" ) {
13662 this.buttons.first().find( ".ui-icon" )
13663 .removeClass( this.options.icons.up )
13664 .addClass( value.up );
13665 this.buttons.last().find( ".ui-icon" )
13666 .removeClass( this.options.icons.down )
13667 .addClass( value.down );
13668 }
13669
13670 this._super( key, value );
13671
13672 if ( key === "disabled" ) {
13673 if ( value ) {
13674 this.element.prop( "disabled", true );
13675 this.buttons.button( "disable" );
13676 } else {
13677 this.element.prop( "disabled", false );
13678 this.buttons.button( "enable" );
13679 }
13680 }
13681 },
13682
13683 _setOptions: modifier(function( options ) {
13684 this._super( options );
13685 this._value( this.element.val() );
13686 }),
13687
13688 _parse: function( val ) {
13689 if ( typeof val === "string" && val !== "" ) {
13690 val = window.Globalize && this.options.numberFormat ?
13691 Globalize.parseFloat( val, 10, this.options.culture ) : +val;
13692 }
13693 return val === "" || isNaN( val ) ? null : val;
13694 },
13695
13696 _format: function( value ) {
13697 if ( value === "" ) {
13698 return "";
13699 }
13700 return window.Globalize && this.options.numberFormat ?
13701 Globalize.format( value, this.options.numberFormat, this.options.culture ) :
13702 value;
13703 },
13704
13705 _refresh: function() {
13706 this.element.attr({
13707 "aria-valuemin": this.options.min,
13708 "aria-valuemax": this.options.max,
13709 // TODO: what should we do with values that can't be parsed?
13710 "aria-valuenow": this._parse( this.element.val() )
13711 });
13712 },
13713
13714 // update the value without triggering change
13715 _value: function( value, allowAny ) {
13716 var parsed;
13717 if ( value !== "" ) {
13718 parsed = this._parse( value );
13719 if ( parsed !== null ) {
13720 if ( !allowAny ) {
13721 parsed = this._adjustValue( parsed );
13722 }
13723 value = this._format( parsed );
13724 }
13725 }
13726 this.element.val( value );
13727 this._refresh();
13728 },
13729
13730 _destroy: function() {
13731 this.element
13732 .removeClass( "ui-spinner-input" )
13733 .prop( "disabled", false )
13734 .removeAttr( "autocomplete" )
13735 .removeAttr( "role" )
13736 .removeAttr( "aria-valuemin" )
13737 .removeAttr( "aria-valuemax" )
13738 .removeAttr( "aria-valuenow" );
13739 this.uiSpinner.replaceWith( this.element );
13740 },
13741
13742 stepUp: modifier(function( steps ) {
13743 this._stepUp( steps );
13744 }),
13745 _stepUp: function( steps ) {
13746 if ( this._start() ) {
13747 this._spin( (steps || 1) * this.options.step );
13748 this._stop();
13749 }
13750 },
13751
13752 stepDown: modifier(function( steps ) {
13753 this._stepDown( steps );
13754 }),
13755 _stepDown: function( steps ) {
13756 if ( this._start() ) {
13757 this._spin( (steps || 1) * -this.options.step );
13758 this._stop();
13759 }
13760 },
13761
13762 pageUp: modifier(function( pages ) {
13763 this._stepUp( (pages || 1) * this.options.page );
13764 }),
13765
13766 pageDown: modifier(function( pages ) {
13767 this._stepDown( (pages || 1) * this.options.page );
13768 }),
13769
13770 value: function( newVal ) {
13771 if ( !arguments.length ) {
13772 return this._parse( this.element.val() );
13773 }
13774 modifier( this._value ).call( this, newVal );
13775 },
13776
13777 widget: function() {
13778 return this.uiSpinner;
13779 }
13780});
13781
13782}( jQuery ) );
13783
13784(function( $, undefined ) {
13785
13786var tabId = 0,
13787 rhash = /#.*$/;
13788
13789function getNextTabId() {
13790 return ++tabId;
13791}
13792
13793function isLocal( anchor ) {
13794 return anchor.hash.length > 1 &&
13795 decodeURIComponent( anchor.href.replace( rhash, "" ) ) ===
13796 decodeURIComponent( location.href.replace( rhash, "" ) );
13797}
13798
13799$.widget( "ui.tabs", {
13800 version: "1.10.3",
13801 delay: 300,
13802 options: {
13803 active: null,
13804 collapsible: false,
13805 event: "click",
13806 heightStyle: "content",
13807 hide: null,
13808 show: null,
13809
13810 // callbacks
13811 activate: null,
13812 beforeActivate: null,
13813 beforeLoad: null,
13814 load: null
13815 },
13816
13817 _create: function() {
13818 var that = this,
13819 options = this.options;
13820
13821 this.running = false;
13822
13823 this.element
13824 .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
13825 .toggleClass( "ui-tabs-collapsible", options.collapsible )
13826 // Prevent users from focusing disabled tabs via click
13827 .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
13828 if ( $( this ).is( ".ui-state-disabled" ) ) {
13829 event.preventDefault();
13830 }
13831 })
13832 // support: IE <9
13833 // Preventing the default action in mousedown doesn't prevent IE
13834 // from focusing the element, so if the anchor gets focused, blur.
13835 // We don't have to worry about focusing the previously focused
13836 // element since clicking on a non-focusable element should focus
13837 // the body anyway.
13838 .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
13839 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
13840 this.blur();
13841 }
13842 });
13843
13844 this._processTabs();
13845 options.active = this._initialActive();
13846
13847 // Take disabling tabs via class attribute from HTML
13848 // into account and update option properly.
13849 if ( $.isArray( options.disabled ) ) {
13850 options.disabled = $.unique( options.disabled.concat(
13851 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
13852 return that.tabs.index( li );
13853 })
13854 ) ).sort();
13855 }
13856
13857 // check for length avoids error when initializing empty list
13858 if ( this.options.active !== false && this.anchors.length ) {
13859 this.active = this._findActive( options.active );
13860 } else {
13861 this.active = $();
13862 }
13863
13864 this._refresh();
13865
13866 if ( this.active.length ) {
13867 this.load( options.active );
13868 }
13869 },
13870
13871 _initialActive: function() {
13872 var active = this.options.active,
13873 collapsible = this.options.collapsible,
13874 locationHash = location.hash.substring( 1 );
13875
13876 if ( active === null ) {
13877 // check the fragment identifier in the URL
13878 if ( locationHash ) {
13879 this.tabs.each(function( i, tab ) {
13880 if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
13881 active = i;
13882 return false;
13883 }
13884 });
13885 }
13886
13887 // check for a tab marked active via a class
13888 if ( active === null ) {
13889 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
13890 }
13891
13892 // no active tab, set to false
13893 if ( active === null || active === -1 ) {
13894 active = this.tabs.length ? 0 : false;
13895 }
13896 }
13897
13898 // handle numbers: negative, out of range
13899 if ( active !== false ) {
13900 active = this.tabs.index( this.tabs.eq( active ) );
13901 if ( active === -1 ) {
13902 active = collapsible ? false : 0;
13903 }
13904 }
13905
13906 // don't allow collapsible: false and active: false
13907 if ( !collapsible && active === false && this.anchors.length ) {
13908 active = 0;
13909 }
13910
13911 return active;
13912 },
13913
13914 _getCreateEventData: function() {
13915 return {
13916 tab: this.active,
13917 panel: !this.active.length ? $() : this._getPanelForTab( this.active )
13918 };
13919 },
13920
13921 _tabKeydown: function( event ) {
13922 /*jshint maxcomplexity:15*/
13923 var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
13924 selectedIndex = this.tabs.index( focusedTab ),
13925 goingForward = true;
13926
13927 if ( this._handlePageNav( event ) ) {
13928 return;
13929 }
13930
13931 switch ( event.keyCode ) {
13932 case $.ui.keyCode.RIGHT:
13933 case $.ui.keyCode.DOWN:
13934 selectedIndex++;
13935 break;
13936 case $.ui.keyCode.UP:
13937 case $.ui.keyCode.LEFT:
13938 goingForward = false;
13939 selectedIndex--;
13940 break;
13941 case $.ui.keyCode.END:
13942 selectedIndex = this.anchors.length - 1;
13943 break;
13944 case $.ui.keyCode.HOME:
13945 selectedIndex = 0;
13946 break;
13947 case $.ui.keyCode.SPACE:
13948 // Activate only, no collapsing
13949 event.preventDefault();
13950 clearTimeout( this.activating );
13951 this._activate( selectedIndex );
13952 return;
13953 case $.ui.keyCode.ENTER:
13954 // Toggle (cancel delayed activation, allow collapsing)
13955 event.preventDefault();
13956 clearTimeout( this.activating );
13957 // Determine if we should collapse or activate
13958 this._activate( selectedIndex === this.options.active ? false : selectedIndex );
13959 return;
13960 default:
13961 return;
13962 }
13963
13964 // Focus the appropriate tab, based on which key was pressed
13965 event.preventDefault();
13966 clearTimeout( this.activating );
13967 selectedIndex = this._focusNextTab( selectedIndex, goingForward );
13968
13969 // Navigating with control key will prevent automatic activation
13970 if ( !event.ctrlKey ) {
13971 // Update aria-selected immediately so that AT think the tab is already selected.
13972 // Otherwise AT may confuse the user by stating that they need to activate the tab,
13973 // but the tab will already be activated by the time the announcement finishes.
13974 focusedTab.attr( "aria-selected", "false" );
13975 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
13976
13977 this.activating = this._delay(function() {
13978 this.option( "active", selectedIndex );
13979 }, this.delay );
13980 }
13981 },
13982
13983 _panelKeydown: function( event ) {
13984 if ( this._handlePageNav( event ) ) {
13985 return;
13986 }
13987
13988 // Ctrl+up moves focus to the current tab
13989 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
13990 event.preventDefault();
13991 this.active.focus();
13992 }
13993 },
13994
13995 // Alt+page up/down moves focus to the previous/next tab (and activates)
13996 _handlePageNav: function( event ) {
13997 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
13998 this._activate( this._focusNextTab( this.options.active - 1, false ) );
13999 return true;
14000 }
14001 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
14002 this._activate( this._focusNextTab( this.options.active + 1, true ) );
14003 return true;
14004 }
14005 },
14006
14007 _findNextTab: function( index, goingForward ) {
14008 var lastTabIndex = this.tabs.length - 1;
14009
14010 function constrain() {
14011 if ( index > lastTabIndex ) {
14012 index = 0;
14013 }
14014 if ( index < 0 ) {
14015 index = lastTabIndex;
14016 }
14017 return index;
14018 }
14019
14020 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
14021 index = goingForward ? index + 1 : index - 1;
14022 }
14023
14024 return index;
14025 },
14026
14027 _focusNextTab: function( index, goingForward ) {
14028 index = this._findNextTab( index, goingForward );
14029 this.tabs.eq( index ).focus();
14030 return index;
14031 },
14032
14033 _setOption: function( key, value ) {
14034 if ( key === "active" ) {
14035 // _activate() will handle invalid values and update this.options
14036 this._activate( value );
14037 return;
14038 }
14039
14040 if ( key === "disabled" ) {
14041 // don't use the widget factory's disabled handling
14042 this._setupDisabled( value );
14043 return;
14044 }
14045
14046 this._super( key, value);
14047
14048 if ( key === "collapsible" ) {
14049 this.element.toggleClass( "ui-tabs-collapsible", value );
14050 // Setting collapsible: false while collapsed; open first panel
14051 if ( !value && this.options.active === false ) {
14052 this._activate( 0 );
14053 }
14054 }
14055
14056 if ( key === "event" ) {
14057 this._setupEvents( value );
14058 }
14059
14060 if ( key === "heightStyle" ) {
14061 this._setupHeightStyle( value );
14062 }
14063 },
14064
14065 _tabId: function( tab ) {
14066 return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
14067 },
14068
14069 _sanitizeSelector: function( hash ) {
14070 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
14071 },
14072
14073 refresh: function() {
14074 var options = this.options,
14075 lis = this.tablist.children( ":has(a[href])" );
14076
14077 // get disabled tabs from class attribute from HTML
14078 // this will get converted to a boolean if needed in _refresh()
14079 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
14080 return lis.index( tab );
14081 });
14082
14083 this._processTabs();
14084
14085 // was collapsed or no tabs
14086 if ( options.active === false || !this.anchors.length ) {
14087 options.active = false;
14088 this.active = $();
14089 // was active, but active tab is gone
14090 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
14091 // all remaining tabs are disabled
14092 if ( this.tabs.length === options.disabled.length ) {
14093 options.active = false;
14094 this.active = $();
14095 // activate previous tab
14096 } else {
14097 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
14098 }
14099 // was active, active tab still exists
14100 } else {
14101 // make sure active index is correct
14102 options.active = this.tabs.index( this.active );
14103 }
14104
14105 this._refresh();
14106 },
14107
14108 _refresh: function() {
14109 this._setupDisabled( this.options.disabled );
14110 this._setupEvents( this.options.event );
14111 this._setupHeightStyle( this.options.heightStyle );
14112
14113 this.tabs.not( this.active ).attr({
14114 "aria-selected": "false",
14115 tabIndex: -1
14116 });
14117 this.panels.not( this._getPanelForTab( this.active ) )
14118 .hide()
14119 .attr({
14120 "aria-expanded": "false",
14121 "aria-hidden": "true"
14122 });
14123
14124 // Make sure one tab is in the tab order
14125 if ( !this.active.length ) {
14126 this.tabs.eq( 0 ).attr( "tabIndex", 0 );
14127 } else {
14128 this.active
14129 .addClass( "ui-tabs-active ui-state-active" )
14130 .attr({
14131 "aria-selected": "true",
14132 tabIndex: 0
14133 });
14134 this._getPanelForTab( this.active )
14135 .show()
14136 .attr({
14137 "aria-expanded": "true",
14138 "aria-hidden": "false"
14139 });
14140 }
14141 },
14142
14143 _processTabs: function() {
14144 var that = this;
14145
14146 this.tablist = this._getList()
14147 .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
14148 .attr( "role", "tablist" );
14149
14150 this.tabs = this.tablist.find( "> li:has(a[href])" )
14151 .addClass( "ui-state-default ui-corner-top" )
14152 .attr({
14153 role: "tab",
14154 tabIndex: -1
14155 });
14156
14157 this.anchors = this.tabs.map(function() {
14158 return $( "a", this )[ 0 ];
14159 })
14160 .addClass( "ui-tabs-anchor" )
14161 .attr({
14162 role: "presentation",
14163 tabIndex: -1
14164 });
14165
14166 this.panels = $();
14167
14168 this.anchors.each(function( i, anchor ) {
14169 var selector, panel, panelId,
14170 anchorId = $( anchor ).uniqueId().attr( "id" ),
14171 tab = $( anchor ).closest( "li" ),
14172 originalAriaControls = tab.attr( "aria-controls" );
14173
14174 // inline tab
14175 if ( isLocal( anchor ) ) {
14176 selector = anchor.hash;
14177 panel = that.element.find( that._sanitizeSelector( selector ) );
14178 // remote tab
14179 } else {
14180 panelId = that._tabId( tab );
14181 selector = "#" + panelId;
14182 panel = that.element.find( selector );
14183 if ( !panel.length ) {
14184 panel = that._createPanel( panelId );
14185 panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
14186 }
14187 panel.attr( "aria-live", "polite" );
14188 }
14189
14190 if ( panel.length) {
14191 that.panels = that.panels.add( panel );
14192 }
14193 if ( originalAriaControls ) {
14194 tab.data( "ui-tabs-aria-controls", originalAriaControls );
14195 }
14196 tab.attr({
14197 "aria-controls": selector.substring( 1 ),
14198 "aria-labelledby": anchorId
14199 });
14200 panel.attr( "aria-labelledby", anchorId );
14201 });
14202
14203 this.panels
14204 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
14205 .attr( "role", "tabpanel" );
14206 },
14207
14208 // allow overriding how to find the list for rare usage scenarios (#7715)
14209 _getList: function() {
14210 return this.element.find( "ol,ul" ).eq( 0 );
14211 },
14212
14213 _createPanel: function( id ) {
14214 return $( "<div>" )
14215 .attr( "id", id )
14216 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
14217 .data( "ui-tabs-destroy", true );
14218 },
14219
14220 _setupDisabled: function( disabled ) {
14221 if ( $.isArray( disabled ) ) {
14222 if ( !disabled.length ) {
14223 disabled = false;
14224 } else if ( disabled.length === this.anchors.length ) {
14225 disabled = true;
14226 }
14227 }
14228
14229 // disable tabs
14230 for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
14231 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
14232 $( li )
14233 .addClass( "ui-state-disabled" )
14234 .attr( "aria-disabled", "true" );
14235 } else {
14236 $( li )
14237 .removeClass( "ui-state-disabled" )
14238 .removeAttr( "aria-disabled" );
14239 }
14240 }
14241
14242 this.options.disabled = disabled;
14243 },
14244
14245 _setupEvents: function( event ) {
14246 var events = {
14247 click: function( event ) {
14248 event.preventDefault();
14249 }
14250 };
14251 if ( event ) {
14252 $.each( event.split(" "), function( index, eventName ) {
14253 events[ eventName ] = "_eventHandler";
14254 });
14255 }
14256
14257 this._off( this.anchors.add( this.tabs ).add( this.panels ) );
14258 this._on( this.anchors, events );
14259 this._on( this.tabs, { keydown: "_tabKeydown" } );
14260 this._on( this.panels, { keydown: "_panelKeydown" } );
14261
14262 this._focusable( this.tabs );
14263 this._hoverable( this.tabs );
14264 },
14265
14266 _setupHeightStyle: function( heightStyle ) {
14267 var maxHeight,
14268 parent = this.element.parent();
14269
14270 if ( heightStyle === "fill" ) {
14271 maxHeight = parent.height();
14272 maxHeight -= this.element.outerHeight() - this.element.height();
14273
14274 this.element.siblings( ":visible" ).each(function() {
14275 var elem = $( this ),
14276 position = elem.css( "position" );
14277
14278 if ( position === "absolute" || position === "fixed" ) {
14279 return;
14280 }
14281 maxHeight -= elem.outerHeight( true );
14282 });
14283
14284 this.element.children().not( this.panels ).each(function() {
14285 maxHeight -= $( this ).outerHeight( true );
14286 });
14287
14288 this.panels.each(function() {
14289 $( this ).height( Math.max( 0, maxHeight -
14290 $( this ).innerHeight() + $( this ).height() ) );
14291 })
14292 .css( "overflow", "auto" );
14293 } else if ( heightStyle === "auto" ) {
14294 maxHeight = 0;
14295 this.panels.each(function() {
14296 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
14297 }).height( maxHeight );
14298 }
14299 },
14300
14301 _eventHandler: function( event ) {
14302 var options = this.options,
14303 active = this.active,
14304 anchor = $( event.currentTarget ),
14305 tab = anchor.closest( "li" ),
14306 clickedIsActive = tab[ 0 ] === active[ 0 ],
14307 collapsing = clickedIsActive && options.collapsible,
14308 toShow = collapsing ? $() : this._getPanelForTab( tab ),
14309 toHide = !active.length ? $() : this._getPanelForTab( active ),
14310 eventData = {
14311 oldTab: active,
14312 oldPanel: toHide,
14313 newTab: collapsing ? $() : tab,
14314 newPanel: toShow
14315 };
14316
14317 event.preventDefault();
14318
14319 if ( tab.hasClass( "ui-state-disabled" ) ||
14320 // tab is already loading
14321 tab.hasClass( "ui-tabs-loading" ) ||
14322 // can't switch durning an animation
14323 this.running ||
14324 // click on active header, but not collapsible
14325 ( clickedIsActive && !options.collapsible ) ||
14326 // allow canceling activation
14327 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
14328 return;
14329 }
14330
14331 options.active = collapsing ? false : this.tabs.index( tab );
14332
14333 this.active = clickedIsActive ? $() : tab;
14334 if ( this.xhr ) {
14335 this.xhr.abort();
14336 }
14337
14338 if ( !toHide.length && !toShow.length ) {
14339 $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
14340 }
14341
14342 if ( toShow.length ) {
14343 this.load( this.tabs.index( tab ), event );
14344 }
14345 this._toggle( event, eventData );
14346 },
14347
14348 // handles show/hide for selecting tabs
14349 _toggle: function( event, eventData ) {
14350 var that = this,
14351 toShow = eventData.newPanel,
14352 toHide = eventData.oldPanel;
14353
14354 this.running = true;
14355
14356 function complete() {
14357 that.running = false;
14358 that._trigger( "activate", event, eventData );
14359 }
14360
14361 function show() {
14362 eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
14363
14364 if ( toShow.length && that.options.show ) {
14365 that._show( toShow, that.options.show, complete );
14366 } else {
14367 toShow.show();
14368 complete();
14369 }
14370 }
14371
14372 // start out by hiding, then showing, then completing
14373 if ( toHide.length && this.options.hide ) {
14374 this._hide( toHide, this.options.hide, function() {
14375 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
14376 show();
14377 });
14378 } else {
14379 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
14380 toHide.hide();
14381 show();
14382 }
14383
14384 toHide.attr({
14385 "aria-expanded": "false",
14386 "aria-hidden": "true"
14387 });
14388 eventData.oldTab.attr( "aria-selected", "false" );
14389 // If we're switching tabs, remove the old tab from the tab order.
14390 // If we're opening from collapsed state, remove the previous tab from the tab order.
14391 // If we're collapsing, then keep the collapsing tab in the tab order.
14392 if ( toShow.length && toHide.length ) {
14393 eventData.oldTab.attr( "tabIndex", -1 );
14394 } else if ( toShow.length ) {
14395 this.tabs.filter(function() {
14396 return $( this ).attr( "tabIndex" ) === 0;
14397 })
14398 .attr( "tabIndex", -1 );
14399 }
14400
14401 toShow.attr({
14402 "aria-expanded": "true",
14403 "aria-hidden": "false"
14404 });
14405 eventData.newTab.attr({
14406 "aria-selected": "true",
14407 tabIndex: 0
14408 });
14409 },
14410
14411 _activate: function( index ) {
14412 var anchor,
14413 active = this._findActive( index );
14414
14415 // trying to activate the already active panel
14416 if ( active[ 0 ] === this.active[ 0 ] ) {
14417 return;
14418 }
14419
14420 // trying to collapse, simulate a click on the current active header
14421 if ( !active.length ) {
14422 active = this.active;
14423 }
14424
14425 anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
14426 this._eventHandler({
14427 target: anchor,
14428 currentTarget: anchor,
14429 preventDefault: $.noop
14430 });
14431 },
14432
14433 _findActive: function( index ) {
14434 return index === false ? $() : this.tabs.eq( index );
14435 },
14436
14437 _getIndex: function( index ) {
14438 // meta-function to give users option to provide a href string instead of a numerical index.
14439 if ( typeof index === "string" ) {
14440 index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
14441 }
14442
14443 return index;
14444 },
14445
14446 _destroy: function() {
14447 if ( this.xhr ) {
14448 this.xhr.abort();
14449 }
14450
14451 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
14452
14453 this.tablist
14454 .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
14455 .removeAttr( "role" );
14456
14457 this.anchors
14458 .removeClass( "ui-tabs-anchor" )
14459 .removeAttr( "role" )
14460 .removeAttr( "tabIndex" )
14461 .removeUniqueId();
14462
14463 this.tabs.add( this.panels ).each(function() {
14464 if ( $.data( this, "ui-tabs-destroy" ) ) {
14465 $( this ).remove();
14466 } else {
14467 $( this )
14468 .removeClass( "ui-state-default ui-state-active ui-state-disabled " +
14469 "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
14470 .removeAttr( "tabIndex" )
14471 .removeAttr( "aria-live" )
14472 .removeAttr( "aria-busy" )
14473 .removeAttr( "aria-selected" )
14474 .removeAttr( "aria-labelledby" )
14475 .removeAttr( "aria-hidden" )
14476 .removeAttr( "aria-expanded" )
14477 .removeAttr( "role" );
14478 }
14479 });
14480
14481 this.tabs.each(function() {
14482 var li = $( this ),
14483 prev = li.data( "ui-tabs-aria-controls" );
14484 if ( prev ) {
14485 li
14486 .attr( "aria-controls", prev )
14487 .removeData( "ui-tabs-aria-controls" );
14488 } else {
14489 li.removeAttr( "aria-controls" );
14490 }
14491 });
14492
14493 this.panels.show();
14494
14495 if ( this.options.heightStyle !== "content" ) {
14496 this.panels.css( "height", "" );
14497 }
14498 },
14499
14500 enable: function( index ) {
14501 var disabled = this.options.disabled;
14502 if ( disabled === false ) {
14503 return;
14504 }
14505
14506 if ( index === undefined ) {
14507 disabled = false;
14508 } else {
14509 index = this._getIndex( index );
14510 if ( $.isArray( disabled ) ) {
14511 disabled = $.map( disabled, function( num ) {
14512 return num !== index ? num : null;
14513 });
14514 } else {
14515 disabled = $.map( this.tabs, function( li, num ) {
14516 return num !== index ? num : null;
14517 });
14518 }
14519 }
14520 this._setupDisabled( disabled );
14521 },
14522
14523 disable: function( index ) {
14524 var disabled = this.options.disabled;
14525 if ( disabled === true ) {
14526 return;
14527 }
14528
14529 if ( index === undefined ) {
14530 disabled = true;
14531 } else {
14532 index = this._getIndex( index );
14533 if ( $.inArray( index, disabled ) !== -1 ) {
14534 return;
14535 }
14536 if ( $.isArray( disabled ) ) {
14537 disabled = $.merge( [ index ], disabled ).sort();
14538 } else {
14539 disabled = [ index ];
14540 }
14541 }
14542 this._setupDisabled( disabled );
14543 },
14544
14545 load: function( index, event ) {
14546 index = this._getIndex( index );
14547 var that = this,
14548 tab = this.tabs.eq( index ),
14549 anchor = tab.find( ".ui-tabs-anchor" ),
14550 panel = this._getPanelForTab( tab ),
14551 eventData = {
14552 tab: tab,
14553 panel: panel
14554 };
14555
14556 // not remote
14557 if ( isLocal( anchor[ 0 ] ) ) {
14558 return;
14559 }
14560
14561 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
14562
14563 // support: jQuery <1.8
14564 // jQuery <1.8 returns false if the request is canceled in beforeSend,
14565 // but as of 1.8, $.ajax() always returns a jqXHR object.
14566 if ( this.xhr && this.xhr.statusText !== "canceled" ) {
14567 tab.addClass( "ui-tabs-loading" );
14568 panel.attr( "aria-busy", "true" );
14569
14570 this.xhr
14571 .success(function( response ) {
14572 // support: jQuery <1.8
14573 // http://bugs.jquery.com/ticket/11778
14574 setTimeout(function() {
14575 panel.html( response );
14576 that._trigger( "load", event, eventData );
14577 }, 1 );
14578 })
14579 .complete(function( jqXHR, status ) {
14580 // support: jQuery <1.8
14581 // http://bugs.jquery.com/ticket/11778
14582 setTimeout(function() {
14583 if ( status === "abort" ) {
14584 that.panels.stop( false, true );
14585 }
14586
14587 tab.removeClass( "ui-tabs-loading" );
14588 panel.removeAttr( "aria-busy" );
14589
14590 if ( jqXHR === that.xhr ) {
14591 delete that.xhr;
14592 }
14593 }, 1 );
14594 });
14595 }
14596 },
14597
14598 _ajaxSettings: function( anchor, event, eventData ) {
14599 var that = this;
14600 return {
14601 url: anchor.attr( "href" ),
14602 beforeSend: function( jqXHR, settings ) {
14603 return that._trigger( "beforeLoad", event,
14604 $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
14605 }
14606 };
14607 },
14608
14609 _getPanelForTab: function( tab ) {
14610 var id = $( tab ).attr( "aria-controls" );
14611 return this.element.find( this._sanitizeSelector( "#" + id ) );
14612 }
14613});
14614
14615})( jQuery );
14616
14617(function( $ ) {
14618
14619var increments = 0;
14620
14621function addDescribedBy( elem, id ) {
14622 var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
14623 describedby.push( id );
14624 elem
14625 .data( "ui-tooltip-id", id )
14626 .attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
14627}
14628
14629function removeDescribedBy( elem ) {
14630 var id = elem.data( "ui-tooltip-id" ),
14631 describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
14632 index = $.inArray( id, describedby );
14633 if ( index !== -1 ) {
14634 describedby.splice( index, 1 );
14635 }
14636
14637 elem.removeData( "ui-tooltip-id" );
14638 describedby = $.trim( describedby.join( " " ) );
14639 if ( describedby ) {
14640 elem.attr( "aria-describedby", describedby );
14641 } else {
14642 elem.removeAttr( "aria-describedby" );
14643 }
14644}
14645
14646$.widget( "ui.tooltip", {
14647 version: "1.10.3",
14648 options: {
14649 content: function() {
14650 // support: IE<9, Opera in jQuery <1.7
14651 // .text() can't accept undefined, so coerce to a string
14652 var title = $( this ).attr( "title" ) || "";
14653 // Escape title, since we're going from an attribute to raw HTML
14654 return $( "<a>" ).text( title ).html();
14655 },
14656 hide: true,
14657 // Disabled elements have inconsistent behavior across browsers (#8661)
14658 items: "[title]:not([disabled])",
14659 position: {
14660 my: "left top+15",
14661 at: "left bottom",
14662 collision: "flipfit flip"
14663 },
14664 show: true,
14665 tooltipClass: null,
14666 track: false,
14667
14668 // callbacks
14669 close: null,
14670 open: null
14671 },
14672
14673 _create: function() {
14674 this._on({
14675 mouseover: "open",
14676 focusin: "open"
14677 });
14678
14679 // IDs of generated tooltips, needed for destroy
14680 this.tooltips = {};
14681 // IDs of parent tooltips where we removed the title attribute
14682 this.parents = {};
14683
14684 if ( this.options.disabled ) {
14685 this._disable();
14686 }
14687 },
14688
14689 _setOption: function( key, value ) {
14690 var that = this;
14691
14692 if ( key === "disabled" ) {
14693 this[ value ? "_disable" : "_enable" ]();
14694 this.options[ key ] = value;
14695 // disable element style changes
14696 return;
14697 }
14698
14699 this._super( key, value );
14700
14701 if ( key === "content" ) {
14702 $.each( this.tooltips, function( id, element ) {
14703 that._updateContent( element );
14704 });
14705 }
14706 },
14707
14708 _disable: function() {
14709 var that = this;
14710
14711 // close open tooltips
14712 $.each( this.tooltips, function( id, element ) {
14713 var event = $.Event( "blur" );
14714 event.target = event.currentTarget = element[0];
14715 that.close( event, true );
14716 });
14717
14718 // remove title attributes to prevent native tooltips
14719 this.element.find( this.options.items ).addBack().each(function() {
14720 var element = $( this );
14721 if ( element.is( "[title]" ) ) {
14722 element
14723 .data( "ui-tooltip-title", element.attr( "title" ) )
14724 .attr( "title", "" );
14725 }
14726 });
14727 },
14728
14729 _enable: function() {
14730 // restore title attributes
14731 this.element.find( this.options.items ).addBack().each(function() {
14732 var element = $( this );
14733 if ( element.data( "ui-tooltip-title" ) ) {
14734 element.attr( "title", element.data( "ui-tooltip-title" ) );
14735 }
14736 });
14737 },
14738
14739 open: function( event ) {
14740 var that = this,
14741 target = $( event ? event.target : this.element )
14742 // we need closest here due to mouseover bubbling,
14743 // but always pointing at the same event target
14744 .closest( this.options.items );
14745
14746 // No element to show a tooltip for or the tooltip is already open
14747 if ( !target.length || target.data( "ui-tooltip-id" ) ) {
14748 return;
14749 }
14750
14751 if ( target.attr( "title" ) ) {
14752 target.data( "ui-tooltip-title", target.attr( "title" ) );
14753 }
14754
14755 target.data( "ui-tooltip-open", true );
14756
14757 // kill parent tooltips, custom or native, for hover
14758 if ( event && event.type === "mouseover" ) {
14759 target.parents().each(function() {
14760 var parent = $( this ),
14761 blurEvent;
14762 if ( parent.data( "ui-tooltip-open" ) ) {
14763 blurEvent = $.Event( "blur" );
14764 blurEvent.target = blurEvent.currentTarget = this;
14765 that.close( blurEvent, true );
14766 }
14767 if ( parent.attr( "title" ) ) {
14768 parent.uniqueId();
14769 that.parents[ this.id ] = {
14770 element: this,
14771 title: parent.attr( "title" )
14772 };
14773 parent.attr( "title", "" );
14774 }
14775 });
14776 }
14777
14778 this._updateContent( target, event );
14779 },
14780
14781 _updateContent: function( target, event ) {
14782 var content,
14783 contentOption = this.options.content,
14784 that = this,
14785 eventType = event ? event.type : null;
14786
14787 if ( typeof contentOption === "string" ) {
14788 return this._open( event, target, contentOption );
14789 }
14790
14791 content = contentOption.call( target[0], function( response ) {
14792 // ignore async response if tooltip was closed already
14793 if ( !target.data( "ui-tooltip-open" ) ) {
14794 return;
14795 }
14796 // IE may instantly serve a cached response for ajax requests
14797 // delay this call to _open so the other call to _open runs first
14798 that._delay(function() {
14799 // jQuery creates a special event for focusin when it doesn't
14800 // exist natively. To improve performance, the native event
14801 // object is reused and the type is changed. Therefore, we can't
14802 // rely on the type being correct after the event finished
14803 // bubbling, so we set it back to the previous value. (#8740)
14804 if ( event ) {
14805 event.type = eventType;
14806 }
14807 this._open( event, target, response );
14808 });
14809 });
14810 if ( content ) {
14811 this._open( event, target, content );
14812 }
14813 },
14814
14815 _open: function( event, target, content ) {
14816 var tooltip, events, delayedShow,
14817 positionOption = $.extend( {}, this.options.position );
14818
14819 if ( !content ) {
14820 return;
14821 }
14822
14823 // Content can be updated multiple times. If the tooltip already
14824 // exists, then just update the content and bail.
14825 tooltip = this._find( target );
14826 if ( tooltip.length ) {
14827 tooltip.find( ".ui-tooltip-content" ).html( content );
14828 return;
14829 }
14830
14831 // if we have a title, clear it to prevent the native tooltip
14832 // we have to check first to avoid defining a title if none exists
14833 // (we don't want to cause an element to start matching [title])
14834 //
14835 // We use removeAttr only for key events, to allow IE to export the correct
14836 // accessible attributes. For mouse events, set to empty string to avoid
14837 // native tooltip showing up (happens only when removing inside mouseover).
14838 if ( target.is( "[title]" ) ) {
14839 if ( event && event.type === "mouseover" ) {
14840 target.attr( "title", "" );
14841 } else {
14842 target.removeAttr( "title" );
14843 }
14844 }
14845
14846 tooltip = this._tooltip( target );
14847 addDescribedBy( target, tooltip.attr( "id" ) );
14848 tooltip.find( ".ui-tooltip-content" ).html( content );
14849
14850 function position( event ) {
14851 positionOption.of = event;
14852 if ( tooltip.is( ":hidden" ) ) {
14853 return;
14854 }
14855 tooltip.position( positionOption );
14856 }
14857 if ( this.options.track && event && /^mouse/.test( event.type ) ) {
14858 this._on( this.document, {
14859 mousemove: position
14860 });
14861 // trigger once to override element-relative positioning
14862 position( event );
14863 } else {
14864 tooltip.position( $.extend({
14865 of: target
14866 }, this.options.position ) );
14867 }
14868
14869 tooltip.hide();
14870
14871 this._show( tooltip, this.options.show );
14872 // Handle tracking tooltips that are shown with a delay (#8644). As soon
14873 // as the tooltip is visible, position the tooltip using the most recent
14874 // event.
14875 if ( this.options.show && this.options.show.delay ) {
14876 delayedShow = this.delayedShow = setInterval(function() {
14877 if ( tooltip.is( ":visible" ) ) {
14878 position( positionOption.of );
14879 clearInterval( delayedShow );
14880 }
14881 }, $.fx.interval );
14882 }
14883
14884 this._trigger( "open", event, { tooltip: tooltip } );
14885
14886 events = {
14887 keyup: function( event ) {
14888 if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
14889 var fakeEvent = $.Event(event);
14890 fakeEvent.currentTarget = target[0];
14891 this.close( fakeEvent, true );
14892 }
14893 },
14894 remove: function() {
14895 this._removeTooltip( tooltip );
14896 }
14897 };
14898 if ( !event || event.type === "mouseover" ) {
14899 events.mouseleave = "close";
14900 }
14901 if ( !event || event.type === "focusin" ) {
14902 events.focusout = "close";
14903 }
14904 this._on( true, target, events );
14905 },
14906
14907 close: function( event ) {
14908 var that = this,
14909 target = $( event ? event.currentTarget : this.element ),
14910 tooltip = this._find( target );
14911
14912 // disabling closes the tooltip, so we need to track when we're closing
14913 // to avoid an infinite loop in case the tooltip becomes disabled on close
14914 if ( this.closing ) {
14915 return;
14916 }
14917
14918 // Clear the interval for delayed tracking tooltips
14919 clearInterval( this.delayedShow );
14920
14921 // only set title if we had one before (see comment in _open())
14922 if ( target.data( "ui-tooltip-title" ) ) {
14923 target.attr( "title", target.data( "ui-tooltip-title" ) );
14924 }
14925
14926 removeDescribedBy( target );
14927
14928 tooltip.stop( true );
14929 this._hide( tooltip, this.options.hide, function() {
14930 that._removeTooltip( $( this ) );
14931 });
14932
14933 target.removeData( "ui-tooltip-open" );
14934 this._off( target, "mouseleave focusout keyup" );
14935 // Remove 'remove' binding only on delegated targets
14936 if ( target[0] !== this.element[0] ) {
14937 this._off( target, "remove" );
14938 }
14939 this._off( this.document, "mousemove" );
14940
14941 if ( event && event.type === "mouseleave" ) {
14942 $.each( this.parents, function( id, parent ) {
14943 $( parent.element ).attr( "title", parent.title );
14944 delete that.parents[ id ];
14945 });
14946 }
14947
14948 this.closing = true;
14949 this._trigger( "close", event, { tooltip: tooltip } );
14950 this.closing = false;
14951 },
14952
14953 _tooltip: function( element ) {
14954 var id = "ui-tooltip-" + increments++,
14955 tooltip = $( "<div>" )
14956 .attr({
14957 id: id,
14958 role: "tooltip"
14959 })
14960 .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
14961 ( this.options.tooltipClass || "" ) );
14962 $( "<div>" )
14963 .addClass( "ui-tooltip-content" )
14964 .appendTo( tooltip );
14965 tooltip.appendTo( this.document[0].body );
14966 this.tooltips[ id ] = element;
14967 return tooltip;
14968 },
14969
14970 _find: function( target ) {
14971 var id = target.data( "ui-tooltip-id" );
14972 return id ? $( "#" + id ) : $();
14973 },
14974
14975 _removeTooltip: function( tooltip ) {
14976 tooltip.remove();
14977 delete this.tooltips[ tooltip.attr( "id" ) ];
14978 },
14979
14980 _destroy: function() {
14981 var that = this;
14982
14983 // close open tooltips
14984 $.each( this.tooltips, function( id, element ) {
14985 // Delegate to close method to handle common cleanup
14986 var event = $.Event( "blur" );
14987 event.target = event.currentTarget = element[0];
14988 that.close( event, true );
14989
14990 // Remove immediately; destroying an open tooltip doesn't use the
14991 // hide animation
14992 $( "#" + id ).remove();
14993
14994 // Restore the title
14995 if ( element.data( "ui-tooltip-title" ) ) {
14996 element.attr( "title", element.data( "ui-tooltip-title" ) );
14997 element.removeData( "ui-tooltip-title" );
14998 }
14999 });
15000 }
15001});
15002
15003}( jQuery ) );