Line # Revision Author
1 386 ahitrov /*! jQuery UI - v1.10.3 - 2013-10-13
2 * http://jqueryui.com
3 * Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js, jquery.ui.effect.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
4 * Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
5
6 (function( $, undefined ) {
7
8 var uuid = 0,
9 runiqueId = /^ui-id-\d+$/;
10
11 // $.ui might exist from components with no dependencies, e.g., $.ui.position
12 $.ui = $.ui || {};
13
14 $.extend( $.ui, {
15 version: "1.10.3",
16
17 keyCode: {
18 BACKSPACE: 8,
19 COMMA: 188,
20 DELETE: 46,
21 DOWN: 40,
22 END: 35,
23 ENTER: 13,
24 ESCAPE: 27,
25 HOME: 36,
26 LEFT: 37,
27 NUMPAD_ADD: 107,
28 NUMPAD_DECIMAL: 110,
29 NUMPAD_DIVIDE: 111,
30 NUMPAD_ENTER: 108,
31 NUMPAD_MULTIPLY: 106,
32 NUMPAD_SUBTRACT: 109,
33 PAGE_DOWN: 34,
34 PAGE_UP: 33,
35 PERIOD: 190,
36 RIGHT: 39,
37 SPACE: 32,
38 TAB: 9,
39 UP: 38
40 }
41 });
42
43 // plugins
44 $.fn.extend({
45 focus: (function( orig ) {
46 return function( delay, fn ) {
47 return typeof delay === "number" ?
48 this.each(function() {
49 var elem = this;
50 setTimeout(function() {
51 $( elem ).focus();
52 if ( fn ) {
53 fn.call( elem );
54 }
55 }, delay );
56 }) :
57 orig.apply( this, arguments );
58 };
59 })( $.fn.focus ),
60
61 scrollParent: function() {
62 var scrollParent;
63 if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {
64 scrollParent = this.parents().filter(function() {
65 return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
66 }).eq(0);
67 } else {
68 scrollParent = this.parents().filter(function() {
69 return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
70 }).eq(0);
71 }
72
73 return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent;
74 },
75
76 zIndex: function( zIndex ) {
77 if ( zIndex !== undefined ) {
78 return this.css( "zIndex", zIndex );
79 }
80
81 if ( this.length ) {
82 var elem = $( this[ 0 ] ), position, value;
83 while ( elem.length && elem[ 0 ] !== document ) {
84 // Ignore z-index if position is set to a value where z-index is ignored by the browser
85 // This makes behavior of this function consistent across browsers
86 // WebKit always returns auto if the element is positioned
87 position = elem.css( "position" );
88 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
89 // IE returns 0 when zIndex is not specified
90 // other browsers return a string
91 // we ignore the case of nested elements with an explicit value of 0
92 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
93 value = parseInt( elem.css( "zIndex" ), 10 );
94 if ( !isNaN( value ) && value !== 0 ) {
95 return value;
96 }
97 }
98 elem = elem.parent();
99 }
100 }
101
102 return 0;
103 },
104
105 uniqueId: function() {
106 return this.each(function() {
107 if ( !this.id ) {
108 this.id = "ui-id-" + (++uuid);
109 }
110 });
111 },
112
113 removeUniqueId: function() {
114 return this.each(function() {
115 if ( runiqueId.test( this.id ) ) {
116 $( this ).removeAttr( "id" );
117 }
118 });
119 }
120 });
121
122 // selectors
123 function focusable( element, isTabIndexNotNaN ) {
124 var map, mapName, img,
125 nodeName = element.nodeName.toLowerCase();
126 if ( "area" === nodeName ) {
127 map = element.parentNode;
128 mapName = map.name;
129 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
130 return false;
131 }
132 img = $( "img[usemap=#" + mapName + "]" )[0];
133 return !!img && visible( img );
134 }
135 return ( /input|select|textarea|button|object/.test( nodeName ) ?
136 !element.disabled :
137 "a" === nodeName ?
138 element.href || isTabIndexNotNaN :
139 isTabIndexNotNaN) &&
140 // the element and all of its ancestors must be visible
141 visible( element );
142 }
143
144 function visible( element ) {
145 return $.expr.filters.visible( element ) &&
146 !$( element ).parents().addBack().filter(function() {
147 return $.css( this, "visibility" ) === "hidden";
148 }).length;
149 }
150
151 $.extend( $.expr[ ":" ], {
152 data: $.expr.createPseudo ?
153 $.expr.createPseudo(function( dataName ) {
154 return function( elem ) {
155 return !!$.data( elem, dataName );
156 };
157 }) :
158 // support: jQuery <1.8
159 function( elem, i, match ) {
160 return !!$.data( elem, match[ 3 ] );
161 },
162
163 focusable: function( element ) {
164 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
165 },
166
167 tabbable: function( element ) {
168 var tabIndex = $.attr( element, "tabindex" ),
169 isTabIndexNaN = isNaN( tabIndex );
170 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
171 }
172 });
173
174 // support: jQuery <1.8
175 if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
176 $.each( [ "Width", "Height" ], function( i, name ) {
177 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
178 type = name.toLowerCase(),
179 orig = {
180 innerWidth: $.fn.innerWidth,
181 innerHeight: $.fn.innerHeight,
182 outerWidth: $.fn.outerWidth,
183 outerHeight: $.fn.outerHeight
184 };
185
186 function reduce( elem, size, border, margin ) {
187 $.each( side, function() {
188 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
189 if ( border ) {
190 size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
191 }
192 if ( margin ) {
193 size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
194 }
195 });
196 return size;
197 }
198
199 $.fn[ "inner" + name ] = function( size ) {
200 if ( size === undefined ) {
201 return orig[ "inner" + name ].call( this );
202 }
203
204 return this.each(function() {
205 $( this ).css( type, reduce( this, size ) + "px" );
206 });
207 };
208
209 $.fn[ "outer" + name] = function( size, margin ) {
210 if ( typeof size !== "number" ) {
211 return orig[ "outer" + name ].call( this, size );
212 }
213
214 return this.each(function() {
215 $( this).css( type, reduce( this, size, true, margin ) + "px" );
216 });
217 };
218 });
219 }
220
221 // support: jQuery <1.8
222 if ( !$.fn.addBack ) {
223 $.fn.addBack = function( selector ) {
224 return this.add( selector == null ?
225 this.prevObject : this.prevObject.filter( selector )
226 );
227 };
228 }
229
230 // support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
231 if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
232 $.fn.removeData = (function( removeData ) {
233 return function( key ) {
234 if ( arguments.length ) {
235 return removeData.call( this, $.camelCase( key ) );
236 } else {
237 return removeData.call( this );
238 }
239 };
240 })( $.fn.removeData );
241 }
242
243
244
245
246
247 // deprecated
248 $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
249
250 $.support.selectstart = "onselectstart" in document.createElement( "div" );
251 $.fn.extend({
252 disableSelection: function() {
253 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
254 ".ui-disableSelection", function( event ) {
255 event.preventDefault();
256 });
257 },
258
259 enableSelection: function() {
260 return this.unbind( ".ui-disableSelection" );
261 }
262 });
263
264 $.extend( $.ui, {
265 // $.ui.plugin is deprecated. Use $.widget() extensions instead.
266 plugin: {
267 add: function( module, option, set ) {
268 var i,
269 proto = $.ui[ module ].prototype;
270 for ( i in set ) {
271 proto.plugins[ i ] = proto.plugins[ i ] || [];
272 proto.plugins[ i ].push( [ option, set[ i ] ] );
273 }
274 },
275 call: function( instance, name, args ) {
276 var i,
277 set = instance.plugins[ name ];
278 if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
279 return;
280 }
281
282 for ( i = 0; i < set.length; i++ ) {
283 if ( instance.options[ set[ i ][ 0 ] ] ) {
284 set[ i ][ 1 ].apply( instance.element, args );
285 }
286 }
287 }
288 },
289
290 // only used by resizable
291 hasScroll: function( el, a ) {
292
293 //If overflow is hidden, the element might have extra content, but the user wants to hide it
294 if ( $( el ).css( "overflow" ) === "hidden") {
295 return false;
296 }
297
298 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
299 has = false;
300
301 if ( el[ scroll ] > 0 ) {
302 return true;
303 }
304
305 // TODO: determine which cases actually cause this to happen
306 // if the element doesn't have the scroll set, see if it's possible to
307 // set the scroll
308 el[ scroll ] = 1;
309 has = ( el[ scroll ] > 0 );
310 el[ scroll ] = 0;
311 return has;
312 }
313 });
314
315 })( jQuery );
316 (function( $, undefined ) {
317
318 var 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 (function( $, undefined ) {
828
829 var mouseHandled = false;
830 $( document ).mouseup( function() {
831 mouseHandled = false;
832 });
833
834 $.widget("ui.mouse", {
835 version: "1.10.3",
836 options: {
837 cancel: "input,textarea,button,select,option",
838 distance: 1,
839 delay: 0
840 },
841 _mouseInit: function() {
842 var that = this;
843
844 this.element
845 .bind("mousedown."+this.widgetName, function(event) {
846 return that._mouseDown(event);
847 })
848 .bind("click."+this.widgetName, function(event) {
849 if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
850 $.removeData(event.target, that.widgetName + ".preventClickEvent");
851 event.stopImmediatePropagation();
852 return false;
853 }
854 });
855
856 this.started = false;
857 },
858
859 // TODO: make sure destroying one instance of mouse doesn't mess with
860 // other instances of mouse
861 _mouseDestroy: function() {
862 this.element.unbind("."+this.widgetName);
863 if ( this._mouseMoveDelegate ) {
864 $(document)
865 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
866 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
867 }
868 },
869
870 _mouseDown: function(event) {
871 // don't let more than one widget handle mouseStart
872 if( mouseHandled ) { return; }
873
874 // we may have missed mouseup (out of window)
875 (this._mouseStarted && this._mouseUp(event));
876
877 this._mouseDownEvent = event;
878
879 var that = this,
880 btnIsLeft = (event.which === 1),
881 // event.target.nodeName works around a bug in IE 8 with
882 // disabled inputs (#7620)
883 elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
884 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
885 return true;
886 }
887
888 this.mouseDelayMet = !this.options.delay;
889 if (!this.mouseDelayMet) {
890 this._mouseDelayTimer = setTimeout(function() {
891 that.mouseDelayMet = true;
892 }, this.options.delay);
893 }
894
895 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
896 this._mouseStarted = (this._mouseStart(event) !== false);
897 if (!this._mouseStarted) {
898 event.preventDefault();
899 return true;
900 }
901 }
902
903 // Click event may never have fired (Gecko & Opera)
904 if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
905 $.removeData(event.target, this.widgetName + ".preventClickEvent");
906 }
907
908 // these delegates are required to keep context
909 this._mouseMoveDelegate = function(event) {
910 return that._mouseMove(event);
911 };
912 this._mouseUpDelegate = function(event) {
913 return that._mouseUp(event);
914 };
915 $(document)
916 .bind("mousemove."+this.widgetName, this._mouseMoveDelegate)
917 .bind("mouseup."+this.widgetName, this._mouseUpDelegate);
918
919 event.preventDefault();
920
921 mouseHandled = true;
922 return true;
923 },
924
925 _mouseMove: function(event) {
926 // IE mouseup check - mouseup happened when mouse was out of window
927 if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
928 return this._mouseUp(event);
929 }
930
931 if (this._mouseStarted) {
932 this._mouseDrag(event);
933 return event.preventDefault();
934 }
935
936 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
937 this._mouseStarted =
938 (this._mouseStart(this._mouseDownEvent, event) !== false);
939 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
940 }
941
942 return !this._mouseStarted;
943 },
944
945 _mouseUp: function(event) {
946 $(document)
947 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
948 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
949
950 if (this._mouseStarted) {
951 this._mouseStarted = false;
952
953 if (event.target === this._mouseDownEvent.target) {
954 $.data(event.target, this.widgetName + ".preventClickEvent", true);
955 }
956
957 this._mouseStop(event);
958 }
959
960 return false;
961 },
962
963 _mouseDistanceMet: function(event) {
964 return (Math.max(
965 Math.abs(this._mouseDownEvent.pageX - event.pageX),
966 Math.abs(this._mouseDownEvent.pageY - event.pageY)
967 ) >= this.options.distance
968 );
969 },
970
971 _mouseDelayMet: function(/* event */) {
972 return this.mouseDelayMet;
973 },
974
975 // These are placeholder methods, to be overriden by extending plugin
976 _mouseStart: function(/* event */) {},
977 _mouseDrag: function(/* event */) {},
978 _mouseStop: function(/* event */) {},
979 _mouseCapture: function(/* event */) { return true; }
980 });
981
982 })(jQuery);
983 (function( $, undefined ) {
984
985 $.ui = $.ui || {};
986
987 var cachedScrollbarWidth,
988 max = Math.max,
989 abs = Math.abs,
990 round = Math.round,
991 rhorizontal = /left|center|right/,
992 rvertical = /top|center|bottom/,
993 roffset = /[\+\-]\d+(\.[\d]+)?%?/,
994 rposition = /^\w+/,
995 rpercent = /%$/,
996 _position = $.fn.position;
997
998 function getOffsets( offsets, width, height ) {
999 return [
1000 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
1001 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
1002 ];
1003 }
1004
1005 function parseCss( element, property ) {
1006 return parseInt( $.css( element, property ), 10 ) || 0;
1007 }
1008
1009 function getDimensions( elem ) {
1010 var raw = elem[0];
1011 if ( raw.nodeType === 9 ) {
1012 return {
1013 width: elem.width(),
1014 height: elem.height(),
1015 offset: { top: 0, left: 0 }
1016 };
1017 }
1018 if ( $.isWindow( raw ) ) {
1019 return {
1020 width: elem.width(),
1021 height: elem.height(),
1022 offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
1023 };
1024 }
1025 if ( raw.preventDefault ) {
1026 return {
1027 width: 0,
1028 height: 0,
1029 offset: { top: raw.pageY, left: raw.pageX }
1030 };
1031 }
1032 return {
1033 width: elem.outerWidth(),
1034 height: elem.outerHeight(),
1035 offset: elem.offset()
1036 };
1037 }
1038
1039 $.position = {
1040 scrollbarWidth: function() {
1041 if ( cachedScrollbarWidth !== undefined ) {
1042 return cachedScrollbarWidth;
1043 }
1044 var w1, w2,
1045 div = $( "<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
1046 innerDiv = div.children()[0];
1047
1048 $( "body" ).append( div );
1049 w1 = innerDiv.offsetWidth;
1050 div.css( "overflow", "scroll" );
1051
1052 w2 = innerDiv.offsetWidth;
1053
1054 if ( w1 === w2 ) {
1055 w2 = div[0].clientWidth;
1056 }
1057
1058 div.remove();
1059
1060 return (cachedScrollbarWidth = w1 - w2);
1061 },
1062 getScrollInfo: function( within ) {
1063 var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ),
1064 overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ),
1065 hasOverflowX = overflowX === "scroll" ||
1066 ( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
1067 hasOverflowY = overflowY === "scroll" ||
1068 ( overflowY === "auto" && within.height < within.element[0].scrollHeight );
1069 return {
1070 width: hasOverflowY ? $.position.scrollbarWidth() : 0,
1071 height: hasOverflowX ? $.position.scrollbarWidth() : 0
1072 };
1073 },
1074 getWithinInfo: function( element ) {
1075 var withinElement = $( element || window ),
1076 isWindow = $.isWindow( withinElement[0] );
1077 return {
1078 element: withinElement,
1079 isWindow: isWindow,
1080 offset: withinElement.offset() || { left: 0, top: 0 },
1081 scrollLeft: withinElement.scrollLeft(),
1082 scrollTop: withinElement.scrollTop(),
1083 width: isWindow ? withinElement.width() : withinElement.outerWidth(),
1084 height: isWindow ? withinElement.height() : withinElement.outerHeight()
1085 };
1086 }
1087 };
1088
1089 $.fn.position = function( options ) {
1090 if ( !options || !options.of ) {
1091 return _position.apply( this, arguments );
1092 }
1093
1094 // make a copy, we don't want to modify arguments
1095 options = $.extend( {}, options );
1096
1097 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
1098 target = $( options.of ),
1099 within = $.position.getWithinInfo( options.within ),
1100 scrollInfo = $.position.getScrollInfo( within ),
1101 collision = ( options.collision || "flip" ).split( " " ),
1102 offsets = {};
1103
1104 dimensions = getDimensions( target );
1105 if ( target[0].preventDefault ) {
1106 // force left top to allow flipping
1107 options.at = "left top";
1108 }
1109 targetWidth = dimensions.width;
1110 targetHeight = dimensions.height;
1111 targetOffset = dimensions.offset;
1112 // clone to reuse original targetOffset later
1113 basePosition = $.extend( {}, targetOffset );
1114
1115 // force my and at to have valid horizontal and vertical positions
1116 // if a value is missing or invalid, it will be converted to center
1117 $.each( [ "my", "at" ], function() {
1118 var pos = ( options[ this ] || "" ).split( " " ),
1119 horizontalOffset,
1120 verticalOffset;
1121
1122 if ( pos.length === 1) {
1123 pos = rhorizontal.test( pos[ 0 ] ) ?
1124 pos.concat( [ "center" ] ) :
1125 rvertical.test( pos[ 0 ] ) ?
1126 [ "center" ].concat( pos ) :
1127 [ "center", "center" ];
1128 }
1129 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
1130 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
1131
1132 // calculate offsets
1133 horizontalOffset = roffset.exec( pos[ 0 ] );
1134 verticalOffset = roffset.exec( pos[ 1 ] );
1135 offsets[ this ] = [
1136 horizontalOffset ? horizontalOffset[ 0 ] : 0,
1137 verticalOffset ? verticalOffset[ 0 ] : 0
1138 ];
1139
1140 // reduce to just the positions without the offsets
1141 options[ this ] = [
1142 rposition.exec( pos[ 0 ] )[ 0 ],
1143 rposition.exec( pos[ 1 ] )[ 0 ]
1144 ];
1145 });
1146
1147 // normalize collision option
1148 if ( collision.length === 1 ) {
1149 collision[ 1 ] = collision[ 0 ];
1150 }
1151
1152 if ( options.at[ 0 ] === "right" ) {
1153 basePosition.left += targetWidth;
1154 } else if ( options.at[ 0 ] === "center" ) {
1155 basePosition.left += targetWidth / 2;
1156 }
1157
1158 if ( options.at[ 1 ] === "bottom" ) {
1159 basePosition.top += targetHeight;
1160 } else if ( options.at[ 1 ] === "center" ) {
1161 basePosition.top += targetHeight / 2;
1162 }
1163
1164 atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
1165 basePosition.left += atOffset[ 0 ];
1166 basePosition.top += atOffset[ 1 ];
1167
1168 return this.each(function() {
1169 var collisionPosition, using,
1170 elem = $( this ),
1171 elemWidth = elem.outerWidth(),
1172 elemHeight = elem.outerHeight(),
1173 marginLeft = parseCss( this, "marginLeft" ),
1174 marginTop = parseCss( this, "marginTop" ),
1175 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
1176 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
1177 position = $.extend( {}, basePosition ),
1178 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
1179
1180 if ( options.my[ 0 ] === "right" ) {
1181 position.left -= elemWidth;
1182 } else if ( options.my[ 0 ] === "center" ) {
1183 position.left -= elemWidth / 2;
1184 }
1185
1186 if ( options.my[ 1 ] === "bottom" ) {
1187 position.top -= elemHeight;
1188 } else if ( options.my[ 1 ] === "center" ) {
1189 position.top -= elemHeight / 2;
1190 }
1191
1192 position.left += myOffset[ 0 ];
1193 position.top += myOffset[ 1 ];
1194
1195 // if the browser doesn't support fractions, then round for consistent results
1196 if ( !$.support.offsetFractions ) {
1197 position.left = round( position.left );
1198 position.top = round( position.top );
1199 }
1200
1201 collisionPosition = {
1202 marginLeft: marginLeft,
1203 marginTop: marginTop
1204 };
1205
1206 $.each( [ "left", "top" ], function( i, dir ) {
1207 if ( $.ui.position[ collision[ i ] ] ) {
1208 $.ui.position[ collision[ i ] ][ dir ]( position, {
1209 targetWidth: targetWidth,
1210 targetHeight: targetHeight,
1211 elemWidth: elemWidth,
1212 elemHeight: elemHeight,
1213 collisionPosition: collisionPosition,
1214 collisionWidth: collisionWidth,
1215 collisionHeight: collisionHeight,
1216 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1217 my: options.my,
1218 at: options.at,
1219 within: within,
1220 elem : elem
1221 });
1222 }
1223 });
1224
1225 if ( options.using ) {
1226 // adds feedback as second argument to using callback, if present
1227 using = function( props ) {
1228 var left = targetOffset.left - position.left,
1229 right = left + targetWidth - elemWidth,
1230 top = targetOffset.top - position.top,
1231 bottom = top + targetHeight - elemHeight,
1232 feedback = {
1233 target: {
1234 element: target,
1235 left: targetOffset.left,
1236 top: targetOffset.top,
1237 width: targetWidth,
1238 height: targetHeight
1239 },
1240 element: {
1241 element: elem,
1242 left: position.left,
1243 top: position.top,
1244 width: elemWidth,
1245 height: elemHeight
1246 },
1247 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1248 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1249 };
1250 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1251 feedback.horizontal = "center";
1252 }
1253 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1254 feedback.vertical = "middle";
1255 }
1256 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1257 feedback.important = "horizontal";
1258 } else {
1259 feedback.important = "vertical";
1260 }
1261 options.using.call( this, props, feedback );
1262 };
1263 }
1264
1265 elem.offset( $.extend( position, { using: using } ) );
1266 });
1267 };
1268
1269 $.ui.position = {
1270 fit: {
1271 left: function( position, data ) {
1272 var within = data.within,
1273 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1274 outerWidth = within.width,
1275 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1276 overLeft = withinOffset - collisionPosLeft,
1277 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1278 newOverRight;
1279
1280 // element is wider than within
1281 if ( data.collisionWidth > outerWidth ) {
1282 // element is initially over the left side of within
1283 if ( overLeft > 0 && overRight <= 0 ) {
1284 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
1285 position.left += overLeft - newOverRight;
1286 // element is initially over right side of within
1287 } else if ( overRight > 0 && overLeft <= 0 ) {
1288 position.left = withinOffset;
1289 // element is initially over both left and right sides of within
1290 } else {
1291 if ( overLeft > overRight ) {
1292 position.left = withinOffset + outerWidth - data.collisionWidth;
1293 } else {
1294 position.left = withinOffset;
1295 }
1296 }
1297 // too far left -> align with left edge
1298 } else if ( overLeft > 0 ) {
1299 position.left += overLeft;
1300 // too far right -> align with right edge
1301 } else if ( overRight > 0 ) {
1302 position.left -= overRight;
1303 // adjust based on position and margin
1304 } else {
1305 position.left = max( position.left - collisionPosLeft, position.left );
1306 }
1307 },
1308 top: function( position, data ) {
1309 var within = data.within,
1310 withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1311 outerHeight = data.within.height,
1312 collisionPosTop = position.top - data.collisionPosition.marginTop,
1313 overTop = withinOffset - collisionPosTop,
1314 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1315 newOverBottom;
1316
1317 // element is taller than within
1318 if ( data.collisionHeight > outerHeight ) {
1319 // element is initially over the top of within
1320 if ( overTop > 0 && overBottom <= 0 ) {
1321 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
1322 position.top += overTop - newOverBottom;
1323 // element is initially over bottom of within
1324 } else if ( overBottom > 0 && overTop <= 0 ) {
1325 position.top = withinOffset;
1326 // element is initially over both top and bottom of within
1327 } else {
1328 if ( overTop > overBottom ) {
1329 position.top = withinOffset + outerHeight - data.collisionHeight;
1330 } else {
1331 position.top = withinOffset;
1332 }
1333 }
1334 // too far up -> align with top
1335 } else if ( overTop > 0 ) {
1336 position.top += overTop;
1337 // too far down -> align with bottom edge
1338 } else if ( overBottom > 0 ) {
1339 position.top -= overBottom;
1340 // adjust based on position and margin
1341 } else {
1342 position.top = max( position.top - collisionPosTop, position.top );
1343 }
1344 }
1345 },
1346 flip: {
1347 left: function( position, data ) {
1348 var within = data.within,
1349 withinOffset = within.offset.left + within.scrollLeft,
1350 outerWidth = within.width,
1351 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1352 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1353 overLeft = collisionPosLeft - offsetLeft,
1354 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1355 myOffset = data.my[ 0 ] === "left" ?
1356 -data.elemWidth :
1357 data.my[ 0 ] === "right" ?
1358 data.elemWidth :
1359 0,
1360 atOffset = data.at[ 0 ] === "left" ?
1361 data.targetWidth :
1362 data.at[ 0 ] === "right" ?
1363 -data.targetWidth :
1364 0,
1365 offset = -2 * data.offset[ 0 ],
1366 newOverRight,
1367 newOverLeft;
1368
1369 if ( overLeft < 0 ) {
1370 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
1371 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1372 position.left += myOffset + atOffset + offset;
1373 }
1374 }
1375 else if ( overRight > 0 ) {
1376 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
1377 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1378 position.left += myOffset + atOffset + offset;
1379 }
1380 }
1381 },
1382 top: function( position, data ) {
1383 var within = data.within,
1384 withinOffset = within.offset.top + within.scrollTop,
1385 outerHeight = within.height,
1386 offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1387 collisionPosTop = position.top - data.collisionPosition.marginTop,
1388 overTop = collisionPosTop - offsetTop,
1389 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1390 top = data.my[ 1 ] === "top",
1391 myOffset = top ?
1392 -data.elemHeight :
1393 data.my[ 1 ] === "bottom" ?
1394 data.elemHeight :
1395 0,
1396 atOffset = data.at[ 1 ] === "top" ?
1397 data.targetHeight :
1398 data.at[ 1 ] === "bottom" ?
1399 -data.targetHeight :
1400 0,
1401 offset = -2 * data.offset[ 1 ],
1402 newOverTop,
1403 newOverBottom;
1404 if ( overTop < 0 ) {
1405 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
1406 if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
1407 position.top += myOffset + atOffset + offset;
1408 }
1409 }
1410 else if ( overBottom > 0 ) {
1411 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
1412 if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
1413 position.top += myOffset + atOffset + offset;
1414 }
1415 }
1416 }
1417 },
1418 flipfit: {
1419 left: function() {
1420 $.ui.position.flip.left.apply( this, arguments );
1421 $.ui.position.fit.left.apply( this, arguments );
1422 },
1423 top: function() {
1424 $.ui.position.flip.top.apply( this, arguments );
1425 $.ui.position.fit.top.apply( this, arguments );
1426 }
1427 }
1428 };
1429
1430 // fraction support test
1431 (function () {
1432 var testElement, testElementParent, testElementStyle, offsetLeft, i,
1433 body = document.getElementsByTagName( "body" )[ 0 ],
1434 div = document.createElement( "div" );
1435
1436 //Create a "fake body" for testing based on method used in jQuery.support
1437 testElement = document.createElement( body ? "div" : "body" );
1438 testElementStyle = {
1439 visibility: "hidden",
1440 width: 0,
1441 height: 0,
1442 border: 0,
1443 margin: 0,
1444 background: "none"
1445 };
1446 if ( body ) {
1447 $.extend( testElementStyle, {
1448 position: "absolute",
1449 left: "-1000px",
1450 top: "-1000px"
1451 });
1452 }
1453 for ( i in testElementStyle ) {
1454 testElement.style[ i ] = testElementStyle[ i ];
1455 }
1456 testElement.appendChild( div );
1457 testElementParent = body || document.documentElement;
1458 testElementParent.insertBefore( testElement, testElementParent.firstChild );
1459
1460 div.style.cssText = "position: absolute; left: 10.7432222px;";
1461
1462 offsetLeft = $( div ).offset().left;
1463 $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;
1464
1465 testElement.innerHTML = "";
1466 testElementParent.removeChild( testElement );
1467 })();
1468
1469 }( jQuery ) );
1470 (function( $, undefined ) {
1471
1472 $.widget("ui.draggable", $.ui.mouse, {
1473 version: "1.10.3",
1474 widgetEventPrefix: "drag",
1475 options: {
1476 addClasses: true,
1477 appendTo: "parent",
1478 axis: false,
1479 connectToSortable: false,
1480 containment: false,
1481 cursor: "auto",
1482 cursorAt: false,
1483 grid: false,
1484 handle: false,
1485 helper: "original",
1486 iframeFix: false,
1487 opacity: false,
1488 refreshPositions: false,
1489 revert: false,
1490 revertDuration: 500,
1491 scope: "default",
1492 scroll: true,
1493 scrollSensitivity: 20,
1494 scrollSpeed: 20,
1495 snap: false,
1496 snapMode: "both",
1497 snapTolerance: 20,
1498 stack: false,
1499 zIndex: false,
1500
1501 // callbacks
1502 drag: null,
1503 start: null,
1504 stop: null
1505 },
1506 _create: function() {
1507
1508 if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) {
1509 this.element[0].style.position = "relative";
1510 }
1511 if (this.options.addClasses){
1512 this.element.addClass("ui-draggable");
1513 }
1514 if (this.options.disabled){
1515 this.element.addClass("ui-draggable-disabled");
1516 }
1517
1518 this._mouseInit();
1519
1520 },
1521
1522 _destroy: function() {
1523 this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
1524 this._mouseDestroy();
1525 },
1526
1527 _mouseCapture: function(event) {
1528
1529 var o = this.options;
1530
1531 // among others, prevent a drag on a resizable-handle
1532 if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
1533 return false;
1534 }
1535
1536 //Quit if we're not on a valid handle
1537 this.handle = this._getHandle(event);
1538 if (!this.handle) {
1539 return false;
1540 }
1541
1542 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1543 $("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>")
1544 .css({
1545 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
1546 position: "absolute", opacity: "0.001", zIndex: 1000
1547 })
1548 .css($(this).offset())
1549 .appendTo("body");
1550 });
1551
1552 return true;
1553
1554 },
1555
1556 _mouseStart: function(event) {
1557
1558 var o = this.options;
1559
1560 //Create and append the visible helper
1561 this.helper = this._createHelper(event);
1562
1563 this.helper.addClass("ui-draggable-dragging");
1564
1565 //Cache the helper size
1566 this._cacheHelperProportions();
1567
1568 //If ddmanager is used for droppables, set the global draggable
1569 if($.ui.ddmanager) {
1570 $.ui.ddmanager.current = this;
1571 }
1572
1573 /*
1574 * - Position generation -
1575 * This block generates everything position related - it's the core of draggables.
1576 */
1577
1578 //Cache the margins of the original element
1579 this._cacheMargins();
1580
1581 //Store the helper's css position
1582 this.cssPosition = this.helper.css( "position" );
1583 this.scrollParent = this.helper.scrollParent();
1584 this.offsetParent = this.helper.offsetParent();
1585 this.offsetParentCssPosition = this.offsetParent.css( "position" );
1586
1587 //The element's absolute position on the page minus margins
1588 this.offset = this.positionAbs = this.element.offset();
1589 this.offset = {
1590 top: this.offset.top - this.margins.top,
1591 left: this.offset.left - this.margins.left
1592 };
1593
1594 //Reset scroll cache
1595 this.offset.scroll = false;
1596
1597 $.extend(this.offset, {
1598 click: { //Where the click happened, relative to the element
1599 left: event.pageX - this.offset.left,
1600 top: event.pageY - this.offset.top
1601 },
1602 parent: this._getParentOffset(),
1603 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
1604 });
1605
1606 //Generate the original position
1607 this.originalPosition = this.position = this._generatePosition(event);
1608 this.originalPageX = event.pageX;
1609 this.originalPageY = event.pageY;
1610
1611 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
1612 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
1613
1614 //Set a containment if given in the options
1615 this._setContainment();
1616
1617 //Trigger event + callbacks
1618 if(this._trigger("start", event) === false) {
1619 this._clear();
1620 return false;
1621 }
1622
1623 //Recache the helper size
1624 this._cacheHelperProportions();
1625
1626 //Prepare the droppable offsets
1627 if ($.ui.ddmanager && !o.dropBehaviour) {
1628 $.ui.ddmanager.prepareOffsets(this, event);
1629 }
1630
1631
1632 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
1633
1634 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
1635 if ( $.ui.ddmanager ) {
1636 $.ui.ddmanager.dragStart(this, event);
1637 }
1638
1639 return true;
1640 },
1641
1642 _mouseDrag: function(event, noPropagation) {
1643 // reset any necessary cached properties (see #5009)
1644 if ( this.offsetParentCssPosition === "fixed" ) {
1645 this.offset.parent = this._getParentOffset();
1646 }
1647
1648 //Compute the helpers position
1649 this.position = this._generatePosition(event);
1650 this.positionAbs = this._convertPositionTo("absolute");
1651
1652 //Call plugins and callbacks and use the resulting position if something is returned
1653 if (!noPropagation) {
1654 var ui = this._uiHash();
1655 if(this._trigger("drag", event, ui) === false) {
1656 this._mouseUp({});
1657 return false;
1658 }
1659 this.position = ui.position;
1660 }
1661
1662 if(!this.options.axis || this.options.axis !== "y") {
1663 this.helper[0].style.left = this.position.left+"px";
1664 }
1665 if(!this.options.axis || this.options.axis !== "x") {
1666 this.helper[0].style.top = this.position.top+"px";
1667 }
1668 if($.ui.ddmanager) {
1669 $.ui.ddmanager.drag(this, event);
1670 }
1671
1672 return false;
1673 },
1674
1675 _mouseStop: function(event) {
1676
1677 //If we are using droppables, inform the manager about the drop
1678 var that = this,
1679 dropped = false;
1680 if ($.ui.ddmanager && !this.options.dropBehaviour) {
1681 dropped = $.ui.ddmanager.drop(this, event);
1682 }
1683
1684 //if a drop comes from outside (a sortable)
1685 if(this.dropped) {
1686 dropped = this.dropped;
1687 this.dropped = false;
1688 }
1689
1690 //if the original element is no longer in the DOM don't bother to continue (see #8269)
1691 if ( this.options.helper === "original" && !$.contains( this.element[ 0 ].ownerDocument, this.element[ 0 ] ) ) {
1692 return false;
1693 }
1694
1695 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))) {
1696 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
1697 if(that._trigger("stop", event) !== false) {
1698 that._clear();
1699 }
1700 });
1701 } else {
1702 if(this._trigger("stop", event) !== false) {
1703 this._clear();
1704 }
1705 }
1706
1707 return false;
1708 },
1709
1710 _mouseUp: function(event) {
1711 //Remove frame helpers
1712 $("div.ui-draggable-iframeFix").each(function() {
1713 this.parentNode.removeChild(this);
1714 });
1715
1716 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
1717 if( $.ui.ddmanager ) {
1718 $.ui.ddmanager.dragStop(this, event);
1719 }
1720
1721 return $.ui.mouse.prototype._mouseUp.call(this, event);
1722 },
1723
1724 cancel: function() {
1725
1726 if(this.helper.is(".ui-draggable-dragging")) {
1727 this._mouseUp({});
1728 } else {
1729 this._clear();
1730 }
1731
1732 return this;
1733
1734 },
1735
1736 _getHandle: function(event) {
1737 return this.options.handle ?
1738 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
1739 true;
1740 },
1741
1742 _createHelper: function(event) {
1743
1744 var o = this.options,
1745 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element);
1746
1747 if(!helper.parents("body").length) {
1748 helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
1749 }
1750
1751 if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
1752 helper.css("position", "absolute");
1753 }
1754
1755 return helper;
1756
1757 },
1758
1759 _adjustOffsetFromHelper: function(obj) {
1760 if (typeof obj === "string") {
1761 obj = obj.split(" ");
1762 }
1763 if ($.isArray(obj)) {
1764 obj = {left: +obj[0], top: +obj[1] || 0};
1765 }
1766 if ("left" in obj) {
1767 this.offset.click.left = obj.left + this.margins.left;
1768 }
1769 if ("right" in obj) {
1770 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1771 }
1772 if ("top" in obj) {
1773 this.offset.click.top = obj.top + this.margins.top;
1774 }
1775 if ("bottom" in obj) {
1776 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1777 }
1778 },
1779
1780 _getParentOffset: function() {
1781
1782 //Get the offsetParent and cache its position
1783 var po = this.offsetParent.offset();
1784
1785 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1786 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1787 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1788 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1789 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
1790 po.left += this.scrollParent.scrollLeft();
1791 po.top += this.scrollParent.scrollTop();
1792 }
1793
1794 //This needs to be actually done for all browsers, since pageX/pageY includes this information
1795 //Ugly IE fix
1796 if((this.offsetParent[0] === document.body) ||
1797 (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
1798 po = { top: 0, left: 0 };
1799 }
1800
1801 return {
1802 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1803 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1804 };
1805
1806 },
1807
1808 _getRelativeOffset: function() {
1809
1810 if(this.cssPosition === "relative") {
1811 var p = this.element.position();
1812 return {
1813 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1814 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1815 };
1816 } else {
1817 return { top: 0, left: 0 };
1818 }
1819
1820 },
1821
1822 _cacheMargins: function() {
1823 this.margins = {
1824 left: (parseInt(this.element.css("marginLeft"),10) || 0),
1825 top: (parseInt(this.element.css("marginTop"),10) || 0),
1826 right: (parseInt(this.element.css("marginRight"),10) || 0),
1827 bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
1828 };
1829 },
1830
1831 _cacheHelperProportions: function() {
1832 this.helperProportions = {
1833 width: this.helper.outerWidth(),
1834 height: this.helper.outerHeight()
1835 };
1836 },
1837
1838 _setContainment: function() {
1839
1840 var over, c, ce,
1841 o = this.options;
1842
1843 if ( !o.containment ) {
1844 this.containment = null;
1845 return;
1846 }
1847
1848 if ( o.containment === "window" ) {
1849 this.containment = [
1850 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
1851 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
1852 $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,
1853 $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
1854 ];
1855 return;
1856 }
1857
1858 if ( o.containment === "document") {
1859 this.containment = [
1860 0,
1861 0,
1862 $( document ).width() - this.helperProportions.width - this.margins.left,
1863 ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
1864 ];
1865 return;
1866 }
1867
1868 if ( o.containment.constructor === Array ) {
1869 this.containment = o.containment;
1870 return;
1871 }
1872
1873 if ( o.containment === "parent" ) {
1874 o.containment = this.helper[ 0 ].parentNode;
1875 }
1876
1877 c = $( o.containment );
1878 ce = c[ 0 ];
1879
1880 if( !ce ) {
1881 return;
1882 }
1883
1884 over = c.css( "overflow" ) !== "hidden";
1885
1886 this.containment = [
1887 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
1888 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ) ,
1889 ( 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,
1890 ( 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
1891 ];
1892 this.relative_container = c;
1893 },
1894
1895 _convertPositionTo: function(d, pos) {
1896
1897 if(!pos) {
1898 pos = this.position;
1899 }
1900
1901 var mod = d === "absolute" ? 1 : -1,
1902 scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent;
1903
1904 //Cache the scroll
1905 if (!this.offset.scroll) {
1906 this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
1907 }
1908
1909 return {
1910 top: (
1911 pos.top + // The absolute mouse position
1912 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
1913 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
1914 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) * mod )
1915 ),
1916 left: (
1917 pos.left + // The absolute mouse position
1918 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
1919 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
1920 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) * mod )
1921 )
1922 };
1923
1924 },
1925
1926 _generatePosition: function(event) {
1927
1928 var containment, co, top, left,
1929 o = this.options,
1930 scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent,
1931 pageX = event.pageX,
1932 pageY = event.pageY;
1933
1934 //Cache the scroll
1935 if (!this.offset.scroll) {
1936 this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};
1937 }
1938
1939 /*
1940 * - Position constraining -
1941 * Constrain the position to a mix of grid, containment.
1942 */
1943
1944 // If we are not dragging yet, we won't check for options
1945 if ( this.originalPosition ) {
1946 if ( this.containment ) {
1947 if ( this.relative_container ){
1948 co = this.relative_container.offset();
1949 containment = [
1950 this.containment[ 0 ] + co.left,
1951 this.containment[ 1 ] + co.top,
1952 this.containment[ 2 ] + co.left,
1953 this.containment[ 3 ] + co.top
1954 ];
1955 }
1956 else {
1957 containment = this.containment;
1958 }
1959
1960 if(event.pageX - this.offset.click.left < containment[0]) {
1961 pageX = containment[0] + this.offset.click.left;
1962 }
1963 if(event.pageY - this.offset.click.top < containment[1]) {
1964 pageY = containment[1] + this.offset.click.top;
1965 }
1966 if(event.pageX - this.offset.click.left > containment[2]) {
1967 pageX = containment[2] + this.offset.click.left;
1968 }
1969 if(event.pageY - this.offset.click.top > containment[3]) {
1970 pageY = containment[3] + this.offset.click.top;
1971 }
1972 }
1973
1974 if(o.grid) {
1975 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
1976 top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
1977 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;
1978
1979 left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
1980 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;
1981 }
1982
1983 }
1984
1985 return {
1986 top: (
1987 pageY - // The absolute mouse position
1988 this.offset.click.top - // Click offset (relative to the element)
1989 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
1990 this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
1991 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top )
1992 ),
1993 left: (
1994 pageX - // The absolute mouse position
1995 this.offset.click.left - // Click offset (relative to the element)
1996 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
1997 this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
1998 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left )
1999 )
2000 };
2001
2002 },
2003
2004 _clear: function() {
2005 this.helper.removeClass("ui-draggable-dragging");
2006 if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
2007 this.helper.remove();
2008 }
2009 this.helper = null;
2010 this.cancelHelperRemoval = false;
2011 },
2012
2013 // From now on bulk stuff - mainly helpers
2014
2015 _trigger: function(type, event, ui) {
2016 ui = ui || this._uiHash();
2017 $.ui.plugin.call(this, type, [event, ui]);
2018 //The absolute position has to be recalculated after plugins
2019 if(type === "drag") {
2020 this.positionAbs = this._convertPositionTo("absolute");
2021 }
2022 return $.Widget.prototype._trigger.call(this, type, event, ui);
2023 },
2024
2025 plugins: {},
2026
2027 _uiHash: function() {
2028 return {
2029 helper: this.helper,
2030 position: this.position,
2031 originalPosition: this.originalPosition,
2032 offset: this.positionAbs
2033 };
2034 }
2035
2036 });
2037
2038 $.ui.plugin.add("draggable", "connectToSortable", {
2039 start: function(event, ui) {
2040
2041 var inst = $(this).data("ui-draggable"), o = inst.options,
2042 uiSortable = $.extend({}, ui, { item: inst.element });
2043 inst.sortables = [];
2044 $(o.connectToSortable).each(function() {
2045 var sortable = $.data(this, "ui-sortable");
2046 if (sortable && !sortable.options.disabled) {
2047 inst.sortables.push({
2048 instance: sortable,
2049 shouldRevert: sortable.options.revert
2050 });
2051 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).
2052 sortable._trigger("activate", event, uiSortable);
2053 }
2054 });
2055
2056 },
2057 stop: function(event, ui) {
2058
2059 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
2060 var inst = $(this).data("ui-draggable"),
2061 uiSortable = $.extend({}, ui, { item: inst.element });
2062
2063 $.each(inst.sortables, function() {
2064 if(this.instance.isOver) {
2065
2066 this.instance.isOver = 0;
2067
2068 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
2069 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
2070
2071 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid"
2072 if(this.shouldRevert) {
2073 this.instance.options.revert = this.shouldRevert;
2074 }
2075
2076 //Trigger the stop of the sortable
2077 this.instance._mouseStop(event);
2078
2079 this.instance.options.helper = this.instance.options._helper;
2080
2081 //If the helper has been the original item, restore properties in the sortable
2082 if(inst.options.helper === "original") {
2083 this.instance.currentItem.css({ top: "auto", left: "auto" });
2084 }
2085
2086 } else {
2087 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
2088 this.instance._trigger("deactivate", event, uiSortable);
2089 }
2090
2091 });
2092
2093 },
2094 drag: function(event, ui) {
2095
2096 var inst = $(this).data("ui-draggable"), that = this;
2097
2098 $.each(inst.sortables, function() {
2099
2100 var innermostIntersecting = false,
2101 thisSortable = this;
2102
2103 //Copy over some variables to allow calling the sortable's native _intersectsWith
2104 this.instance.positionAbs = inst.positionAbs;
2105 this.instance.helperProportions = inst.helperProportions;
2106 this.instance.offset.click = inst.offset.click;
2107
2108 if(this.instance._intersectsWith(this.instance.containerCache)) {
2109 innermostIntersecting = true;
2110 $.each(inst.sortables, function () {
2111 this.instance.positionAbs = inst.positionAbs;
2112 this.instance.helperProportions = inst.helperProportions;
2113 this.instance.offset.click = inst.offset.click;
2114 if (this !== thisSortable &&
2115 this.instance._intersectsWith(this.instance.containerCache) &&
2116 $.contains(thisSortable.instance.element[0], this.instance.element[0])
2117 ) {
2118 innermostIntersecting = false;
2119 }
2120 return innermostIntersecting;
2121 });
2122 }
2123
2124
2125 if(innermostIntersecting) {
2126 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
2127 if(!this.instance.isOver) {
2128
2129 this.instance.isOver = 1;
2130 //Now we fake the start of dragging for the sortable instance,
2131 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
2132 //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)
2133 this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true);
2134 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
2135 this.instance.options.helper = function() { return ui.helper[0]; };
2136
2137 event.target = this.instance.currentItem[0];
2138 this.instance._mouseCapture(event, true);
2139 this.instance._mouseStart(event, true, true);
2140
2141 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
2142 this.instance.offset.click.top = inst.offset.click.top;
2143 this.instance.offset.click.left = inst.offset.click.left;
2144 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
2145 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
2146
2147 inst._trigger("toSortable", event);
2148 inst.dropped = this.instance.element; //draggable revert needs that
2149 //hack so receive/update callbacks work (mostly)
2150 inst.currentItem = inst.element;
2151 this.instance.fromOutside = inst;
2152
2153 }
2154
2155 //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
2156 if(this.instance.currentItem) {
2157 this.instance._mouseDrag(event);
2158 }
2159
2160 } else {
2161
2162 //If it doesn't intersect with the sortable, and it intersected before,
2163 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
2164 if(this.instance.isOver) {
2165
2166 this.instance.isOver = 0;
2167 this.instance.cancelHelperRemoval = true;
2168
2169 //Prevent reverting on this forced stop
2170 this.instance.options.revert = false;
2171
2172 // The out event needs to be triggered independently
2173 this.instance._trigger("out", event, this.instance._uiHash(this.instance));
2174
2175 this.instance._mouseStop(event, true);
2176 this.instance.options.helper = this.instance.options._helper;
2177
2178 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
2179 this.instance.currentItem.remove();
2180 if(this.instance.placeholder) {
2181 this.instance.placeholder.remove();
2182 }
2183
2184 inst._trigger("fromSortable", event);
2185 inst.dropped = false; //draggable revert needs that
2186 }
2187
2188 }
2189
2190 });
2191
2192 }
2193 });
2194
2195 $.ui.plugin.add("draggable", "cursor", {
2196 start: function() {
2197 var t = $("body"), o = $(this).data("ui-draggable").options;
2198 if (t.css("cursor")) {
2199 o._cursor = t.css("cursor");
2200 }
2201 t.css("cursor", o.cursor);
2202 },
2203 stop: function() {
2204 var o = $(this).data("ui-draggable").options;
2205 if (o._cursor) {
2206 $("body").css("cursor", o._cursor);
2207 }
2208 }
2209 });
2210
2211 $.ui.plugin.add("draggable", "opacity", {
2212 start: function(event, ui) {
2213 var t = $(ui.helper), o = $(this).data("ui-draggable").options;
2214 if(t.css("opacity")) {
2215 o._opacity = t.css("opacity");
2216 }
2217 t.css("opacity", o.opacity);
2218 },
2219 stop: function(event, ui) {
2220 var o = $(this).data("ui-draggable").options;
2221 if(o._opacity) {
2222 $(ui.helper).css("opacity", o._opacity);
2223 }
2224 }
2225 });
2226
2227 $.ui.plugin.add("draggable", "scroll", {
2228 start: function() {
2229 var i = $(this).data("ui-draggable");
2230 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
2231 i.overflowOffset = i.scrollParent.offset();
2232 }
2233 },
2234 drag: function( event ) {
2235
2236 var i = $(this).data("ui-draggable"), o = i.options, scrolled = false;
2237
2238 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
2239
2240 if(!o.axis || o.axis !== "x") {
2241 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
2242 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
2243 } else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) {
2244 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
2245 }
2246 }
2247
2248 if(!o.axis || o.axis !== "y") {
2249 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
2250 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
2251 } else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) {
2252 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
2253 }
2254 }
2255
2256 } else {
2257
2258 if(!o.axis || o.axis !== "x") {
2259 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
2260 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
2261 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
2262 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
2263 }
2264 }
2265
2266 if(!o.axis || o.axis !== "y") {
2267 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
2268 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
2269 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
2270 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
2271 }
2272 }
2273
2274 }
2275
2276 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
2277 $.ui.ddmanager.prepareOffsets(i, event);
2278 }
2279
2280 }
2281 });
2282
2283 $.ui.plugin.add("draggable", "snap", {
2284 start: function() {
2285
2286 var i = $(this).data("ui-draggable"),
2287 o = i.options;
2288
2289 i.snapElements = [];
2290
2291 $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
2292 var $t = $(this),
2293 $o = $t.offset();
2294 if(this !== i.element[0]) {
2295 i.snapElements.push({
2296 item: this,
2297 width: $t.outerWidth(), height: $t.outerHeight(),
2298 top: $o.top, left: $o.left
2299 });
2300 }
2301 });
2302
2303 },
2304 drag: function(event, ui) {
2305
2306 var ts, bs, ls, rs, l, r, t, b, i, first,
2307 inst = $(this).data("ui-draggable"),
2308 o = inst.options,
2309 d = o.snapTolerance,
2310 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
2311 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
2312
2313 for (i = inst.snapElements.length - 1; i >= 0; i--){
2314
2315 l = inst.snapElements[i].left;
2316 r = l + inst.snapElements[i].width;
2317 t = inst.snapElements[i].top;
2318 b = t + inst.snapElements[i].height;
2319
2320 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {
2321 if(inst.snapElements[i].snapping) {
2322 (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
2323 }
2324 inst.snapElements[i].snapping = false;
2325 continue;
2326 }
2327
2328 if(o.snapMode !== "inner") {
2329 ts = Math.abs(t - y2) <= d;
2330 bs = Math.abs(b - y1) <= d;
2331 ls = Math.abs(l - x2) <= d;
2332 rs = Math.abs(r - x1) <= d;
2333 if(ts) {
2334 ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
2335 }
2336 if(bs) {
2337 ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
2338 }
2339 if(ls) {
2340 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
2341 }
2342 if(rs) {
2343 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
2344 }
2345 }
2346
2347 first = (ts || bs || ls || rs);
2348
2349 if(o.snapMode !== "outer") {
2350 ts = Math.abs(t - y1) <= d;
2351 bs = Math.abs(b - y2) <= d;
2352 ls = Math.abs(l - x1) <= d;
2353 rs = Math.abs(r - x2) <= d;
2354 if(ts) {
2355 ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
2356 }
2357 if(bs) {
2358 ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
2359 }
2360 if(ls) {
2361 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
2362 }
2363 if(rs) {
2364 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
2365 }
2366 }
2367
2368 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
2369 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
2370 }
2371 inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
2372
2373 }
2374
2375 }
2376 });
2377
2378 $.ui.plugin.add("draggable", "stack", {
2379 start: function() {
2380 var min,
2381 o = this.data("ui-draggable").options,
2382 group = $.makeArray($(o.stack)).sort(function(a,b) {
2383 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
2384 });
2385
2386 if (!group.length) { return; }
2387
2388 min = parseInt($(group[0]).css("zIndex"), 10) || 0;
2389 $(group).each(function(i) {
2390 $(this).css("zIndex", min + i);
2391 });
2392 this.css("zIndex", (min + group.length));
2393 }
2394 });
2395
2396 $.ui.plugin.add("draggable", "zIndex", {
2397 start: function(event, ui) {
2398 var t = $(ui.helper), o = $(this).data("ui-draggable").options;
2399 if(t.css("zIndex")) {
2400 o._zIndex = t.css("zIndex");
2401 }
2402 t.css("zIndex", o.zIndex);
2403 },
2404 stop: function(event, ui) {
2405 var o = $(this).data("ui-draggable").options;
2406 if(o._zIndex) {
2407 $(ui.helper).css("zIndex", o._zIndex);
2408 }
2409 }
2410 });
2411
2412 })(jQuery);
2413 (function( $, undefined ) {
2414
2415 function isOverAxis( x, reference, size ) {
2416 return ( x > reference ) && ( x < ( reference + size ) );
2417 }
2418
2419 $.widget("ui.droppable", {
2420 version: "1.10.3",
2421 widgetEventPrefix: "drop",
2422 options: {
2423 accept: "*",
2424 activeClass: false,
2425 addClasses: true,
2426 greedy: false,
2427 hoverClass: false,
2428 scope: "default",
2429 tolerance: "intersect",
2430
2431 // callbacks
2432 activate: null,
2433 deactivate: null,
2434 drop: null,
2435 out: null,
2436 over: null
2437 },
2438 _create: function() {
2439
2440 var o = this.options,
2441 accept = o.accept;
2442
2443 this.isover = false;
2444 this.isout = true;
2445
2446 this.accept = $.isFunction(accept) ? accept : function(d) {
2447 return d.is(accept);
2448 };
2449
2450 //Store the droppable's proportions
2451 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
2452
2453 // Add the reference and positions to the manager
2454 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
2455 $.ui.ddmanager.droppables[o.scope].push(this);
2456
2457 (o.addClasses && this.element.addClass("ui-droppable"));
2458
2459 },
2460
2461 _destroy: function() {
2462 var i = 0,
2463 drop = $.ui.ddmanager.droppables[this.options.scope];
2464
2465 for ( ; i < drop.length; i++ ) {
2466 if ( drop[i] === this ) {
2467 drop.splice(i, 1);
2468 }
2469 }
2470
2471 this.element.removeClass("ui-droppable ui-droppable-disabled");
2472 },
2473
2474 _setOption: function(key, value) {
2475
2476 if(key === "accept") {
2477 this.accept = $.isFunction(value) ? value : function(d) {
2478 return d.is(value);
2479 };
2480 }
2481 $.Widget.prototype._setOption.apply(this, arguments);
2482 },
2483
2484 _activate: function(event) {
2485 var draggable = $.ui.ddmanager.current;
2486 if(this.options.activeClass) {
2487 this.element.addClass(this.options.activeClass);
2488 }
2489 if(draggable){
2490 this._trigger("activate", event, this.ui(draggable));
2491 }
2492 },
2493
2494 _deactivate: function(event) {
2495 var draggable = $.ui.ddmanager.current;
2496 if(this.options.activeClass) {
2497 this.element.removeClass(this.options.activeClass);
2498 }
2499 if(draggable){
2500 this._trigger("deactivate", event, this.ui(draggable));
2501 }
2502 },
2503
2504 _over: function(event) {
2505
2506 var draggable = $.ui.ddmanager.current;
2507
2508 // Bail if draggable and droppable are same element
2509 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
2510 return;
2511 }
2512
2513 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2514 if(this.options.hoverClass) {
2515 this.element.addClass(this.options.hoverClass);
2516 }
2517 this._trigger("over", event, this.ui(draggable));
2518 }
2519
2520 },
2521
2522 _out: function(event) {
2523
2524 var draggable = $.ui.ddmanager.current;
2525
2526 // Bail if draggable and droppable are same element
2527 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
2528 return;
2529 }
2530
2531 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2532 if(this.options.hoverClass) {
2533 this.element.removeClass(this.options.hoverClass);
2534 }
2535 this._trigger("out", event, this.ui(draggable));
2536 }
2537
2538 },
2539
2540 _drop: function(event,custom) {
2541
2542 var draggable = custom || $.ui.ddmanager.current,
2543 childrenIntersection = false;
2544
2545 // Bail if draggable and droppable are same element
2546 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
2547 return false;
2548 }
2549
2550 this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() {
2551 var inst = $.data(this, "ui-droppable");
2552 if(
2553 inst.options.greedy &&
2554 !inst.options.disabled &&
2555 inst.options.scope === draggable.options.scope &&
2556 inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) &&
2557 $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
2558 ) { childrenIntersection = true; return false; }
2559 });
2560 if(childrenIntersection) {
2561 return false;
2562 }
2563
2564 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2565 if(this.options.activeClass) {
2566 this.element.removeClass(this.options.activeClass);
2567 }
2568 if(this.options.hoverClass) {
2569 this.element.removeClass(this.options.hoverClass);
2570 }
2571 this._trigger("drop", event, this.ui(draggable));
2572 return this.element;
2573 }
2574
2575 return false;
2576
2577 },
2578
2579 ui: function(c) {
2580 return {
2581 draggable: (c.currentItem || c.element),
2582 helper: c.helper,
2583 position: c.position,
2584 offset: c.positionAbs
2585 };
2586 }
2587
2588 });
2589
2590 $.ui.intersect = function(draggable, droppable, toleranceMode) {
2591
2592 if (!droppable.offset) {
2593 return false;
2594 }
2595
2596 var draggableLeft, draggableTop,
2597 x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
2598 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height,
2599 l = droppable.offset.left, r = l + droppable.proportions.width,
2600 t = droppable.offset.top, b = t + droppable.proportions.height;
2601
2602 switch (toleranceMode) {
2603 case "fit":
2604 return (l <= x1 && x2 <= r && t <= y1 && y2 <= b);
2605 case "intersect":
2606 return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half
2607 x2 - (draggable.helperProportions.width / 2) < r && // Left Half
2608 t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half
2609 y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
2610 case "pointer":
2611 draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left);
2612 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top);
2613 return isOverAxis( draggableTop, t, droppable.proportions.height ) && isOverAxis( draggableLeft, l, droppable.proportions.width );
2614 case "touch":
2615 return (
2616 (y1 >= t && y1 <= b) || // Top edge touching
2617 (y2 >= t && y2 <= b) || // Bottom edge touching
2618 (y1 < t && y2 > b) // Surrounded vertically
2619 ) && (
2620 (x1 >= l && x1 <= r) || // Left edge touching
2621 (x2 >= l && x2 <= r) || // Right edge touching
2622 (x1 < l && x2 > r) // Surrounded horizontally
2623 );
2624 default:
2625 return false;
2626 }
2627
2628 };
2629
2630 /*
2631 This manager tracks offsets of draggables and droppables
2632 */
2633 $.ui.ddmanager = {
2634 current: null,
2635 droppables: { "default": [] },
2636 prepareOffsets: function(t, event) {
2637
2638 var i, j,
2639 m = $.ui.ddmanager.droppables[t.options.scope] || [],
2640 type = event ? event.type : null, // workaround for #2317
2641 list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack();
2642
2643 droppablesLoop: for (i = 0; i < m.length; i++) {
2644
2645 //No disabled and non-accepted
2646 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) {
2647 continue;
2648 }
2649
2650 // Filter out elements in the current dragged item
2651 for (j=0; j < list.length; j++) {
2652 if(list[j] === m[i].element[0]) {
2653 m[i].proportions.height = 0;
2654 continue droppablesLoop;
2655 }
2656 }
2657
2658 m[i].visible = m[i].element.css("display") !== "none";
2659 if(!m[i].visible) {
2660 continue;
2661 }
2662
2663 //Activate the droppable if used directly from draggables
2664 if(type === "mousedown") {
2665 m[i]._activate.call(m[i], event);
2666 }
2667
2668 m[i].offset = m[i].element.offset();
2669 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
2670
2671 }
2672
2673 },
2674 drop: function(draggable, event) {
2675
2676 var dropped = false;
2677 // Create a copy of the droppables in case the list changes during the drop (#9116)
2678 $.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function() {
2679
2680 if(!this.options) {
2681 return;
2682 }
2683 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) {
2684 dropped = this._drop.call(this, event) || dropped;
2685 }
2686
2687 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2688 this.isout = true;
2689 this.isover = false;
2690 this._deactivate.call(this, event);
2691 }
2692
2693 });
2694 return dropped;
2695
2696 },
2697 dragStart: function( draggable, event ) {
2698 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
2699 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
2700 if( !draggable.options.refreshPositions ) {
2701 $.ui.ddmanager.prepareOffsets( draggable, event );
2702 }
2703 });
2704 },
2705 drag: function(draggable, event) {
2706
2707 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
2708 if(draggable.options.refreshPositions) {
2709 $.ui.ddmanager.prepareOffsets(draggable, event);
2710 }
2711
2712 //Run through all droppables and check their positions based on specific tolerance options
2713 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
2714
2715 if(this.options.disabled || this.greedyChild || !this.visible) {
2716 return;
2717 }
2718
2719 var parentInstance, scope, parent,
2720 intersects = $.ui.intersect(draggable, this, this.options.tolerance),
2721 c = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null);
2722 if(!c) {
2723 return;
2724 }
2725
2726 if (this.options.greedy) {
2727 // find droppable parents with same scope
2728 scope = this.options.scope;
2729 parent = this.element.parents(":data(ui-droppable)").filter(function () {
2730 return $.data(this, "ui-droppable").options.scope === scope;
2731 });
2732
2733 if (parent.length) {
2734 parentInstance = $.data(parent[0], "ui-droppable");
2735 parentInstance.greedyChild = (c === "isover");
2736 }
2737 }
2738
2739 // we just moved into a greedy child
2740 if (parentInstance && c === "isover") {
2741 parentInstance.isover = false;
2742 parentInstance.isout = true;
2743 parentInstance._out.call(parentInstance, event);
2744 }
2745
2746 this[c] = true;
2747 this[c === "isout" ? "isover" : "isout"] = false;
2748 this[c === "isover" ? "_over" : "_out"].call(this, event);
2749
2750 // we just moved out of a greedy child
2751 if (parentInstance && c === "isout") {
2752 parentInstance.isout = false;
2753 parentInstance.isover = true;
2754 parentInstance._over.call(parentInstance, event);
2755 }
2756 });
2757
2758 },
2759 dragStop: function( draggable, event ) {
2760 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
2761 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
2762 if( !draggable.options.refreshPositions ) {
2763 $.ui.ddmanager.prepareOffsets( draggable, event );
2764 }
2765 }
2766 };
2767
2768 })(jQuery);
2769 (function( $, undefined ) {
2770
2771 function num(v) {
2772 return parseInt(v, 10) || 0;
2773 }
2774
2775 function isNumber(value) {
2776 return !isNaN(parseInt(value, 10));
2777 }
2778
2779 $.widget("ui.resizable", $.ui.mouse, {
2780 version: "1.10.3",
2781 widgetEventPrefix: "resize",
2782 options: {
2783 alsoResize: false,
2784 animate: false,
2785 animateDuration: "slow",
2786 animateEasing: "swing",
2787 aspectRatio: false,
2788 autoHide: false,
2789 containment: false,
2790 ghost: false,
2791 grid: false,
2792 handles: "e,s,se",
2793 helper: false,
2794 maxHeight: null,
2795 maxWidth: null,
2796 minHeight: 10,
2797 minWidth: 10,
2798 // See #7960
2799 zIndex: 90,
2800
2801 // callbacks
2802 resize: null,
2803 start: null,
2804 stop: null
2805 },
2806 _create: function() {
2807
2808 var n, i, handle, axis, hname,
2809 that = this,
2810 o = this.options;
2811 this.element.addClass("ui-resizable");
2812
2813 $.extend(this, {
2814 _aspectRatio: !!(o.aspectRatio),
2815 aspectRatio: o.aspectRatio,
2816 originalElement: this.element,
2817 _proportionallyResizeElements: [],
2818 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
2819 });
2820
2821 //Wrap the element if it cannot hold child nodes
2822 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
2823
2824 //Create a wrapper element and set the wrapper to the new current internal element
2825 this.element.wrap(
2826 $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
2827 position: this.element.css("position"),
2828 width: this.element.outerWidth(),
2829 height: this.element.outerHeight(),
2830 top: this.element.css("top"),
2831 left: this.element.css("left")
2832 })
2833 );
2834
2835 //Overwrite the original this.element
2836 this.element = this.element.parent().data(
2837 "ui-resizable", this.element.data("ui-resizable")
2838 );
2839
2840 this.elementIsWrapper = true;
2841
2842 //Move margins to the wrapper
2843 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
2844 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
2845
2846 //Prevent Safari textarea resize
2847 this.originalResizeStyle = this.originalElement.css("resize");
2848 this.originalElement.css("resize", "none");
2849
2850 //Push the actual element to our proportionallyResize internal array
2851 this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" }));
2852
2853 // avoid IE jump (hard set the margin)
2854 this.originalElement.css({ margin: this.originalElement.css("margin") });
2855
2856 // fix handlers offset
2857 this._proportionallyResize();
2858
2859 }
2860
2861 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" });
2862 if(this.handles.constructor === String) {
2863
2864 if ( this.handles === "all") {
2865 this.handles = "n,e,s,w,se,sw,ne,nw";
2866 }
2867
2868 n = this.handles.split(",");
2869 this.handles = {};
2870
2871 for(i = 0; i < n.length; i++) {
2872
2873 handle = $.trim(n[i]);
2874 hname = "ui-resizable-"+handle;
2875 axis = $("<div class='ui-resizable-handle " + hname + "'></div>");
2876
2877 // Apply zIndex to all handles - see #7960
2878 axis.css({ zIndex: o.zIndex });
2879
2880 //TODO : What's going on here?
2881 if ("se" === handle) {
2882 axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
2883 }
2884
2885 //Insert into internal handles object and append to element
2886 this.handles[handle] = ".ui-resizable-"+handle;
2887 this.element.append(axis);
2888 }
2889
2890 }
2891
2892 this._renderAxis = function(target) {
2893
2894 var i, axis, padPos, padWrapper;
2895
2896 target = target || this.element;
2897
2898 for(i in this.handles) {
2899
2900 if(this.handles[i].constructor === String) {
2901 this.handles[i] = $(this.handles[i], this.element).show();
2902 }
2903
2904 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
2905 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
2906
2907 axis = $(this.handles[i], this.element);
2908
2909 //Checking the correct pad and border
2910 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
2911
2912 //The padding type i have to apply...
2913 padPos = [ "padding",
2914 /ne|nw|n/.test(i) ? "Top" :
2915 /se|sw|s/.test(i) ? "Bottom" :
2916 /^e$/.test(i) ? "Right" : "Left" ].join("");
2917
2918 target.css(padPos, padWrapper);
2919
2920 this._proportionallyResize();
2921
2922 }
2923
2924 //TODO: What's that good for? There's not anything to be executed left
2925 if(!$(this.handles[i]).length) {
2926 continue;
2927 }
2928 }
2929 };
2930
2931 //TODO: make renderAxis a prototype function
2932 this._renderAxis(this.element);
2933
2934 this._handles = $(".ui-resizable-handle", this.element)
2935 .disableSelection();
2936
2937 //Matching axis name
2938 this._handles.mouseover(function() {
2939 if (!that.resizing) {
2940 if (this.className) {
2941 axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
2942 }
2943 //Axis, default = se
2944 that.axis = axis && axis[1] ? axis[1] : "se";
2945 }
2946 });
2947
2948 //If we want to auto hide the elements
2949 if (o.autoHide) {
2950 this._handles.hide();
2951 $(this.element)
2952 .addClass("ui-resizable-autohide")
2953 .mouseenter(function() {
2954 if (o.disabled) {
2955 return;
2956 }
2957 $(this).removeClass("ui-resizable-autohide");
2958 that._handles.show();
2959 })
2960 .mouseleave(function(){
2961 if (o.disabled) {
2962 return;
2963 }
2964 if (!that.resizing) {
2965 $(this).addClass("ui-resizable-autohide");
2966 that._handles.hide();
2967 }
2968 });
2969 }
2970
2971 //Initialize the mouse interaction
2972 this._mouseInit();
2973
2974 },
2975
2976 _destroy: function() {
2977
2978 this._mouseDestroy();
2979
2980 var wrapper,
2981 _destroy = function(exp) {
2982 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
2983 .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove();
2984 };
2985
2986 //TODO: Unwrap at same DOM position
2987 if (this.elementIsWrapper) {
2988 _destroy(this.element);
2989 wrapper = this.element;
2990 this.originalElement.css({
2991 position: wrapper.css("position"),
2992 width: wrapper.outerWidth(),
2993 height: wrapper.outerHeight(),
2994 top: wrapper.css("top"),
2995 left: wrapper.css("left")
2996 }).insertAfter( wrapper );
2997 wrapper.remove();
2998 }
2999
3000 this.originalElement.css("resize", this.originalResizeStyle);
3001 _destroy(this.originalElement);
3002
3003 return this;
3004 },
3005
3006 _mouseCapture: function(event) {
3007 var i, handle,
3008 capture = false;
3009
3010 for (i in this.handles) {
3011 handle = $(this.handles[i])[0];
3012 if (handle === event.target || $.contains(handle, event.target)) {
3013 capture = true;
3014 }
3015 }
3016
3017 return !this.options.disabled && capture;
3018 },
3019
3020 _mouseStart: function(event) {
3021
3022 var curleft, curtop, cursor,
3023 o = this.options,
3024 iniPos = this.element.position(),
3025 el = this.element;
3026
3027 this.resizing = true;
3028
3029 // bugfix for http://dev.jquery.com/ticket/1749
3030 if ( (/absolute/).test( el.css("position") ) ) {
3031 el.css({ position: "absolute", top: el.css("top"), left: el.css("left") });
3032 } else if (el.is(".ui-draggable")) {
3033 el.css({ position: "absolute", top: iniPos.top, left: iniPos.left });
3034 }
3035
3036 this._renderProxy();
3037
3038 curleft = num(this.helper.css("left"));
3039 curtop = num(this.helper.css("top"));
3040
3041 if (o.containment) {
3042 curleft += $(o.containment).scrollLeft() || 0;
3043 curtop += $(o.containment).scrollTop() || 0;
3044 }
3045
3046 //Store needed variables
3047 this.offset = this.helper.offset();
3048 this.position = { left: curleft, top: curtop };
3049 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
3050 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
3051 this.originalPosition = { left: curleft, top: curtop };
3052 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
3053 this.originalMousePosition = { left: event.pageX, top: event.pageY };
3054
3055 //Aspect Ratio
3056 this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
3057
3058 cursor = $(".ui-resizable-" + this.axis).css("cursor");
3059 $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
3060
3061 el.addClass("ui-resizable-resizing");
3062 this._propagate("start", event);
3063 return true;
3064 },
3065
3066 _mouseDrag: function(event) {
3067
3068 //Increase performance, avoid regex
3069 var data,
3070 el = this.helper, props = {},
3071 smp = this.originalMousePosition,
3072 a = this.axis,
3073 prevTop = this.position.top,
3074 prevLeft = this.position.left,
3075 prevWidth = this.size.width,
3076 prevHeight = this.size.height,
3077 dx = (event.pageX-smp.left)||0,
3078 dy = (event.pageY-smp.top)||0,
3079 trigger = this._change[a];
3080
3081 if (!trigger) {
3082 return false;
3083 }
3084
3085 // Calculate the attrs that will be change
3086 data = trigger.apply(this, [event, dx, dy]);
3087
3088 // Put this in the mouseDrag handler since the user can start pressing shift while resizing
3089 this._updateVirtualBoundaries(event.shiftKey);
3090 if (this._aspectRatio || event.shiftKey) {
3091 data = this._updateRatio(data, event);
3092 }
3093
3094 data = this._respectSize(data, event);
3095
3096 this._updateCache(data);
3097
3098 // plugins callbacks need to be called first
3099 this._propagate("resize", event);
3100
3101 if (this.position.top !== prevTop) {
3102 props.top = this.position.top + "px";
3103 }
3104 if (this.position.left !== prevLeft) {
3105 props.left = this.position.left + "px";
3106 }
3107 if (this.size.width !== prevWidth) {
3108 props.width = this.size.width + "px";
3109 }
3110 if (this.size.height !== prevHeight) {
3111 props.height = this.size.height + "px";
3112 }
3113 el.css(props);
3114
3115 if (!this._helper && this._proportionallyResizeElements.length) {
3116 this._proportionallyResize();
3117 }
3118
3119 // Call the user callback if the element was resized
3120 if ( ! $.isEmptyObject(props) ) {
3121 this._trigger("resize", event, this.ui());
3122 }
3123
3124 return false;
3125 },
3126
3127 _mouseStop: function(event) {
3128
3129 this.resizing = false;
3130 var pr, ista, soffseth, soffsetw, s, left, top,
3131 o = this.options, that = this;
3132
3133 if(this._helper) {
3134
3135 pr = this._proportionallyResizeElements;
3136 ista = pr.length && (/textarea/i).test(pr[0].nodeName);
3137 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height;
3138 soffsetw = ista ? 0 : that.sizeDiff.width;
3139
3140 s = { width: (that.helper.width() - soffsetw), height: (that.helper.height() - soffseth) };
3141 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null;
3142 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
3143
3144 if (!o.animate) {
3145 this.element.css($.extend(s, { top: top, left: left }));
3146 }
3147
3148 that.helper.height(that.size.height);
3149 that.helper.width(that.size.width);
3150
3151 if (this._helper && !o.animate) {
3152 this._proportionallyResize();
3153 }
3154 }
3155
3156 $("body").css("cursor", "auto");
3157
3158 this.element.removeClass("ui-resizable-resizing");
3159
3160 this._propagate("stop", event);
3161
3162 if (this._helper) {
3163 this.helper.remove();
3164 }
3165
3166 return false;
3167
3168 },
3169
3170 _updateVirtualBoundaries: function(forceAspectRatio) {
3171 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
3172 o = this.options;
3173
3174 b = {
3175 minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
3176 maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
3177 minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
3178 maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
3179 };
3180
3181 if(this._aspectRatio || forceAspectRatio) {
3182 // We want to create an enclosing box whose aspect ration is the requested one
3183 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
3184 pMinWidth = b.minHeight * this.aspectRatio;
3185 pMinHeight = b.minWidth / this.aspectRatio;
3186 pMaxWidth = b.maxHeight * this.aspectRatio;
3187 pMaxHeight = b.maxWidth / this.aspectRatio;
3188
3189 if(pMinWidth > b.minWidth) {
3190 b.minWidth = pMinWidth;
3191 }
3192 if(pMinHeight > b.minHeight) {
3193 b.minHeight = pMinHeight;
3194 }
3195 if(pMaxWidth < b.maxWidth) {
3196 b.maxWidth = pMaxWidth;
3197 }
3198 if(pMaxHeight < b.maxHeight) {
3199 b.maxHeight = pMaxHeight;
3200 }
3201 }
3202 this._vBoundaries = b;
3203 },
3204
3205 _updateCache: function(data) {
3206 this.offset = this.helper.offset();
3207 if (isNumber(data.left)) {
3208 this.position.left = data.left;
3209 }
3210 if (isNumber(data.top)) {
3211 this.position.top = data.top;
3212 }
3213 if (isNumber(data.height)) {
3214 this.size.height = data.height;
3215 }
3216 if (isNumber(data.width)) {
3217 this.size.width = data.width;
3218 }
3219 },
3220
3221 _updateRatio: function( data ) {
3222
3223 var cpos = this.position,
3224 csize = this.size,
3225 a = this.axis;
3226
3227 if (isNumber(data.height)) {
3228 data.width = (data.height * this.aspectRatio);
3229 } else if (isNumber(data.width)) {
3230 data.height = (data.width / this.aspectRatio);
3231 }
3232
3233 if (a === "sw") {
3234 data.left = cpos.left + (csize.width - data.width);
3235 data.top = null;
3236 }
3237 if (a === "nw") {
3238 data.top = cpos.top + (csize.height - data.height);
3239 data.left = cpos.left + (csize.width - data.width);
3240 }
3241
3242 return data;
3243 },
3244
3245 _respectSize: function( data ) {
3246
3247 var o = this._vBoundaries,
3248 a = this.axis,
3249 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
3250 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
3251 dw = this.originalPosition.left + this.originalSize.width,
3252 dh = this.position.top + this.size.height,
3253 cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
3254 if (isminw) {
3255 data.width = o.minWidth;
3256 }
3257 if (isminh) {
3258 data.height = o.minHeight;
3259 }
3260 if (ismaxw) {
3261 data.width = o.maxWidth;
3262 }
3263 if (ismaxh) {
3264 data.height = o.maxHeight;
3265 }
3266
3267 if (isminw && cw) {
3268 data.left = dw - o.minWidth;
3269 }
3270 if (ismaxw && cw) {
3271 data.left = dw - o.maxWidth;
3272 }
3273 if (isminh && ch) {
3274 data.top = dh - o.minHeight;
3275 }
3276 if (ismaxh && ch) {
3277 data.top = dh - o.maxHeight;
3278 }
3279
3280 // fixing jump error on top/left - bug #2330
3281 if (!data.width && !data.height && !data.left && data.top) {
3282 data.top = null;
3283 } else if (!data.width && !data.height && !data.top && data.left) {
3284 data.left = null;
3285 }
3286
3287 return data;
3288 },
3289
3290 _proportionallyResize: function() {
3291
3292 if (!this._proportionallyResizeElements.length) {
3293 return;
3294 }
3295
3296 var i, j, borders, paddings, prel,
3297 element = this.helper || this.element;
3298
3299 for ( i=0; i < this._proportionallyResizeElements.length; i++) {
3300
3301 prel = this._proportionallyResizeElements[i];
3302
3303 if (!this.borderDif) {
3304 this.borderDif = [];
3305 borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")];
3306 paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")];
3307
3308 for ( j = 0; j < borders.length; j++ ) {
3309 this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 );
3310 }
3311 }
3312
3313 prel.css({
3314 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
3315 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
3316 });
3317
3318 }
3319
3320 },
3321
3322 _renderProxy: function() {
3323
3324 var el = this.element, o = this.options;
3325 this.elementOffset = el.offset();
3326
3327 if(this._helper) {
3328
3329 this.helper = this.helper || $("<div style='overflow:hidden;'></div>");
3330
3331 this.helper.addClass(this._helper).css({
3332 width: this.element.outerWidth() - 1,
3333 height: this.element.outerHeight() - 1,
3334 position: "absolute",
3335 left: this.elementOffset.left +"px",
3336 top: this.elementOffset.top +"px",
3337 zIndex: ++o.zIndex //TODO: Don't modify option
3338 });
3339
3340 this.helper
3341 .appendTo("body")
3342 .disableSelection();
3343
3344 } else {
3345 this.helper = this.element;
3346 }
3347
3348 },
3349
3350 _change: {
3351 e: function(event, dx) {
3352 return { width: this.originalSize.width + dx };
3353 },
3354 w: function(event, dx) {
3355 var cs = this.originalSize, sp = this.originalPosition;
3356 return { left: sp.left + dx, width: cs.width - dx };
3357 },
3358 n: function(event, dx, dy) {
3359 var cs = this.originalSize, sp = this.originalPosition;
3360 return { top: sp.top + dy, height: cs.height - dy };
3361 },
3362 s: function(event, dx, dy) {
3363 return { height: this.originalSize.height + dy };
3364 },
3365 se: function(event, dx, dy) {
3366 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
3367 },
3368 sw: function(event, dx, dy) {
3369 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
3370 },
3371 ne: function(event, dx, dy) {
3372 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
3373 },
3374 nw: function(event, dx, dy) {
3375 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
3376 }
3377 },
3378
3379 _propagate: function(n, event) {
3380 $.ui.plugin.call(this, n, [event, this.ui()]);
3381 (n !== "resize" && this._trigger(n, event, this.ui()));
3382 },
3383
3384 plugins: {},
3385
3386 ui: function() {
3387 return {
3388 originalElement: this.originalElement,
3389 element: this.element,
3390 helper: this.helper,
3391 position: this.position,
3392 size: this.size,
3393 originalSize: this.originalSize,
3394 originalPosition: this.originalPosition
3395 };
3396 }
3397
3398 });
3399
3400 /*
3401 * Resizable Extensions
3402 */
3403
3404 $.ui.plugin.add("resizable", "animate", {
3405
3406 stop: function( event ) {
3407 var that = $(this).data("ui-resizable"),
3408 o = that.options,
3409 pr = that._proportionallyResizeElements,
3410 ista = pr.length && (/textarea/i).test(pr[0].nodeName),
3411 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height,
3412 soffsetw = ista ? 0 : that.sizeDiff.width,
3413 style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
3414 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null,
3415 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
3416
3417 that.element.animate(
3418 $.extend(style, top && left ? { top: top, left: left } : {}), {
3419 duration: o.animateDuration,
3420 easing: o.animateEasing,
3421 step: function() {
3422
3423 var data = {
3424 width: parseInt(that.element.css("width"), 10),
3425 height: parseInt(that.element.css("height"), 10),
3426 top: parseInt(that.element.css("top"), 10),
3427 left: parseInt(that.element.css("left"), 10)
3428 };
3429
3430 if (pr && pr.length) {
3431 $(pr[0]).css({ width: data.width, height: data.height });
3432 }
3433
3434 // propagating resize, and updating values for each animation step
3435 that._updateCache(data);
3436 that._propagate("resize", event);
3437
3438 }
3439 }
3440 );
3441 }
3442
3443 });
3444
3445 $.ui.plugin.add("resizable", "containment", {
3446
3447 start: function() {
3448 var element, p, co, ch, cw, width, height,
3449 that = $(this).data("ui-resizable"),
3450 o = that.options,
3451 el = that.element,
3452 oc = o.containment,
3453 ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
3454
3455 if (!ce) {
3456 return;
3457 }
3458
3459 that.containerElement = $(ce);
3460
3461 if (/document/.test(oc) || oc === document) {
3462 that.containerOffset = { left: 0, top: 0 };
3463 that.containerPosition = { left: 0, top: 0 };
3464
3465 that.parentData = {
3466 element: $(document), left: 0, top: 0,
3467 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
3468 };
3469 }
3470
3471 // i'm a node, so compute top, left, right, bottom
3472 else {
3473 element = $(ce);
3474 p = [];
3475 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
3476
3477 that.containerOffset = element.offset();
3478 that.containerPosition = element.position();
3479 that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
3480
3481 co = that.containerOffset;
3482 ch = that.containerSize.height;
3483 cw = that.containerSize.width;
3484 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw );
3485 height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
3486
3487 that.parentData = {
3488 element: ce, left: co.left, top: co.top, width: width, height: height
3489 };
3490 }
3491 },
3492
3493 resize: function( event ) {
3494 var woset, hoset, isParent, isOffsetRelative,
3495 that = $(this).data("ui-resizable"),
3496 o = that.options,
3497 co = that.containerOffset, cp = that.position,
3498 pRatio = that._aspectRatio || event.shiftKey,
3499 cop = { top:0, left:0 }, ce = that.containerElement;
3500
3501 if (ce[0] !== document && (/static/).test(ce.css("position"))) {
3502 cop = co;
3503 }
3504
3505 if (cp.left < (that._helper ? co.left : 0)) {
3506 that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left));
3507 if (pRatio) {
3508 that.size.height = that.size.width / that.aspectRatio;
3509 }
3510 that.position.left = o.helper ? co.left : 0;
3511 }
3512
3513 if (cp.top < (that._helper ? co.top : 0)) {
3514 that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top);
3515 if (pRatio) {
3516 that.size.width = that.size.height * that.aspectRatio;
3517 }
3518 that.position.top = that._helper ? co.top : 0;
3519 }
3520
3521 that.offset.left = that.parentData.left+that.position.left;
3522 that.offset.top = that.parentData.top+that.position.top;
3523
3524 woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width );
3525 hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height );
3526
3527 isParent = that.containerElement.get(0) === that.element.parent().get(0);
3528 isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position"));
3529
3530 if(isParent && isOffsetRelative) {
3531 woset -= that.parentData.left;
3532 }
3533
3534 if (woset + that.size.width >= that.parentData.width) {
3535 that.size.width = that.parentData.width - woset;
3536 if (pRatio) {
3537 that.size.height = that.size.width / that.aspectRatio;
3538 }
3539 }
3540
3541 if (hoset + that.size.height >= that.parentData.height) {
3542 that.size.height = that.parentData.height - hoset;
3543 if (pRatio) {
3544 that.size.width = that.size.height * that.aspectRatio;
3545 }
3546 }
3547 },
3548
3549 stop: function(){
3550 var that = $(this).data("ui-resizable"),
3551 o = that.options,
3552 co = that.containerOffset,
3553 cop = that.containerPosition,
3554 ce = that.containerElement,
3555 helper = $(that.helper),
3556 ho = helper.offset(),
3557 w = helper.outerWidth() - that.sizeDiff.width,
3558 h = helper.outerHeight() - that.sizeDiff.height;
3559
3560 if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) {
3561 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
3562 }
3563
3564 if (that._helper && !o.animate && (/static/).test(ce.css("position"))) {
3565 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
3566 }
3567
3568 }
3569 });
3570
3571 $.ui.plugin.add("resizable", "alsoResize", {
3572
3573 start: function () {
3574 var that = $(this).data("ui-resizable"),
3575 o = that.options,
3576 _store = function (exp) {
3577 $(exp).each(function() {
3578 var el = $(this);
3579 el.data("ui-resizable-alsoresize", {
3580 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
3581 left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
3582 });
3583 });
3584 };
3585
3586 if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) {
3587 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
3588 else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
3589 }else{
3590 _store(o.alsoResize);
3591 }
3592 },
3593
3594 resize: function (event, ui) {
3595 var that = $(this).data("ui-resizable"),
3596 o = that.options,
3597 os = that.originalSize,
3598 op = that.originalPosition,
3599 delta = {
3600 height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0,
3601 top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0
3602 },
3603
3604 _alsoResize = function (exp, c) {
3605 $(exp).each(function() {
3606 var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
3607 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"];
3608
3609 $.each(css, function (i, prop) {
3610 var sum = (start[prop]||0) + (delta[prop]||0);
3611 if (sum && sum >= 0) {
3612 style[prop] = sum || null;
3613 }
3614 });
3615
3616 el.css(style);
3617 });
3618 };
3619
3620 if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) {
3621 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
3622 }else{
3623 _alsoResize(o.alsoResize);
3624 }
3625 },
3626
3627 stop: function () {
3628 $(this).removeData("resizable-alsoresize");
3629 }
3630 });
3631
3632 $.ui.plugin.add("resizable", "ghost", {
3633
3634 start: function() {
3635
3636 var that = $(this).data("ui-resizable"), o = that.options, cs = that.size;
3637
3638 that.ghost = that.originalElement.clone();
3639 that.ghost
3640 .css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
3641 .addClass("ui-resizable-ghost")
3642 .addClass(typeof o.ghost === "string" ? o.ghost : "");
3643
3644 that.ghost.appendTo(that.helper);
3645
3646 },
3647
3648 resize: function(){
3649 var that = $(this).data("ui-resizable");
3650 if (that.ghost) {
3651 that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width });
3652 }
3653 },
3654
3655 stop: function() {
3656 var that = $(this).data("ui-resizable");
3657 if (that.ghost && that.helper) {
3658 that.helper.get(0).removeChild(that.ghost.get(0));
3659 }
3660 }
3661
3662 });
3663
3664 $.ui.plugin.add("resizable", "grid", {
3665
3666 resize: function() {
3667 var that = $(this).data("ui-resizable"),
3668 o = that.options,
3669 cs = that.size,
3670 os = that.originalSize,
3671 op = that.originalPosition,
3672 a = that.axis,
3673 grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid,
3674 gridX = (grid[0]||1),
3675 gridY = (grid[1]||1),
3676 ox = Math.round((cs.width - os.width) / gridX) * gridX,
3677 oy = Math.round((cs.height - os.height) / gridY) * gridY,
3678 newWidth = os.width + ox,
3679 newHeight = os.height + oy,
3680 isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
3681 isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
3682 isMinWidth = o.minWidth && (o.minWidth > newWidth),
3683 isMinHeight = o.minHeight && (o.minHeight > newHeight);
3684
3685 o.grid = grid;
3686
3687 if (isMinWidth) {
3688 newWidth = newWidth + gridX;
3689 }
3690 if (isMinHeight) {
3691 newHeight = newHeight + gridY;
3692 }
3693 if (isMaxWidth) {
3694 newWidth = newWidth - gridX;
3695 }
3696 if (isMaxHeight) {
3697 newHeight = newHeight - gridY;
3698 }
3699
3700 if (/^(se|s|e)$/.test(a)) {
3701 that.size.width = newWidth;
3702 that.size.height = newHeight;
3703 } else if (/^(ne)$/.test(a)) {
3704 that.size.width = newWidth;
3705 that.size.height = newHeight;
3706 that.position.top = op.top - oy;
3707 } else if (/^(sw)$/.test(a)) {
3708 that.size.width = newWidth;
3709 that.size.height = newHeight;
3710 that.position.left = op.left - ox;
3711 } else {
3712 that.size.width = newWidth;
3713 that.size.height = newHeight;
3714 that.position.top = op.top - oy;
3715 that.position.left = op.left - ox;
3716 }
3717 }
3718
3719 });
3720
3721 })(jQuery);
3722 (function( $, undefined ) {
3723
3724 $.widget("ui.selectable", $.ui.mouse, {
3725 version: "1.10.3",
3726 options: {
3727 appendTo: "body",
3728 autoRefresh: true,
3729 distance: 0,
3730 filter: "*",
3731 tolerance: "touch",
3732
3733 // callbacks
3734 selected: null,
3735 selecting: null,
3736 start: null,
3737 stop: null,
3738 unselected: null,
3739 unselecting: null
3740 },
3741 _create: function() {
3742 var selectees,
3743 that = this;
3744
3745 this.element.addClass("ui-selectable");
3746
3747 this.dragged = false;
3748
3749 // cache selectee children based on filter
3750 this.refresh = function() {
3751 selectees = $(that.options.filter, that.element[0]);
3752 selectees.addClass("ui-selectee");
3753 selectees.each(function() {
3754 var $this = $(this),
3755 pos = $this.offset();
3756 $.data(this, "selectable-item", {
3757 element: this,
3758 $element: $this,
3759 left: pos.left,
3760 top: pos.top,
3761 right: pos.left + $this.outerWidth(),
3762 bottom: pos.top + $this.outerHeight(),
3763 startselected: false,
3764 selected: $this.hasClass("ui-selected"),
3765 selecting: $this.hasClass("ui-selecting"),
3766 unselecting: $this.hasClass("ui-unselecting")
3767 });
3768 });
3769 };
3770 this.refresh();
3771
3772 this.selectees = selectees.addClass("ui-selectee");
3773
3774 this._mouseInit();
3775
3776 this.helper = $("<div class='ui-selectable-helper'></div>");
3777 },
3778
3779 _destroy: function() {
3780 this.selectees
3781 .removeClass("ui-selectee")
3782 .removeData("selectable-item");
3783 this.element
3784 .removeClass("ui-selectable ui-selectable-disabled");
3785 this._mouseDestroy();
3786 },
3787
3788 _mouseStart: function(event) {
3789 var that = this,
3790 options = this.options;
3791
3792 this.opos = [event.pageX, event.pageY];
3793
3794 if (this.options.disabled) {
3795 return;
3796 }
3797
3798 this.selectees = $(options.filter, this.element[0]);
3799
3800 this._trigger("start", event);
3801
3802 $(options.appendTo).append(this.helper);
3803 // position helper (lasso)
3804 this.helper.css({
3805 "left": event.pageX,
3806 "top": event.pageY,
3807 "width": 0,
3808 "height": 0
3809 });
3810
3811 if (options.autoRefresh) {
3812 this.refresh();
3813 }
3814
3815 this.selectees.filter(".ui-selected").each(function() {
3816 var selectee = $.data(this, "selectable-item");
3817 selectee.startselected = true;
3818 if (!event.metaKey && !event.ctrlKey) {
3819 selectee.$element.removeClass("ui-selected");
3820 selectee.selected = false;
3821 selectee.$element.addClass("ui-unselecting");
3822 selectee.unselecting = true;
3823 // selectable UNSELECTING callback
3824 that._trigger("unselecting", event, {
3825 unselecting: selectee.element
3826 });
3827 }
3828 });
3829
3830 $(event.target).parents().addBack().each(function() {
3831 var doSelect,
3832 selectee = $.data(this, "selectable-item");
3833 if (selectee) {
3834 doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");
3835 selectee.$element
3836 .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
3837 .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
3838 selectee.unselecting = !doSelect;
3839 selectee.selecting = doSelect;
3840 selectee.selected = doSelect;
3841 // selectable (UN)SELECTING callback
3842 if (doSelect) {
3843 that._trigger("selecting", event, {
3844 selecting: selectee.element
3845 });
3846 } else {
3847 that._trigger("unselecting", event, {
3848 unselecting: selectee.element
3849 });
3850 }
3851 return false;
3852 }
3853 });
3854
3855 },
3856
3857 _mouseDrag: function(event) {
3858
3859 this.dragged = true;
3860
3861 if (this.options.disabled) {
3862 return;
3863 }
3864
3865 var tmp,
3866 that = this,
3867 options = this.options,
3868 x1 = this.opos[0],
3869 y1 = this.opos[1],
3870 x2 = event.pageX,
3871 y2 = event.pageY;
3872
3873 if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
3874 if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
3875 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
3876
3877 this.selectees.each(function() {
3878 var selectee = $.data(this, "selectable-item"),
3879 hit = false;
3880
3881 //prevent helper from being selected if appendTo: selectable
3882 if (!selectee || selectee.element === that.element[0]) {
3883 return;
3884 }
3885
3886 if (options.tolerance === "touch") {
3887 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
3888 } else if (options.tolerance === "fit") {
3889 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
3890 }
3891
3892 if (hit) {
3893 // SELECT
3894 if (selectee.selected) {
3895 selectee.$element.removeClass("ui-selected");
3896 selectee.selected = false;
3897 }
3898 if (selectee.unselecting) {
3899 selectee.$element.removeClass("ui-unselecting");
3900 selectee.unselecting = false;
3901 }
3902 if (!selectee.selecting) {
3903 selectee.$element.addClass("ui-selecting");
3904 selectee.selecting = true;
3905 // selectable SELECTING callback
3906 that._trigger("selecting", event, {
3907 selecting: selectee.element
3908 });
3909 }
3910 } else {
3911 // UNSELECT
3912 if (selectee.selecting) {
3913 if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
3914 selectee.$element.removeClass("ui-selecting");
3915 selectee.selecting = false;
3916 selectee.$element.addClass("ui-selected");
3917 selectee.selected = true;
3918 } else {
3919 selectee.$element.removeClass("ui-selecting");
3920 selectee.selecting = false;
3921 if (selectee.startselected) {
3922 selectee.$element.addClass("ui-unselecting");
3923 selectee.unselecting = true;
3924 }
3925 // selectable UNSELECTING callback
3926 that._trigger("unselecting", event, {
3927 unselecting: selectee.element
3928 });
3929 }
3930 }
3931 if (selectee.selected) {
3932 if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
3933 selectee.$element.removeClass("ui-selected");
3934 selectee.selected = false;
3935
3936 selectee.$element.addClass("ui-unselecting");
3937 selectee.unselecting = true;
3938 // selectable UNSELECTING callback
3939 that._trigger("unselecting", event, {
3940 unselecting: selectee.element
3941 });
3942 }
3943 }
3944 }
3945 });
3946
3947 return false;
3948 },
3949
3950 _mouseStop: function(event) {
3951 var that = this;
3952
3953 this.dragged = false;
3954
3955 $(".ui-unselecting", this.element[0]).each(function() {
3956 var selectee = $.data(this, "selectable-item");
3957 selectee.$element.removeClass("ui-unselecting");
3958 selectee.unselecting = false;
3959 selectee.startselected = false;
3960 that._trigger("unselected", event, {
3961 unselected: selectee.element
3962 });
3963 });
3964 $(".ui-selecting", this.element[0]).each(function() {
3965 var selectee = $.data(this, "selectable-item");
3966 selectee.$element.removeClass("ui-selecting").addClass("ui-selected");
3967 selectee.selecting = false;
3968 selectee.selected = true;
3969 selectee.startselected = true;
3970 that._trigger("selected", event, {
3971 selected: selectee.element
3972 });
3973 });
3974 this._trigger("stop", event);
3975
3976 this.helper.remove();
3977
3978 return false;
3979 }
3980
3981 });
3982
3983 })(jQuery);
3984 (function( $, undefined ) {
3985
3986 /*jshint loopfunc: true */
3987
3988 function isOverAxis( x, reference, size ) {
3989 return ( x > reference ) && ( x < ( reference + size ) );
3990 }
3991
3992 function isFloating(item) {
3993 return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display"));
3994 }
3995
3996 $.widget("ui.sortable", $.ui.mouse, {
3997 version: "1.10.3",
3998 widgetEventPrefix: "sort",
3999 ready: false,
4000 options: {
4001 appendTo: "parent",
4002 axis: false,
4003 connectWith: false,
4004 containment: false,
4005 cursor: "auto",
4006 cursorAt: false,
4007 dropOnEmpty: true,
4008 forcePlaceholderSize: false,
4009 forceHelperSize: false,
4010 grid: false,
4011 handle: false,
4012 helper: "original",
4013 items: "> *",
4014 opacity: false,
4015 placeholder: false,
4016 revert: false,
4017 scroll: true,
4018 scrollSensitivity: 20,
4019 scrollSpeed: 20,
4020 scope: "default",
4021 tolerance: "intersect",
4022 zIndex: 1000,
4023
4024 // callbacks
4025 activate: null,
4026 beforeStop: null,
4027 change: null,
4028 deactivate: null,
4029 out: null,
4030 over: null,
4031 receive: null,
4032 remove: null,
4033 sort: null,
4034 start: null,
4035 stop: null,
4036 update: null
4037 },
4038 _create: function() {
4039
4040 var o = this.options;
4041 this.containerCache = {};
4042 this.element.addClass("ui-sortable");
4043
4044 //Get the items
4045 this.refresh();
4046
4047 //Let's determine if the items are being displayed horizontally
4048 this.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false;
4049
4050 //Let's determine the parent's offset
4051 this.offset = this.element.offset();
4052
4053 //Initialize mouse events for interaction
4054 this._mouseInit();
4055
4056 //We're ready to go
4057 this.ready = true;
4058
4059 },
4060
4061 _destroy: function() {
4062 this.element
4063 .removeClass("ui-sortable ui-sortable-disabled");
4064 this._mouseDestroy();
4065
4066 for ( var i = this.items.length - 1; i >= 0; i-- ) {
4067 this.items[i].item.removeData(this.widgetName + "-item");
4068 }
4069
4070 return this;
4071 },
4072
4073 _setOption: function(key, value){
4074 if ( key === "disabled" ) {
4075 this.options[ key ] = value;
4076
4077 this.widget().toggleClass( "ui-sortable-disabled", !!value );
4078 } else {
4079 // Don't call widget base _setOption for disable as it adds ui-state-disabled class
4080 $.Widget.prototype._setOption.apply(this, arguments);
4081 }
4082 },
4083
4084 _mouseCapture: function(event, overrideHandle) {
4085 var currentItem = null,
4086 validHandle = false,
4087 that = this;
4088
4089 if (this.reverting) {
4090 return false;
4091 }
4092
4093 if(this.options.disabled || this.options.type === "static") {
4094 return false;
4095 }
4096
4097 //We have to refresh the items data once first
4098 this._refreshItems(event);
4099
4100 //Find out if the clicked node (or one of its parents) is a actual item in this.items
4101 $(event.target).parents().each(function() {
4102 if($.data(this, that.widgetName + "-item") === that) {
4103 currentItem = $(this);
4104 return false;
4105 }
4106 });
4107 if($.data(event.target, that.widgetName + "-item") === that) {
4108 currentItem = $(event.target);
4109 }
4110
4111 if(!currentItem) {
4112 return false;
4113 }
4114 if(this.options.handle && !overrideHandle) {
4115 $(this.options.handle, currentItem).find("*").addBack().each(function() {
4116 if(this === event.target) {
4117 validHandle = true;
4118 }
4119 });
4120 if(!validHandle) {
4121 return false;
4122 }
4123 }
4124
4125 this.currentItem = currentItem;
4126 this._removeCurrentsFromItems();
4127 return true;
4128
4129 },
4130
4131 _mouseStart: function(event, overrideHandle, noActivation) {
4132
4133 var i, body,
4134 o = this.options;
4135
4136 this.currentContainer = this;
4137
4138 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
4139 this.refreshPositions();
4140
4141 //Create and append the visible helper
4142 this.helper = this._createHelper(event);
4143
4144 //Cache the helper size
4145 this._cacheHelperProportions();
4146
4147 /*
4148 * - Position generation -
4149 * This block generates everything position related - it's the core of draggables.
4150 */
4151
4152 //Cache the margins of the original element
4153 this._cacheMargins();
4154
4155 //Get the next scrolling parent
4156 this.scrollParent = this.helper.scrollParent();
4157
4158 //The element's absolute position on the page minus margins
4159 this.offset = this.currentItem.offset();
4160 this.offset = {
4161 top: this.offset.top - this.margins.top,
4162 left: this.offset.left - this.margins.left
4163 };
4164
4165 $.extend(this.offset, {
4166 click: { //Where the click happened, relative to the element
4167 left: event.pageX - this.offset.left,
4168 top: event.pageY - this.offset.top
4169 },
4170 parent: this._getParentOffset(),
4171 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
4172 });
4173
4174 // Only after we got the offset, we can change the helper's position to absolute
4175 // TODO: Still need to figure out a way to make relative sorting possible
4176 this.helper.css("position", "absolute");
4177 this.cssPosition = this.helper.css("position");
4178
4179 //Generate the original position
4180 this.originalPosition = this._generatePosition(event);
4181 this.originalPageX = event.pageX;
4182 this.originalPageY = event.pageY;
4183
4184 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
4185 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
4186
4187 //Cache the former DOM position
4188 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
4189
4190 //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
4191 if(this.helper[0] !== this.currentItem[0]) {
4192 this.currentItem.hide();
4193 }
4194
4195 //Create the placeholder
4196 this._createPlaceholder();
4197
4198 //Set a containment if given in the options
4199 if(o.containment) {
4200 this._setContainment();
4201 }
4202
4203 if( o.cursor && o.cursor !== "auto" ) { // cursor option
4204 body = this.document.find( "body" );
4205
4206 // support: IE
4207 this.storedCursor = body.css( "cursor" );
4208 body.css( "cursor", o.cursor );
4209
4210 this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );
4211 }
4212
4213 if(o.opacity) { // opacity option
4214 if (this.helper.css("opacity")) {
4215 this._storedOpacity = this.helper.css("opacity");
4216 }
4217 this.helper.css("opacity", o.opacity);
4218 }
4219
4220 if(o.zIndex) { // zIndex option
4221 if (this.helper.css("zIndex")) {
4222 this._storedZIndex = this.helper.css("zIndex");
4223 }
4224 this.helper.css("zIndex", o.zIndex);
4225 }
4226
4227 //Prepare scrolling
4228 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
4229 this.overflowOffset = this.scrollParent.offset();
4230 }
4231
4232 //Call callbacks
4233 this._trigger("start", event, this._uiHash());
4234
4235 //Recache the helper size
4236 if(!this._preserveHelperProportions) {
4237 this._cacheHelperProportions();
4238 }
4239
4240
4241 //Post "activate" events to possible containers
4242 if( !noActivation ) {
4243 for ( i = this.containers.length - 1; i >= 0; i-- ) {
4244 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
4245 }
4246 }
4247
4248 //Prepare possible droppables
4249 if($.ui.ddmanager) {
4250 $.ui.ddmanager.current = this;
4251 }
4252
4253 if ($.ui.ddmanager && !o.dropBehaviour) {
4254 $.ui.ddmanager.prepareOffsets(this, event);
4255 }
4256
4257 this.dragging = true;
4258
4259 this.helper.addClass("ui-sortable-helper");
4260 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
4261 return true;
4262
4263 },
4264
4265 _mouseDrag: function(event) {
4266 var i, item, itemElement, intersection,
4267 o = this.options,
4268 scrolled = false;
4269
4270 //Compute the helpers position
4271 this.position = this._generatePosition(event);
4272 this.positionAbs = this._convertPositionTo("absolute");
4273
4274 if (!this.lastPositionAbs) {
4275 this.lastPositionAbs = this.positionAbs;
4276 }
4277
4278 //Do scrolling
4279 if(this.options.scroll) {
4280 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
4281
4282 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
4283 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
4284 } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
4285 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
4286 }
4287
4288 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
4289 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
4290 } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
4291 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
4292 }
4293
4294 } else {
4295
4296 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
4297 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
4298 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
4299 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
4300 }
4301
4302 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
4303 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
4304 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
4305 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
4306 }
4307
4308 }
4309
4310 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
4311 $.ui.ddmanager.prepareOffsets(this, event);
4312 }
4313 }
4314
4315 //Regenerate the absolute position used for position checks
4316 this.positionAbs = this._convertPositionTo("absolute");
4317
4318 //Set the helper position
4319 if(!this.options.axis || this.options.axis !== "y") {
4320 this.helper[0].style.left = this.position.left+"px";
4321 }
4322 if(!this.options.axis || this.options.axis !== "x") {
4323 this.helper[0].style.top = this.position.top+"px";
4324 }
4325
4326 //Rearrange
4327 for (i = this.items.length - 1; i >= 0; i--) {
4328
4329 //Cache variables and intersection, continue if no intersection
4330 item = this.items[i];
4331 itemElement = item.item[0];
4332 intersection = this._intersectsWithPointer(item);
4333 if (!intersection) {
4334 continue;
4335 }
4336
4337 // Only put the placeholder inside the current Container, skip all
4338 // items form other containers. This works because when moving
4339 // an item from one container to another the
4340 // currentContainer is switched before the placeholder is moved.
4341 //
4342 // Without this moving items in "sub-sortables" can cause the placeholder to jitter
4343 // beetween the outer and inner container.
4344 if (item.instance !== this.currentContainer) {
4345 continue;
4346 }
4347
4348 // cannot intersect with itself
4349 // no useless actions that have been done before
4350 // no action if the item moved is the parent of the item checked
4351 if (itemElement !== this.currentItem[0] &&
4352 this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
4353 !$.contains(this.placeholder[0], itemElement) &&
4354 (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
4355 ) {
4356
4357 this.direction = intersection === 1 ? "down" : "up";
4358
4359 if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
4360 this._rearrange(event, item);
4361 } else {
4362 break;
4363 }
4364
4365 this._trigger("change", event, this._uiHash());
4366 break;
4367 }
4368 }
4369
4370 //Post events to containers
4371 this._contactContainers(event);
4372
4373 //Interconnect with droppables
4374 if($.ui.ddmanager) {
4375 $.ui.ddmanager.drag(this, event);
4376 }
4377
4378 //Call callbacks
4379 this._trigger("sort", event, this._uiHash());
4380
4381 this.lastPositionAbs = this.positionAbs;
4382 return false;
4383
4384 },
4385
4386 _mouseStop: function(event, noPropagation) {
4387
4388 if(!event) {
4389 return;
4390 }
4391
4392 //If we are using droppables, inform the manager about the drop
4393 if ($.ui.ddmanager && !this.options.dropBehaviour) {
4394 $.ui.ddmanager.drop(this, event);
4395 }
4396
4397 if(this.options.revert) {
4398 var that = this,
4399 cur = this.placeholder.offset(),
4400 axis = this.options.axis,
4401 animation = {};
4402
4403 if ( !axis || axis === "x" ) {
4404 animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft);
4405 }
4406 if ( !axis || axis === "y" ) {
4407 animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop);
4408 }
4409 this.reverting = true;
4410 $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {
4411 that._clear(event);
4412 });
4413 } else {
4414 this._clear(event, noPropagation);
4415 }
4416
4417 return false;
4418
4419 },
4420
4421 cancel: function() {
4422
4423 if(this.dragging) {
4424
4425 this._mouseUp({ target: null });
4426
4427 if(this.options.helper === "original") {
4428 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
4429 } else {
4430 this.currentItem.show();
4431 }
4432
4433 //Post deactivating events to containers
4434 for (var i = this.containers.length - 1; i >= 0; i--){
4435 this.containers[i]._trigger("deactivate", null, this._uiHash(this));
4436 if(this.containers[i].containerCache.over) {
4437 this.containers[i]._trigger("out", null, this._uiHash(this));
4438 this.containers[i].containerCache.over = 0;
4439 }
4440 }
4441
4442 }
4443
4444 if (this.placeholder) {
4445 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
4446 if(this.placeholder[0].parentNode) {
4447 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
4448 }
4449 if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
4450 this.helper.remove();
4451 }
4452
4453 $.extend(this, {
4454 helper: null,
4455 dragging: false,
4456 reverting: false,
4457 _noFinalSort: null
4458 });
4459
4460 if(this.domPosition.prev) {
4461 $(this.domPosition.prev).after(this.currentItem);
4462 } else {
4463 $(this.domPosition.parent).prepend(this.currentItem);
4464 }
4465 }
4466
4467 return this;
4468
4469 },
4470
4471 serialize: function(o) {
4472
4473 var items = this._getItemsAsjQuery(o && o.connected),
4474 str = [];
4475 o = o || {};
4476
4477 $(items).each(function() {
4478 var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/));
4479 if (res) {
4480 str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));
4481 }
4482 });
4483
4484 if(!str.length && o.key) {
4485 str.push(o.key + "=");
4486 }
4487
4488 return str.join("&");
4489
4490 },
4491
4492 toArray: function(o) {
4493
4494 var items = this._getItemsAsjQuery(o && o.connected),
4495 ret = [];
4496
4497 o = o || {};
4498
4499 items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
4500 return ret;
4501
4502 },
4503
4504 /* Be careful with the following core functions */
4505 _intersectsWith: function(item) {
4506
4507 var x1 = this.positionAbs.left,
4508 x2 = x1 + this.helperProportions.width,
4509 y1 = this.positionAbs.top,
4510 y2 = y1 + this.helperProportions.height,
4511 l = item.left,
4512 r = l + item.width,
4513 t = item.top,
4514 b = t + item.height,
4515 dyClick = this.offset.click.top,
4516 dxClick = this.offset.click.left,
4517 isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),
4518 isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),
4519 isOverElement = isOverElementHeight && isOverElementWidth;
4520
4521 if ( this.options.tolerance === "pointer" ||
4522 this.options.forcePointerForContainers ||
4523 (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])
4524 ) {
4525 return isOverElement;
4526 } else {
4527
4528 return (l < x1 + (this.helperProportions.width / 2) && // Right Half
4529 x2 - (this.helperProportions.width / 2) < r && // Left Half
4530 t < y1 + (this.helperProportions.height / 2) && // Bottom Half
4531 y2 - (this.helperProportions.height / 2) < b ); // Top Half
4532
4533 }
4534 },
4535
4536 _intersectsWithPointer: function(item) {
4537
4538 var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
4539 isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
4540 isOverElement = isOverElementHeight && isOverElementWidth,
4541 verticalDirection = this._getDragVerticalDirection(),
4542 horizontalDirection = this._getDragHorizontalDirection();
4543
4544 if (!isOverElement) {
4545 return false;
4546 }
4547
4548 return this.floating ?
4549 ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )
4550 : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );
4551
4552 },
4553
4554 _intersectsWithSides: function(item) {
4555
4556 var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
4557 isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
4558 verticalDirection = this._getDragVerticalDirection(),
4559 horizontalDirection = this._getDragHorizontalDirection();
4560
4561 if (this.floating && horizontalDirection) {
4562 return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
4563 } else {
4564 return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
4565 }
4566
4567 },
4568
4569 _getDragVerticalDirection: function() {
4570 var delta = this.positionAbs.top - this.lastPositionAbs.top;
4571 return delta !== 0 && (delta > 0 ? "down" : "up");
4572 },
4573
4574 _getDragHorizontalDirection: function() {
4575 var delta = this.positionAbs.left - this.lastPositionAbs.left;
4576 return delta !== 0 && (delta > 0 ? "right" : "left");
4577 },
4578
4579 refresh: function(event) {
4580 this._refreshItems(event);
4581 this.refreshPositions();
4582 return this;
4583 },
4584
4585 _connectWith: function() {
4586 var options = this.options;
4587 return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
4588 },
4589
4590 _getItemsAsjQuery: function(connected) {
4591
4592 var i, j, cur, inst,
4593 items = [],
4594 queries = [],
4595 connectWith = this._connectWith();
4596
4597 if(connectWith && connected) {
4598 for (i = connectWith.length - 1; i >= 0; i--){
4599 cur = $(connectWith[i]);
4600 for ( j = cur.length - 1; j >= 0; j--){
4601 inst = $.data(cur[j], this.widgetFullName);
4602 if(inst && inst !== this && !inst.options.disabled) {
4603 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]);
4604 }
4605 }
4606 }
4607 }
4608
4609 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]);
4610
4611 for (i = queries.length - 1; i >= 0; i--){
4612 queries[i][0].each(function() {
4613 items.push(this);
4614 });
4615 }
4616
4617 return $(items);
4618
4619 },
4620
4621 _removeCurrentsFromItems: function() {
4622
4623 var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
4624
4625 this.items = $.grep(this.items, function (item) {
4626 for (var j=0; j < list.length; j++) {
4627 if(list[j] === item.item[0]) {
4628 return false;
4629 }
4630 }
4631 return true;
4632 });
4633
4634 },
4635
4636 _refreshItems: function(event) {
4637
4638 this.items = [];
4639 this.containers = [this];
4640
4641 var i, j, cur, inst, targetData, _queries, item, queriesLength,
4642 items = this.items,
4643 queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],
4644 connectWith = this._connectWith();
4645
4646 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
4647 for (i = connectWith.length - 1; i >= 0; i--){
4648 cur = $(connectWith[i]);
4649 for (j = cur.length - 1; j >= 0; j--){
4650 inst = $.data(cur[j], this.widgetFullName);
4651 if(inst && inst !== this && !inst.options.disabled) {
4652 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
4653 this.containers.push(inst);
4654 }
4655 }
4656 }
4657 }
4658
4659 for (i = queries.length - 1; i >= 0; i--) {
4660 targetData = queries[i][1];
4661 _queries = queries[i][0];
4662
4663 for (j=0, queriesLength = _queries.length; j < queriesLength; j++) {
4664 item = $(_queries[j]);
4665
4666 item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)
4667
4668 items.push({
4669 item: item,
4670 instance: targetData,
4671 width: 0, height: 0,
4672 left: 0, top: 0
4673 });
4674 }
4675 }
4676
4677 },
4678
4679 refreshPositions: function(fast) {
4680
4681 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
4682 if(this.offsetParent && this.helper) {
4683 this.offset.parent = this._getParentOffset();
4684 }
4685
4686 var i, item, t, p;
4687
4688 for (i = this.items.length - 1; i >= 0; i--){
4689 item = this.items[i];
4690
4691 //We ignore calculating positions of all connected containers when we're not over them
4692 if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
4693 continue;
4694 }
4695
4696 t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
4697
4698 if (!fast) {
4699 item.width = t.outerWidth();
4700 item.height = t.outerHeight();
4701 }
4702
4703 p = t.offset();
4704 item.left = p.left;
4705 item.top = p.top;
4706 }
4707
4708 if(this.options.custom && this.options.custom.refreshContainers) {
4709 this.options.custom.refreshContainers.call(this);
4710 } else {
4711 for (i = this.containers.length - 1; i >= 0; i--){
4712 p = this.containers[i].element.offset();
4713 this.containers[i].containerCache.left = p.left;
4714 this.containers[i].containerCache.top = p.top;
4715 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
4716 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
4717 }
4718 }
4719
4720 return this;
4721 },
4722
4723 _createPlaceholder: function(that) {
4724 that = that || this;
4725 var className,
4726 o = that.options;
4727
4728 if(!o.placeholder || o.placeholder.constructor === String) {
4729 className = o.placeholder;
4730 o.placeholder = {
4731 element: function() {
4732
4733 var nodeName = that.currentItem[0].nodeName.toLowerCase(),
4734 element = $( "<" + nodeName + ">", that.document[0] )
4735 .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
4736 .removeClass("ui-sortable-helper");
4737
4738 if ( nodeName === "tr" ) {
4739 that.currentItem.children().each(function() {
4740 $( "<td>&#160;</td>", that.document[0] )
4741 .attr( "colspan", $( this ).attr( "colspan" ) || 1 )
4742 .appendTo( element );
4743 });
4744 } else if ( nodeName === "img" ) {
4745 element.attr( "src", that.currentItem.attr( "src" ) );
4746 }
4747
4748 if ( !className ) {
4749 element.css( "visibility", "hidden" );
4750 }
4751
4752 return element;
4753 },
4754 update: function(container, p) {
4755
4756 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
4757 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
4758 if(className && !o.forcePlaceholderSize) {
4759 return;
4760 }
4761
4762 //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
4763 if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }
4764 if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }
4765 }
4766 };
4767 }
4768
4769 //Create the placeholder
4770 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
4771
4772 //Append it after the actual current item
4773 that.currentItem.after(that.placeholder);
4774
4775 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
4776 o.placeholder.update(that, that.placeholder);
4777
4778 },
4779
4780 _contactContainers: function(event) {
4781 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating,
4782 innermostContainer = null,
4783 innermostIndex = null;
4784
4785 // get innermost container that intersects with item
4786 for (i = this.containers.length - 1; i >= 0; i--) {
4787
4788 // never consider a container that's located within the item itself
4789 if($.contains(this.currentItem[0], this.containers[i].element[0])) {
4790 continue;
4791 }
4792
4793 if(this._intersectsWith(this.containers[i].containerCache)) {
4794
4795 // if we've already found a container and it's more "inner" than this, then continue
4796 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
4797 continue;
4798 }
4799
4800 innermostContainer = this.containers[i];
4801 innermostIndex = i;
4802
4803 } else {
4804 // container doesn't intersect. trigger "out" event if necessary
4805 if(this.containers[i].containerCache.over) {
4806 this.containers[i]._trigger("out", event, this._uiHash(this));
4807 this.containers[i].containerCache.over = 0;
4808 }
4809 }
4810
4811 }
4812
4813 // if no intersecting containers found, return
4814 if(!innermostContainer) {
4815 return;
4816 }
4817
4818 // move the item into the container if it's not there already
4819 if(this.containers.length === 1) {
4820 if (!this.containers[innermostIndex].containerCache.over) {
4821 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
4822 this.containers[innermostIndex].containerCache.over = 1;
4823 }
4824 } else {
4825
4826 //When entering a new container, we will find the item with the least distance and append our item near it
4827 dist = 10000;
4828 itemWithLeastDistance = null;
4829 floating = innermostContainer.floating || isFloating(this.currentItem);
4830 posProperty = floating ? "left" : "top";
4831 sizeProperty = floating ? "width" : "height";
4832 base = this.positionAbs[posProperty] + this.offset.click[posProperty];
4833 for (j = this.items.length - 1; j >= 0; j--) {
4834 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
4835 continue;
4836 }
4837 if(this.items[j].item[0] === this.currentItem[0]) {
4838 continue;
4839 }
4840 if (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) {
4841 continue;
4842 }
4843 cur = this.items[j].item.offset()[posProperty];
4844 nearBottom = false;
4845 if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){
4846 nearBottom = true;
4847 cur += this.items[j][sizeProperty];
4848 }
4849
4850 if(Math.abs(cur - base) < dist) {
4851 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
4852 this.direction = nearBottom ? "up": "down";
4853 }
4854 }
4855
4856 //Check if dropOnEmpty is enabled
4857 if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
4858 return;
4859 }
4860
4861 if(this.currentContainer === this.containers[innermostIndex]) {
4862 return;
4863 }
4864
4865 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
4866 this._trigger("change", event, this._uiHash());
4867 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
4868 this.currentContainer = this.containers[innermostIndex];
4869
4870 //Update the placeholder
4871 this.options.placeholder.update(this.currentContainer, this.placeholder);
4872
4873 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
4874 this.containers[innermostIndex].containerCache.over = 1;
4875 }
4876
4877
4878 },
4879
4880 _createHelper: function(event) {
4881
4882 var o = this.options,
4883 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);
4884
4885 //Add the helper to the DOM if that didn't happen already
4886 if(!helper.parents("body").length) {
4887 $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
4888 }
4889
4890 if(helper[0] === this.currentItem[0]) {
4891 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") };
4892 }
4893
4894 if(!helper[0].style.width || o.forceHelperSize) {
4895 helper.width(this.currentItem.width());
4896 }
4897 if(!helper[0].style.height || o.forceHelperSize) {
4898 helper.height(this.currentItem.height());
4899 }
4900
4901 return helper;
4902
4903 },
4904
4905 _adjustOffsetFromHelper: function(obj) {
4906 if (typeof obj === "string") {
4907 obj = obj.split(" ");
4908 }
4909 if ($.isArray(obj)) {
4910 obj = {left: +obj[0], top: +obj[1] || 0};
4911 }
4912 if ("left" in obj) {
4913 this.offset.click.left = obj.left + this.margins.left;
4914 }
4915 if ("right" in obj) {
4916 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
4917 }
4918 if ("top" in obj) {
4919 this.offset.click.top = obj.top + this.margins.top;
4920 }
4921 if ("bottom" in obj) {
4922 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
4923 }
4924 },
4925
4926 _getParentOffset: function() {
4927
4928
4929 //Get the offsetParent and cache its position
4930 this.offsetParent = this.helper.offsetParent();
4931 var po = this.offsetParent.offset();
4932
4933 // This is a special case where we need to modify a offset calculated on start, since the following happened:
4934 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
4935 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
4936 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
4937 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
4938 po.left += this.scrollParent.scrollLeft();
4939 po.top += this.scrollParent.scrollTop();
4940 }
4941
4942 // This needs to be actually done for all browsers, since pageX/pageY includes this information
4943 // with an ugly IE fix
4944 if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
4945 po = { top: 0, left: 0 };
4946 }
4947
4948 return {
4949 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
4950 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
4951 };
4952
4953 },
4954
4955 _getRelativeOffset: function() {
4956
4957 if(this.cssPosition === "relative") {
4958 var p = this.currentItem.position();
4959 return {
4960 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
4961 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
4962 };
4963 } else {
4964 return { top: 0, left: 0 };
4965 }
4966
4967 },
4968
4969 _cacheMargins: function() {
4970 this.margins = {
4971 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
4972 top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
4973 };
4974 },
4975
4976 _cacheHelperProportions: function() {
4977 this.helperProportions = {
4978 width: this.helper.outerWidth(),
4979 height: this.helper.outerHeight()
4980 };
4981 },
4982
4983 _setContainment: function() {
4984
4985 var ce, co, over,
4986 o = this.options;
4987 if(o.containment === "parent") {
4988 o.containment = this.helper[0].parentNode;
4989 }
4990 if(o.containment === "document" || o.containment === "window") {
4991 this.containment = [
4992 0 - this.offset.relative.left - this.offset.parent.left,
4993 0 - this.offset.relative.top - this.offset.parent.top,
4994 $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left,
4995 ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
4996 ];
4997 }
4998
4999 if(!(/^(document|window|parent)$/).test(o.containment)) {
5000 ce = $(o.containment)[0];
5001 co = $(o.containment).offset();
5002 over = ($(ce).css("overflow") !== "hidden");
5003
5004 this.containment = [
5005 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
5006 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
5007 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,
5008 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
5009 ];
5010 }
5011
5012 },
5013
5014 _convertPositionTo: function(d, pos) {
5015
5016 if(!pos) {
5017 pos = this.position;
5018 }
5019 var mod = d === "absolute" ? 1 : -1,
5020 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
5021 scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
5022
5023 return {
5024 top: (
5025 pos.top + // The absolute mouse position
5026 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
5027 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
5028 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
5029 ),
5030 left: (
5031 pos.left + // The absolute mouse position
5032 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
5033 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
5034 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
5035 )
5036 };
5037
5038 },
5039
5040 _generatePosition: function(event) {
5041
5042 var top, left,
5043 o = this.options,
5044 pageX = event.pageX,
5045 pageY = event.pageY,
5046 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);
5047
5048 // This is another very weird special case that only happens for relative elements:
5049 // 1. If the css position is relative
5050 // 2. and the scroll parent is the document or similar to the offset parent
5051 // we have to refresh the relative offset during the scroll so there are no jumps
5052 if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) {
5053 this.offset.relative = this._getRelativeOffset();
5054 }
5055
5056 /*
5057 * - Position constraining -
5058 * Constrain the position to a mix of grid, containment.
5059 */
5060
5061 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
5062
5063 if(this.containment) {
5064 if(event.pageX - this.offset.click.left < this.containment[0]) {
5065 pageX = this.containment[0] + this.offset.click.left;
5066 }
5067 if(event.pageY - this.offset.click.top < this.containment[1]) {
5068 pageY = this.containment[1] + this.offset.click.top;
5069 }
5070 if(event.pageX - this.offset.click.left > this.containment[2]) {
5071 pageX = this.containment[2] + this.offset.click.left;
5072 }
5073 if(event.pageY - this.offset.click.top > this.containment[3]) {
5074 pageY = this.containment[3] + this.offset.click.top;
5075 }
5076 }
5077
5078 if(o.grid) {
5079 top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
5080 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;
5081
5082 left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
5083 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;
5084 }
5085
5086 }
5087
5088 return {
5089 top: (
5090 pageY - // The absolute mouse position
5091 this.offset.click.top - // Click offset (relative to the element)
5092 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
5093 this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
5094 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
5095 ),
5096 left: (
5097 pageX - // The absolute mouse position
5098 this.offset.click.left - // Click offset (relative to the element)
5099 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
5100 this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
5101 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
5102 )
5103 };
5104
5105 },
5106
5107 _rearrange: function(event, i, a, hardRefresh) {
5108
5109 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));
5110
5111 //Various things done here to improve the performance:
5112 // 1. we create a setTimeout, that calls refreshPositions
5113 // 2. on the instance, we have a counter variable, that get's higher after every append
5114 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
5115 // 4. this lets only the last addition to the timeout stack through
5116 this.counter = this.counter ? ++this.counter : 1;
5117 var counter = this.counter;
5118
5119 this._delay(function() {
5120 if(counter === this.counter) {
5121 this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
5122 }
5123 });
5124
5125 },
5126
5127 _clear: function(event, noPropagation) {
5128
5129 this.reverting = false;
5130 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
5131 // everything else normalized again
5132 var i,
5133 delayedTriggers = [];
5134
5135 // We first have to update the dom position of the actual currentItem
5136 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
5137 if(!this._noFinalSort && this.currentItem.parent().length) {
5138 this.placeholder.before(this.currentItem);
5139 }
5140 this._noFinalSort = null;
5141
5142 if(this.helper[0] === this.currentItem[0]) {
5143 for(i in this._storedCSS) {
5144 if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
5145 this._storedCSS[i] = "";
5146 }
5147 }
5148 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
5149 } else {
5150 this.currentItem.show();
5151 }
5152
5153 if(this.fromOutside && !noPropagation) {
5154 delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
5155 }
5156 if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
5157 delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
5158 }
5159
5160 // Check if the items Container has Changed and trigger appropriate
5161 // events.
5162 if (this !== this.currentContainer) {
5163 if(!noPropagation) {
5164 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
5165 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
5166 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
5167 }
5168 }
5169
5170
5171 //Post events to containers
5172 for (i = this.containers.length - 1; i >= 0; i--){
5173 if(!noPropagation) {
5174 delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
5175 }
5176 if(this.containers[i].containerCache.over) {
5177 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
5178 this.containers[i].containerCache.over = 0;
5179 }
5180 }
5181
5182 //Do what was originally in plugins
5183 if ( this.storedCursor ) {
5184 this.document.find( "body" ).css( "cursor", this.storedCursor );
5185 this.storedStylesheet.remove();
5186 }
5187 if(this._storedOpacity) {
5188 this.helper.css("opacity", this._storedOpacity);
5189 }
5190 if(this._storedZIndex) {
5191 this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
5192 }
5193
5194 this.dragging = false;
5195 if(this.cancelHelperRemoval) {
5196 if(!noPropagation) {
5197 this._trigger("beforeStop", event, this._uiHash());
5198 for (i=0; i < delayedTriggers.length; i++) {
5199 delayedTriggers[i].call(this, event);
5200 } //Trigger all delayed events
5201 this._trigger("stop", event, this._uiHash());
5202 }
5203
5204 this.fromOutside = false;
5205 return false;
5206 }
5207
5208 if(!noPropagation) {
5209 this._trigger("beforeStop", event, this._uiHash());
5210 }
5211
5212 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
5213 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
5214
5215 if(this.helper[0] !== this.currentItem[0]) {
5216 this.helper.remove();
5217 }
5218 this.helper = null;
5219
5220 if(!noPropagation) {
5221 for (i=0; i < delayedTriggers.length; i++) {
5222 delayedTriggers[i].call(this, event);
5223 } //Trigger all delayed events
5224 this._trigger("stop", event, this._uiHash());
5225 }
5226
5227 this.fromOutside = false;
5228 return true;
5229
5230 },
5231
5232 _trigger: function() {
5233 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
5234 this.cancel();
5235 }
5236 },
5237
5238 _uiHash: function(_inst) {
5239 var inst = _inst || this;
5240 return {
5241 helper: inst.helper,
5242 placeholder: inst.placeholder || $([]),
5243 position: inst.position,
5244 originalPosition: inst.originalPosition,
5245 offset: inst.positionAbs,
5246 item: inst.currentItem,
5247 sender: _inst ? _inst.element : null
5248 };
5249 }
5250
5251 });
5252
5253 })(jQuery);
5254 (function( $, undefined ) {
5255
5256 var uid = 0,
5257 hideProps = {},
5258 showProps = {};
5259
5260 hideProps.height = hideProps.paddingTop = hideProps.paddingBottom =
5261 hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide";
5262 showProps.height = showProps.paddingTop = showProps.paddingBottom =
5263 showProps.borderTopWidth = showProps.borderBottomWidth = "show";
5264
5265 $.widget( "ui.accordion", {
5266 version: "1.10.3",
5267 options: {
5268 active: 0,
5269 animate: {},
5270 collapsible: false,
5271 event: "click",
5272 header: "> li > :first-child,> :not(li):even",
5273 heightStyle: "auto",
5274 icons: {
5275 activeHeader: "ui-icon-triangle-1-s",
5276 header: "ui-icon-triangle-1-e"
5277 },
5278
5279 // callbacks
5280 activate: null,
5281 beforeActivate: null
5282 },
5283
5284 _create: function() {
5285 var options = this.options;
5286 this.prevShow = this.prevHide = $();
5287 this.element.addClass( "ui-accordion ui-widget ui-helper-reset" )
5288 // ARIA
5289 .attr( "role", "tablist" );
5290
5291 // don't allow collapsible: false and active: false / null
5292 if ( !options.collapsible && (options.active === false || options.active == null) ) {
5293 options.active = 0;
5294 }
5295
5296 this._processPanels();
5297 // handle negative values
5298 if ( options.active < 0 ) {
5299 options.active += this.headers.length;
5300 }
5301 this._refresh();
5302 },
5303
5304 _getCreateEventData: function() {
5305 return {
5306 header: this.active,
5307 panel: !this.active.length ? $() : this.active.next(),
5308 content: !this.active.length ? $() : this.active.next()
5309 };
5310 },
5311
5312 _createIcons: function() {
5313 var icons = this.options.icons;
5314 if ( icons ) {
5315 $( "<span>" )
5316 .addClass( "ui-accordion-header-icon ui-icon " + icons.header )
5317 .prependTo( this.headers );
5318 this.active.children( ".ui-accordion-header-icon" )
5319 .removeClass( icons.header )
5320 .addClass( icons.activeHeader );
5321 this.headers.addClass( "ui-accordion-icons" );
5322 }
5323 },
5324
5325 _destroyIcons: function() {
5326 this.headers
5327 .removeClass( "ui-accordion-icons" )
5328 .children( ".ui-accordion-header-icon" )
5329 .remove();
5330 },
5331
5332 _destroy: function() {
5333 var contents;
5334
5335 // clean up main element
5336 this.element
5337 .removeClass( "ui-accordion ui-widget ui-helper-reset" )
5338 .removeAttr( "role" );
5339
5340 // clean up headers
5341 this.headers
5342 .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" )
5343 .removeAttr( "role" )
5344 .removeAttr( "aria-selected" )
5345 .removeAttr( "aria-controls" )
5346 .removeAttr( "tabIndex" )
5347 .each(function() {
5348 if ( /^ui-accordion/.test( this.id ) ) {
5349 this.removeAttribute( "id" );
5350 }
5351 });
5352 this._destroyIcons();
5353
5354 // clean up content panels
5355 contents = this.headers.next()
5356 .css( "display", "" )
5357 .removeAttr( "role" )
5358 .removeAttr( "aria-expanded" )
5359 .removeAttr( "aria-hidden" )
5360 .removeAttr( "aria-labelledby" )
5361 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" )
5362 .each(function() {
5363 if ( /^ui-accordion/.test( this.id ) ) {
5364 this.removeAttribute( "id" );
5365 }
5366 });
5367 if ( this.options.heightStyle !== "content" ) {
5368 contents.css( "height", "" );
5369 }
5370 },
5371
5372 _setOption: function( key, value ) {
5373 if ( key === "active" ) {
5374 // _activate() will handle invalid values and update this.options
5375 this._activate( value );
5376 return;
5377 }
5378
5379 if ( key === "event" ) {
5380 if ( this.options.event ) {
5381 this._off( this.headers, this.options.event );
5382 }
5383 this._setupEvents( value );
5384 }
5385
5386 this._super( key, value );
5387
5388 // setting collapsible: false while collapsed; open first panel
5389 if ( key === "collapsible" && !value && this.options.active === false ) {
5390 this._activate( 0 );
5391 }
5392
5393 if ( key === "icons" ) {
5394 this._destroyIcons();
5395 if ( value ) {
5396 this._createIcons();
5397 }
5398 }
5399
5400 // #5332 - opacity doesn't cascade to positioned elements in IE
5401 // so we need to add the disabled class to the headers and panels
5402 if ( key === "disabled" ) {
5403 this.headers.add( this.headers.next() )
5404 .toggleClass( "ui-state-disabled", !!value );
5405 }
5406 },
5407
5408 _keydown: function( event ) {
5409 /*jshint maxcomplexity:15*/
5410 if ( event.altKey || event.ctrlKey ) {
5411 return;
5412 }
5413
5414 var keyCode = $.ui.keyCode,
5415 length = this.headers.length,
5416 currentIndex = this.headers.index( event.target ),
5417 toFocus = false;
5418
5419 switch ( event.keyCode ) {
5420 case keyCode.RIGHT:
5421 case keyCode.DOWN:
5422 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
5423 break;
5424 case keyCode.LEFT:
5425 case keyCode.UP:
5426 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
5427 break;
5428 case keyCode.SPACE:
5429 case keyCode.ENTER:
5430 this._eventHandler( event );
5431 break;
5432 case keyCode.HOME:
5433 toFocus = this.headers[ 0 ];
5434 break;
5435 case keyCode.END:
5436 toFocus = this.headers[ length - 1 ];
5437 break;
5438 }
5439
5440 if ( toFocus ) {
5441 $( event.target ).attr( "tabIndex", -1 );
5442 $( toFocus ).attr( "tabIndex", 0 );
5443 toFocus.focus();
5444 event.preventDefault();
5445 }
5446 },
5447
5448 _panelKeyDown : function( event ) {
5449 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
5450 $( event.currentTarget ).prev().focus();
5451 }
5452 },
5453
5454 refresh: function() {
5455 var options = this.options;
5456 this._processPanels();
5457
5458 // was collapsed or no panel
5459 if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {
5460 options.active = false;
5461 this.active = $();
5462 // active false only when collapsible is true
5463 } else if ( options.active === false ) {
5464 this._activate( 0 );
5465 // was active, but active panel is gone
5466 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
5467 // all remaining panel are disabled
5468 if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {
5469 options.active = false;
5470 this.active = $();
5471 // activate previous panel
5472 } else {
5473 this._activate( Math.max( 0, options.active - 1 ) );
5474 }
5475 // was active, active panel still exists
5476 } else {
5477 // make sure active index is correct
5478 options.active = this.headers.index( this.active );
5479 }
5480
5481 this._destroyIcons();
5482
5483 this._refresh();
5484 },
5485
5486 _processPanels: function() {
5487 this.headers = this.element.find( this.options.header )
5488 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" );
5489
5490 this.headers.next()
5491 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
5492 .filter(":not(.ui-accordion-content-active)")
5493 .hide();
5494 },
5495
5496 _refresh: function() {
5497 var maxHeight,
5498 options = this.options,
5499 heightStyle = options.heightStyle,
5500 parent = this.element.parent(),
5501 accordionId = this.accordionId = "ui-accordion-" +
5502 (this.element.attr( "id" ) || ++uid);
5503
5504 this.active = this._findActive( options.active )
5505 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" )
5506 .removeClass( "ui-corner-all" );
5507 this.active.next()
5508 .addClass( "ui-accordion-content-active" )
5509 .show();
5510
5511 this.headers
5512 .attr( "role", "tab" )
5513 .each(function( i ) {
5514 var header = $( this ),
5515 headerId = header.attr( "id" ),
5516 panel = header.next(),
5517 panelId = panel.attr( "id" );
5518 if ( !headerId ) {
5519 headerId = accordionId + "-header-" + i;
5520 header.attr( "id", headerId );
5521 }
5522 if ( !panelId ) {
5523 panelId = accordionId + "-panel-" + i;
5524 panel.attr( "id", panelId );
5525 }
5526 header.attr( "aria-controls", panelId );
5527 panel.attr( "aria-labelledby", headerId );
5528 })
5529 .next()
5530 .attr( "role", "tabpanel" );
5531
5532 this.headers
5533 .not( this.active )
5534 .attr({
5535 "aria-selected": "false",
5536 tabIndex: -1
5537 })
5538 .next()
5539 .attr({
5540 "aria-expanded": "false",
5541 "aria-hidden": "true"
5542 })
5543 .hide();
5544
5545 // make sure at least one header is in the tab order
5546 if ( !this.active.length ) {
5547 this.headers.eq( 0 ).attr( "tabIndex", 0 );
5548 } else {
5549 this.active.attr({
5550 "aria-selected": "true",
5551 tabIndex: 0
5552 })
5553 .next()
5554 .attr({
5555 "aria-expanded": "true",
5556 "aria-hidden": "false"
5557 });
5558 }
5559
5560 this._createIcons();
5561
5562 this._setupEvents( options.event );
5563
5564 if ( heightStyle === "fill" ) {
5565 maxHeight = parent.height();
5566 this.element.siblings( ":visible" ).each(function() {
5567 var elem = $( this ),
5568 position = elem.css( "position" );
5569
5570 if ( position === "absolute" || position === "fixed" ) {
5571 return;
5572 }
5573 maxHeight -= elem.outerHeight( true );
5574 });
5575
5576 this.headers.each(function() {
5577 maxHeight -= $( this ).outerHeight( true );
5578 });
5579
5580 this.headers.next()
5581 .each(function() {
5582 $( this ).height( Math.max( 0, maxHeight -
5583 $( this ).innerHeight() + $( this ).height() ) );
5584 })
5585 .css( "overflow", "auto" );
5586 } else if ( heightStyle === "auto" ) {
5587 maxHeight = 0;
5588 this.headers.next()
5589 .each(function() {
5590 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
5591 })
5592 .height( maxHeight );
5593 }
5594 },
5595
5596 _activate: function( index ) {
5597 var active = this._findActive( index )[ 0 ];
5598
5599 // trying to activate the already active panel
5600 if ( active === this.active[ 0 ] ) {
5601 return;
5602 }
5603
5604 // trying to collapse, simulate a click on the currently active header
5605 active = active || this.active[ 0 ];
5606
5607 this._eventHandler({
5608 target: active,
5609 currentTarget: active,
5610 preventDefault: $.noop
5611 });
5612 },
5613
5614 _findActive: function( selector ) {
5615 return typeof selector === "number" ? this.headers.eq( selector ) : $();
5616 },
5617
5618 _setupEvents: function( event ) {
5619 var events = {
5620 keydown: "_keydown"
5621 };
5622 if ( event ) {
5623 $.each( event.split(" "), function( index, eventName ) {
5624 events[ eventName ] = "_eventHandler";
5625 });
5626 }
5627
5628 this._off( this.headers.add( this.headers.next() ) );
5629 this._on( this.headers, events );
5630 this._on( this.headers.next(), { keydown: "_panelKeyDown" });
5631 this._hoverable( this.headers );
5632 this._focusable( this.headers );
5633 },
5634
5635 _eventHandler: function( event ) {
5636 var options = this.options,
5637 active = this.active,
5638 clicked = $( event.currentTarget ),
5639 clickedIsActive = clicked[ 0 ] === active[ 0 ],
5640 collapsing = clickedIsActive && options.collapsible,
5641 toShow = collapsing ? $() : clicked.next(),
5642 toHide = active.next(),
5643 eventData = {
5644 oldHeader: active,
5645 oldPanel: toHide,
5646 newHeader: collapsing ? $() : clicked,
5647 newPanel: toShow
5648 };
5649
5650 event.preventDefault();
5651
5652 if (
5653 // click on active header, but not collapsible
5654 ( clickedIsActive && !options.collapsible ) ||
5655 // allow canceling activation
5656 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
5657 return;
5658 }
5659
5660 options.active = collapsing ? false : this.headers.index( clicked );
5661
5662 // when the call to ._toggle() comes after the class changes
5663 // it causes a very odd bug in IE 8 (see #6720)
5664 this.active = clickedIsActive ? $() : clicked;
5665 this._toggle( eventData );
5666
5667 // switch classes
5668 // corner classes on the previously active header stay after the animation
5669 active.removeClass( "ui-accordion-header-active ui-state-active" );
5670 if ( options.icons ) {
5671 active.children( ".ui-accordion-header-icon" )
5672 .removeClass( options.icons.activeHeader )
5673 .addClass( options.icons.header );
5674 }
5675
5676 if ( !clickedIsActive ) {
5677 clicked
5678 .removeClass( "ui-corner-all" )
5679 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
5680 if ( options.icons ) {
5681 clicked.children( ".ui-accordion-header-icon" )
5682 .removeClass( options.icons.header )
5683 .addClass( options.icons.activeHeader );
5684 }
5685
5686 clicked
5687 .next()
5688 .addClass( "ui-accordion-content-active" );
5689 }
5690 },
5691
5692 _toggle: function( data ) {
5693 var toShow = data.newPanel,
5694 toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
5695
5696 // handle activating a panel during the animation for another activation
5697 this.prevShow.add( this.prevHide ).stop( true, true );
5698 this.prevShow = toShow;
5699 this.prevHide = toHide;
5700
5701 if ( this.options.animate ) {
5702 this._animate( toShow, toHide, data );
5703 } else {
5704 toHide.hide();
5705 toShow.show();
5706 this._toggleComplete( data );
5707 }
5708
5709 toHide.attr({
5710 "aria-expanded": "false",
5711 "aria-hidden": "true"
5712 });
5713 toHide.prev().attr( "aria-selected", "false" );
5714 // if we're switching panels, remove the old header from the tab order
5715 // if we're opening from collapsed state, remove the previous header from the tab order
5716 // if we're collapsing, then keep the collapsing header in the tab order
5717 if ( toShow.length && toHide.length ) {
5718 toHide.prev().attr( "tabIndex", -1 );
5719 } else if ( toShow.length ) {
5720 this.headers.filter(function() {
5721 return $( this ).attr( "tabIndex" ) === 0;
5722 })
5723 .attr( "tabIndex", -1 );
5724 }
5725
5726 toShow
5727 .attr({
5728 "aria-expanded": "true",
5729 "aria-hidden": "false"
5730 })
5731 .prev()
5732 .attr({
5733 "aria-selected": "true",
5734 tabIndex: 0
5735 });
5736 },
5737
5738 _animate: function( toShow, toHide, data ) {
5739 var total, easing, duration,
5740 that = this,
5741 adjust = 0,
5742 down = toShow.length &&
5743 ( !toHide.length || ( toShow.index() < toHide.index() ) ),
5744 animate = this.options.animate || {},
5745 options = down && animate.down || animate,
5746 complete = function() {
5747 that._toggleComplete( data );
5748 };
5749
5750 if ( typeof options === "number" ) {
5751 duration = options;
5752 }
5753 if ( typeof options === "string" ) {
5754 easing = options;
5755 }
5756 // fall back from options to animation in case of partial down settings
5757 easing = easing || options.easing || animate.easing;
5758 duration = duration || options.duration || animate.duration;
5759
5760 if ( !toHide.length ) {
5761 return toShow.animate( showProps, duration, easing, complete );
5762 }
5763 if ( !toShow.length ) {
5764 return toHide.animate( hideProps, duration, easing, complete );
5765 }
5766
5767 total = toShow.show().outerHeight();
5768 toHide.animate( hideProps, {
5769 duration: duration,
5770 easing: easing,
5771 step: function( now, fx ) {
5772 fx.now = Math.round( now );
5773 }
5774 });
5775 toShow
5776 .hide()
5777 .animate( showProps, {
5778 duration: duration,
5779 easing: easing,
5780 complete: complete,
5781 step: function( now, fx ) {
5782 fx.now = Math.round( now );
5783 if ( fx.prop !== "height" ) {
5784 adjust += fx.now;
5785 } else if ( that.options.heightStyle !== "content" ) {
5786 fx.now = Math.round( total - toHide.outerHeight() - adjust );
5787 adjust = 0;
5788 }
5789 }
5790 });
5791 },
5792
5793 _toggleComplete: function( data ) {
5794 var toHide = data.oldPanel;
5795
5796 toHide
5797 .removeClass( "ui-accordion-content-active" )
5798 .prev()
5799 .removeClass( "ui-corner-top" )
5800 .addClass( "ui-corner-all" );
5801
5802 // Work around for rendering bug in IE (#5421)
5803 if ( toHide.length ) {
5804 toHide.parent()[0].className = toHide.parent()[0].className;
5805 }
5806
5807 this._trigger( "activate", null, data );
5808 }
5809 });
5810
5811 })( jQuery );
5812 (function( $, undefined ) {
5813
5814 // used to prevent race conditions with remote data sources
5815 var requestIndex = 0;
5816
5817 $.widget( "ui.autocomplete", {
5818 version: "1.10.3",
5819 defaultElement: "<input>",
5820 options: {
5821 appendTo: null,
5822 autoFocus: false,
5823 delay: 300,
5824 minLength: 1,
5825 position: {
5826 my: "left top",
5827 at: "left bottom",
5828 collision: "none"
5829 },
5830 source: null,
5831
5832 // callbacks
5833 change: null,
5834 close: null,
5835 focus: null,
5836 open: null,
5837 response: null,
5838 search: null,
5839 select: null
5840 },
5841
5842 pending: 0,
5843
5844 _create: function() {
5845 // Some browsers only repeat keydown events, not keypress events,
5846 // so we use the suppressKeyPress flag to determine if we've already
5847 // handled the keydown event. #7269
5848 // Unfortunately the code for & in keypress is the same as the up arrow,
5849 // so we use the suppressKeyPressRepeat flag to avoid handling keypress
5850 // events when we know the keydown event was used to modify the
5851 // search term. #7799
5852 var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
5853 nodeName = this.element[0].nodeName.toLowerCase(),
5854 isTextarea = nodeName === "textarea",
5855 isInput = nodeName === "input";
5856
5857 this.isMultiLine =
5858 // Textareas are always multi-line
5859 isTextarea ? true :
5860 // Inputs are always single-line, even if inside a contentEditable element
5861 // IE also treats inputs as contentEditable
5862 isInput ? false :
5863 // All other element types are determined by whether or not they're contentEditable
5864 this.element.prop( "isContentEditable" );
5865
5866 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
5867 this.isNewMenu = true;
5868
5869 this.element
5870 .addClass( "ui-autocomplete-input" )
5871 .attr( "autocomplete", "off" );
5872
5873 this._on( this.element, {
5874 keydown: function( event ) {
5875 /*jshint maxcomplexity:15*/
5876 if ( this.element.prop( "readOnly" ) ) {
5877 suppressKeyPress = true;
5878 suppressInput = true;
5879 suppressKeyPressRepeat = true;
5880 return;
5881 }
5882
5883 suppressKeyPress = false;
5884 suppressInput = false;
5885 suppressKeyPressRepeat = false;
5886 var keyCode = $.ui.keyCode;
5887 switch( event.keyCode ) {
5888 case keyCode.PAGE_UP:
5889 suppressKeyPress = true;
5890 this._move( "previousPage", event );
5891 break;
5892 case keyCode.PAGE_DOWN:
5893 suppressKeyPress = true;
5894 this._move( "nextPage", event );
5895 break;
5896 case keyCode.UP:
5897 suppressKeyPress = true;
5898 this._keyEvent( "previous", event );
5899 break;
5900 case keyCode.DOWN:
5901 suppressKeyPress = true;
5902 this._keyEvent( "next", event );
5903 break;
5904 case keyCode.ENTER:
5905 case keyCode.NUMPAD_ENTER:
5906 // when menu is open and has focus
5907 if ( this.menu.active ) {
5908 // #6055 - Opera still allows the keypress to occur
5909 // which causes forms to submit
5910 suppressKeyPress = true;
5911 event.preventDefault();
5912 this.menu.select( event );
5913 }
5914 break;
5915 case keyCode.TAB:
5916 if ( this.menu.active ) {
5917 this.menu.select( event );
5918 }
5919 break;
5920 case keyCode.ESCAPE:
5921 if ( this.menu.element.is( ":visible" ) ) {
5922 this._value( this.term );
5923 this.close( event );
5924 // Different browsers have different default behavior for escape
5925 // Single press can mean undo or clear
5926 // Double press in IE means clear the whole form
5927 event.preventDefault();
5928 }
5929 break;
5930 default:
5931 suppressKeyPressRepeat = true;
5932 // search timeout should be triggered before the input value is changed
5933 this._searchTimeout( event );
5934 break;
5935 }
5936 },
5937 keypress: function( event ) {
5938 if ( suppressKeyPress ) {
5939 suppressKeyPress = false;
5940 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
5941 event.preventDefault();
5942 }
5943 return;
5944 }
5945 if ( suppressKeyPressRepeat ) {
5946 return;
5947 }
5948
5949 // replicate some key handlers to allow them to repeat in Firefox and Opera
5950 var keyCode = $.ui.keyCode;
5951 switch( event.keyCode ) {
5952 case keyCode.PAGE_UP:
5953 this._move( "previousPage", event );
5954 break;
5955 case keyCode.PAGE_DOWN:
5956 this._move( "nextPage", event );
5957 break;
5958 case keyCode.UP:
5959 this._keyEvent( "previous", event );
5960 break;
5961 case keyCode.DOWN:
5962 this._keyEvent( "next", event );
5963 break;
5964 }
5965 },
5966 input: function( event ) {
5967 if ( suppressInput ) {
5968 suppressInput = false;
5969 event.preventDefault();
5970 return;
5971 }
5972 this._searchTimeout( event );
5973 },
5974 focus: function() {
5975 this.selectedItem = null;
5976 this.previous = this._value();
5977 },
5978 blur: function( event ) {
5979 if ( this.cancelBlur ) {
5980 delete this.cancelBlur;
5981 return;
5982 }
5983
5984 clearTimeout( this.searching );
5985 this.close( event );
5986 this._change( event );
5987 }
5988 });
5989
5990 this._initSource();
5991 this.menu = $( "<ul>" )
5992 .addClass( "ui-autocomplete ui-front" )
5993 .appendTo( this._appendTo() )
5994 .menu({
5995 // disable ARIA support, the live region takes care of that
5996 role: null
5997 })
5998 .hide()
5999 .data( "ui-menu" );
6000
6001 this._on( this.menu.element, {
6002 mousedown: function( event ) {
6003 // prevent moving focus out of the text field
6004 event.preventDefault();
6005
6006 // IE doesn't prevent moving focus even with event.preventDefault()
6007 // so we set a flag to know when we should ignore the blur event
6008 this.cancelBlur = true;
6009 this._delay(function() {
6010 delete this.cancelBlur;
6011 });
6012
6013 // clicking on the scrollbar causes focus to shift to the body
6014 // but we can't detect a mouseup or a click immediately afterward
6015 // so we have to track the next mousedown and close the menu if
6016 // the user clicks somewhere outside of the autocomplete
6017 var menuElement = this.menu.element[ 0 ];
6018 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
6019 this._delay(function() {
6020 var that = this;
6021 this.document.one( "mousedown", function( event ) {
6022 if ( event.target !== that.element[ 0 ] &&
6023 event.target !== menuElement &&
6024 !$.contains( menuElement, event.target ) ) {
6025 that.close();
6026 }
6027 });
6028 });
6029 }
6030 },
6031 menufocus: function( event, ui ) {
6032 // support: Firefox
6033 // Prevent accidental activation of menu items in Firefox (#7024 #9118)
6034 if ( this.isNewMenu ) {
6035 this.isNewMenu = false;
6036 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
6037 this.menu.blur();
6038
6039 this.document.one( "mousemove", function() {
6040 $( event.target ).trigger( event.originalEvent );
6041 });
6042
6043 return;
6044 }
6045 }
6046
6047 var item = ui.item.data( "ui-autocomplete-item" );
6048 if ( false !== this._trigger( "focus", event, { item: item } ) ) {
6049 // use value to match what will end up in the input, if it was a key event
6050 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
6051 this._value( item.value );
6052 }
6053 } else {
6054 // Normally the input is populated with the item's value as the
6055 // menu is navigated, causing screen readers to notice a change and
6056 // announce the item. Since the focus event was canceled, this doesn't
6057 // happen, so we update the live region so that screen readers can
6058 // still notice the change and announce it.
6059 this.liveRegion.text( item.value );
6060 }
6061 },
6062 menuselect: function( event, ui ) {
6063 var item = ui.item.data( "ui-autocomplete-item" ),
6064 previous = this.previous;
6065
6066 // only trigger when focus was lost (click on menu)
6067 if ( this.element[0] !== this.document[0].activeElement ) {
6068 this.element.focus();
6069 this.previous = previous;
6070 // #6109 - IE triggers two focus events and the second
6071 // is asynchronous, so we need to reset the previous
6072 // term synchronously and asynchronously :-(
6073 this._delay(function() {
6074 this.previous = previous;
6075 this.selectedItem = item;
6076 });
6077 }
6078
6079 if ( false !== this._trigger( "select", event, { item: item } ) ) {
6080 this._value( item.value );
6081 }
6082 // reset the term after the select event
6083 // this allows custom select handling to work properly
6084 this.term = this._value();
6085
6086 this.close( event );
6087 this.selectedItem = item;
6088 }
6089 });
6090
6091 this.liveRegion = $( "<span>", {
6092 role: "status",
6093 "aria-live": "polite"
6094 })
6095 .addClass( "ui-helper-hidden-accessible" )
6096 .insertBefore( this.element );
6097
6098 // turning off autocomplete prevents the browser from remembering the
6099 // value when navigating through history, so we re-enable autocomplete
6100 // if the page is unloaded before the widget is destroyed. #7790
6101 this._on( this.window, {
6102 beforeunload: function() {
6103 this.element.removeAttr( "autocomplete" );
6104 }
6105 });
6106 },
6107
6108 _destroy: function() {
6109 clearTimeout( this.searching );
6110 this.element
6111 .removeClass( "ui-autocomplete-input" )
6112 .removeAttr( "autocomplete" );
6113 this.menu.element.remove();
6114 this.liveRegion.remove();
6115 },
6116
6117 _setOption: function( key, value ) {
6118 this._super( key, value );
6119 if ( key === "source" ) {
6120 this._initSource();
6121 }
6122 if ( key === "appendTo" ) {
6123 this.menu.element.appendTo( this._appendTo() );
6124 }
6125 if ( key === "disabled" && value && this.xhr ) {
6126 this.xhr.abort();
6127 }
6128 },
6129
6130 _appendTo: function() {
6131 var element = this.options.appendTo;
6132
6133 if ( element ) {
6134 element = element.jquery || element.nodeType ?
6135 $( element ) :
6136 this.document.find( element ).eq( 0 );
6137 }
6138
6139 if ( !element ) {
6140 element = this.element.closest( ".ui-front" );
6141 }
6142
6143 if ( !element.length ) {
6144 element = this.document[0].body;
6145 }
6146
6147 return element;
6148 },
6149
6150 _initSource: function() {
6151 var array, url,
6152 that = this;
6153 if ( $.isArray(this.options.source) ) {
6154 array = this.options.source;
6155 this.source = function( request, response ) {
6156 response( $.ui.autocomplete.filter( array, request.term ) );
6157 };
6158 } else if ( typeof this.options.source === "string" ) {
6159 url = this.options.source;
6160 this.source = function( request, response ) {
6161 if ( that.xhr ) {
6162 that.xhr.abort();
6163 }
6164 that.xhr = $.ajax({
6165 url: url,
6166 data: request,
6167 dataType: "json",
6168 success: function( data ) {
6169 response( data );
6170 },
6171 error: function() {
6172 response( [] );
6173 }
6174 });
6175 };
6176 } else {
6177 this.source = this.options.source;
6178 }
6179 },
6180
6181 _searchTimeout: function( event ) {
6182 clearTimeout( this.searching );
6183 this.searching = this._delay(function() {
6184 // only search if the value has changed
6185 if ( this.term !== this._value() ) {
6186 this.selectedItem = null;
6187 this.search( null, event );
6188 }
6189 }, this.options.delay );
6190 },
6191
6192 search: function( value, event ) {
6193 value = value != null ? value : this._value();
6194
6195 // always save the actual value, not the one passed as an argument
6196 this.term = this._value();
6197
6198 if ( value.length < this.options.minLength ) {
6199 return this.close( event );
6200 }
6201
6202 if ( this._trigger( "search", event ) === false ) {
6203 return;
6204 }
6205
6206 return this._search( value );
6207 },
6208
6209 _search: function( value ) {
6210 this.pending++;
6211 this.element.addClass( "ui-autocomplete-loading" );
6212 this.cancelSearch = false;
6213
6214 this.source( { term: value }, this._response() );
6215 },
6216
6217 _response: function() {
6218 var that = this,
6219 index = ++requestIndex;
6220
6221 return function( content ) {
6222 if ( index === requestIndex ) {
6223 that.__response( content );
6224 }
6225
6226 that.pending--;
6227 if ( !that.pending ) {
6228 that.element.removeClass( "ui-autocomplete-loading" );
6229 }
6230 };
6231 },
6232
6233 __response: function( content ) {
6234 if ( content ) {
6235 content = this._normalize( content );
6236 }
6237 this._trigger( "response", null, { content: content } );
6238 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
6239 this._suggest( content );
6240 this._trigger( "open" );
6241 } else {
6242 // use ._close() instead of .close() so we don't cancel future searches
6243 this._close();
6244 }
6245 },
6246
6247 close: function( event ) {
6248 this.cancelSearch = true;
6249 this._close( event );
6250 },
6251
6252 _close: function( event ) {
6253 if ( this.menu.element.is( ":visible" ) ) {
6254 this.menu.element.hide();
6255 this.menu.blur();
6256 this.isNewMenu = true;
6257 this._trigger( "close", event );
6258 }
6259 },
6260
6261 _change: function( event ) {
6262 if ( this.previous !== this._value() ) {
6263 this._trigger( "change", event, { item: this.selectedItem } );
6264 }
6265 },
6266
6267 _normalize: function( items ) {
6268 // assume all items have the right format when the first item is complete
6269 if ( items.length && items[0].label && items[0].value ) {
6270 return items;
6271 }
6272 return $.map( items, function( item ) {
6273 if ( typeof item === "string" ) {
6274 return {
6275 label: item,
6276 value: item
6277 };
6278 }
6279 return $.extend({
6280 label: item.label || item.value,
6281 value: item.value || item.label
6282 }, item );
6283 });
6284 },
6285
6286 _suggest: function( items ) {
6287 var ul = this.menu.element.empty();
6288 this._renderMenu( ul, items );
6289 this.isNewMenu = true;
6290 this.menu.refresh();
6291
6292 // size and position menu
6293 ul.show();
6294 this._resizeMenu();
6295 ul.position( $.extend({
6296 of: this.element
6297 }, this.options.position ));
6298
6299 if ( this.options.autoFocus ) {
6300 this.menu.next();
6301 }
6302 },
6303
6304 _resizeMenu: function() {
6305 var ul = this.menu.element;
6306 ul.outerWidth( Math.max(
6307 // Firefox wraps long text (possibly a rounding bug)
6308 // so we add 1px to avoid the wrapping (#7513)
6309 ul.width( "" ).outerWidth() + 1,
6310 this.element.outerWidth()
6311 ) );
6312 },
6313
6314 _renderMenu: function( ul, items ) {
6315 var that = this;
6316 $.each( items, function( index, item ) {
6317 that._renderItemData( ul, item );
6318 });
6319 },
6320
6321 _renderItemData: function( ul, item ) {
6322 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
6323 },
6324
6325 _renderItem: function( ul, item ) {
6326 return $( "<li>" )
6327 .append( $( "<a>" ).text( item.label ) )
6328 .appendTo( ul );
6329 },
6330
6331 _move: function( direction, event ) {
6332 if ( !this.menu.element.is( ":visible" ) ) {
6333 this.search( null, event );
6334 return;
6335 }
6336 if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
6337 this.menu.isLastItem() && /^next/.test( direction ) ) {
6338 this._value( this.term );
6339 this.menu.blur();
6340 return;
6341 }
6342 this.menu[ direction ]( event );
6343 },
6344
6345 widget: function() {
6346 return this.menu.element;
6347 },
6348
6349 _value: function() {
6350 return this.valueMethod.apply( this.element, arguments );
6351 },
6352
6353 _keyEvent: function( keyEvent, event ) {
6354 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6355 this._move( keyEvent, event );
6356
6357 // prevents moving cursor to beginning/end of the text field in some browsers
6358 event.preventDefault();
6359 }
6360 }
6361 });
6362
6363 $.extend( $.ui.autocomplete, {
6364 escapeRegex: function( value ) {
6365 return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
6366 },
6367 filter: function(array, term) {
6368 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
6369 return $.grep( array, function(value) {
6370 return matcher.test( value.label || value.value || value );
6371 });
6372 }
6373 });
6374
6375
6376 // live region extension, adding a `messages` option
6377 // NOTE: This is an experimental API. We are still investigating
6378 // a full solution for string manipulation and internationalization.
6379 $.widget( "ui.autocomplete", $.ui.autocomplete, {
6380 options: {
6381 messages: {
6382 noResults: "No search results.",
6383 results: function( amount ) {
6384 return amount + ( amount > 1 ? " results are" : " result is" ) +
6385 " available, use up and down arrow keys to navigate.";
6386 }
6387 }
6388 },
6389
6390 __response: function( content ) {
6391 var message;
6392 this._superApply( arguments );
6393 if ( this.options.disabled || this.cancelSearch ) {
6394 return;
6395 }
6396 if ( content && content.length ) {
6397 message = this.options.messages.results( content.length );
6398 } else {
6399 message = this.options.messages.noResults;
6400 }
6401 this.liveRegion.text( message );
6402 }
6403 });
6404
6405 }( jQuery ));
6406 (function( $, undefined ) {
6407
6408 var lastActive, startXPos, startYPos, clickDragged,
6409 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
6410 stateClasses = "ui-state-hover ui-state-active ",
6411 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",
6412 formResetHandler = function() {
6413 var form = $( this );
6414 setTimeout(function() {
6415 form.find( ":ui-button" ).button( "refresh" );
6416 }, 1 );
6417 },
6418 radioGroup = function( radio ) {
6419 var name = radio.name,
6420 form = radio.form,
6421 radios = $( [] );
6422 if ( name ) {
6423 name = name.replace( /'/g, "\\'" );
6424 if ( form ) {
6425 radios = $( form ).find( "[name='" + name + "']" );
6426 } else {
6427 radios = $( "[name='" + name + "']", radio.ownerDocument )
6428 .filter(function() {
6429 return !this.form;
6430 });
6431 }
6432 }
6433 return radios;
6434 };
6435
6436 $.widget( "ui.button", {
6437 version: "1.10.3",
6438 defaultElement: "<button>",
6439 options: {
6440 disabled: null,
6441 text: true,
6442 label: null,
6443 icons: {
6444 primary: null,
6445 secondary: null
6446 }
6447 },
6448 _create: function() {
6449 this.element.closest( "form" )
6450 .unbind( "reset" + this.eventNamespace )
6451 .bind( "reset" + this.eventNamespace, formResetHandler );
6452
6453 if ( typeof this.options.disabled !== "boolean" ) {
6454 this.options.disabled = !!this.element.prop( "disabled" );
6455 } else {
6456 this.element.prop( "disabled", this.options.disabled );
6457 }
6458
6459 this._determineButtonType();
6460 this.hasTitle = !!this.buttonElement.attr( "title" );
6461
6462 var that = this,
6463 options = this.options,
6464 toggleButton = this.type === "checkbox" || this.type === "radio",
6465 activeClass = !toggleButton ? "ui-state-active" : "",
6466 focusClass = "ui-state-focus";
6467
6468 if ( options.label === null ) {
6469 options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
6470 }
6471
6472 this._hoverable( this.buttonElement );
6473
6474 this.buttonElement
6475 .addClass( baseClasses )
6476 .attr( "role", "button" )
6477 .bind( "mouseenter" + this.eventNamespace, function() {
6478 if ( options.disabled ) {
6479 return;
6480 }
6481 if ( this === lastActive ) {
6482 $( this ).addClass( "ui-state-active" );
6483 }
6484 })
6485 .bind( "mouseleave" + this.eventNamespace, function() {
6486 if ( options.disabled ) {
6487 return;
6488 }
6489 $( this ).removeClass( activeClass );
6490 })
6491 .bind( "click" + this.eventNamespace, function( event ) {
6492 if ( options.disabled ) {
6493 event.preventDefault();
6494 event.stopImmediatePropagation();
6495 }
6496 });
6497
6498 this.element
6499 .bind( "focus" + this.eventNamespace, function() {
6500 // no need to check disabled, focus won't be triggered anyway
6501 that.buttonElement.addClass( focusClass );
6502 })
6503 .bind( "blur" + this.eventNamespace, function() {
6504 that.buttonElement.removeClass( focusClass );
6505 });
6506
6507 if ( toggleButton ) {
6508 this.element.bind( "change" + this.eventNamespace, function() {
6509 if ( clickDragged ) {
6510 return;
6511 }
6512 that.refresh();
6513 });
6514 // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
6515 // prevents issue where button state changes but checkbox/radio checked state
6516 // does not in Firefox (see ticket #6970)
6517 this.buttonElement
6518 .bind( "mousedown" + this.eventNamespace, function( event ) {
6519 if ( options.disabled ) {
6520 return;
6521 }
6522 clickDragged = false;
6523 startXPos = event.pageX;
6524 startYPos = event.pageY;
6525 })
6526 .bind( "mouseup" + this.eventNamespace, function( event ) {
6527 if ( options.disabled ) {
6528 return;
6529 }
6530 if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
6531 clickDragged = true;
6532 }
6533 });
6534 }
6535
6536 if ( this.type === "checkbox" ) {
6537 this.buttonElement.bind( "click" + this.eventNamespace, function() {
6538 if ( options.disabled || clickDragged ) {
6539 return false;
6540 }
6541 });
6542 } else if ( this.type === "radio" ) {
6543 this.buttonElement.bind( "click" + this.eventNamespace, function() {
6544 if ( options.disabled || clickDragged ) {
6545 return false;
6546 }
6547 $( this ).addClass( "ui-state-active" );
6548 that.buttonElement.attr( "aria-pressed", "true" );
6549
6550 var radio = that.element[ 0 ];
6551 radioGroup( radio )
6552 .not( radio )
6553 .map(function() {
6554 return $( this ).button( "widget" )[ 0 ];
6555 })
6556 .removeClass( "ui-state-active" )
6557 .attr( "aria-pressed", "false" );
6558 });
6559 } else {
6560 this.buttonElement
6561 .bind( "mousedown" + this.eventNamespace, function() {
6562 if ( options.disabled ) {
6563 return false;
6564 }
6565 $( this ).addClass( "ui-state-active" );
6566 lastActive = this;
6567 that.document.one( "mouseup", function() {
6568 lastActive = null;
6569 });
6570 })
6571 .bind( "mouseup" + this.eventNamespace, function() {
6572 if ( options.disabled ) {
6573 return false;
6574 }
6575 $( this ).removeClass( "ui-state-active" );
6576 })
6577 .bind( "keydown" + this.eventNamespace, function(event) {
6578 if ( options.disabled ) {
6579 return false;
6580 }
6581 if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
6582 $( this ).addClass( "ui-state-active" );
6583 }
6584 })
6585 // see #8559, we bind to blur here in case the button element loses
6586 // focus between keydown and keyup, it would be left in an "active" state
6587 .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
6588 $( this ).removeClass( "ui-state-active" );
6589 });
6590
6591 if ( this.buttonElement.is("a") ) {
6592 this.buttonElement.keyup(function(event) {
6593 if ( event.keyCode === $.ui.keyCode.SPACE ) {
6594 // TODO pass through original event correctly (just as 2nd argument doesn't work)
6595 $( this ).click();
6596 }
6597 });
6598 }
6599 }
6600
6601 // TODO: pull out $.Widget's handling for the disabled option into
6602 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
6603 // be overridden by individual plugins
6604 this._setOption( "disabled", options.disabled );
6605 this._resetButton();
6606 },
6607
6608 _determineButtonType: function() {
6609 var ancestor, labelSelector, checked;
6610
6611 if ( this.element.is("[type=checkbox]") ) {
6612 this.type = "checkbox";
6613 } else if ( this.element.is("[type=radio]") ) {
6614 this.type = "radio";
6615 } else if ( this.element.is("input") ) {
6616 this.type = "input";
6617 } else {
6618 this.type = "button";
6619 }
6620
6621 if ( this.type === "checkbox" || this.type === "radio" ) {
6622 // we don't search against the document in case the element
6623 // is disconnected from the DOM
6624 ancestor = this.element.parents().last();
6625 labelSelector = "label[for='" + this.element.attr("id") + "']";
6626 this.buttonElement = ancestor.find( labelSelector );
6627 if ( !this.buttonElement.length ) {
6628 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
6629 this.buttonElement = ancestor.filter( labelSelector );
6630 if ( !this.buttonElement.length ) {
6631 this.buttonElement = ancestor.find( labelSelector );
6632 }
6633 }
6634 this.element.addClass( "ui-helper-hidden-accessible" );
6635
6636 checked = this.element.is( ":checked" );
6637 if ( checked ) {
6638 this.buttonElement.addClass( "ui-state-active" );
6639 }
6640 this.buttonElement.prop( "aria-pressed", checked );
6641 } else {
6642 this.buttonElement = this.element;
6643 }
6644 },
6645
6646 widget: function() {
6647 return this.buttonElement;
6648 },
6649
6650 _destroy: function() {
6651 this.element
6652 .removeClass( "ui-helper-hidden-accessible" );
6653 this.buttonElement
6654 .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
6655 .removeAttr( "role" )
6656 .removeAttr( "aria-pressed" )
6657 .html( this.buttonElement.find(".ui-button-text").html() );
6658
6659 if ( !this.hasTitle ) {
6660 this.buttonElement.removeAttr( "title" );
6661 }
6662 },
6663
6664 _setOption: function( key, value ) {
6665 this._super( key, value );
6666 if ( key === "disabled" ) {
6667 if ( value ) {
6668 this.element.prop( "disabled", true );
6669 } else {
6670 this.element.prop( "disabled", false );
6671 }
6672 return;
6673 }
6674 this._resetButton();
6675 },
6676
6677 refresh: function() {
6678 //See #8237 & #8828
6679 var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
6680
6681 if ( isDisabled !== this.options.disabled ) {
6682 this._setOption( "disabled", isDisabled );
6683 }
6684 if ( this.type === "radio" ) {
6685 radioGroup( this.element[0] ).each(function() {
6686 if ( $( this ).is( ":checked" ) ) {
6687 $( this ).button( "widget" )
6688 .addClass( "ui-state-active" )
6689 .attr( "aria-pressed", "true" );
6690 } else {
6691 $( this ).button( "widget" )
6692 .removeClass( "ui-state-active" )
6693 .attr( "aria-pressed", "false" );
6694 }
6695 });
6696 } else if ( this.type === "checkbox" ) {
6697 if ( this.element.is( ":checked" ) ) {
6698 this.buttonElement
6699 .addClass( "ui-state-active" )
6700 .attr( "aria-pressed", "true" );
6701 } else {
6702 this.buttonElement
6703 .removeClass( "ui-state-active" )
6704 .attr( "aria-pressed", "false" );
6705 }
6706 }
6707 },
6708
6709 _resetButton: function() {
6710 if ( this.type === "input" ) {
6711 if ( this.options.label ) {
6712 this.element.val( this.options.label );
6713 }
6714 return;
6715 }
6716 var buttonElement = this.buttonElement.removeClass( typeClasses ),
6717 buttonText = $( "<span></span>", this.document[0] )
6718 .addClass( "ui-button-text" )
6719 .html( this.options.label )
6720 .appendTo( buttonElement.empty() )
6721 .text(),
6722 icons = this.options.icons,
6723 multipleIcons = icons.primary && icons.secondary,
6724 buttonClasses = [];
6725
6726 if ( icons.primary || icons.secondary ) {
6727 if ( this.options.text ) {
6728 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
6729 }
6730
6731 if ( icons.primary ) {
6732 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
6733 }
6734
6735 if ( icons.secondary ) {
6736 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
6737 }
6738
6739 if ( !this.options.text ) {
6740 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
6741
6742 if ( !this.hasTitle ) {
6743 buttonElement.attr( "title", $.trim( buttonText ) );
6744 }
6745 }
6746 } else {
6747 buttonClasses.push( "ui-button-text-only" );
6748 }
6749 buttonElement.addClass( buttonClasses.join( " " ) );
6750 }
6751 });
6752
6753 $.widget( "ui.buttonset", {
6754 version: "1.10.3",
6755 options: {
6756 items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
6757 },
6758
6759 _create: function() {
6760 this.element.addClass( "ui-buttonset" );
6761 },
6762
6763 _init: function() {
6764 this.refresh();
6765 },
6766
6767 _setOption: function( key, value ) {
6768 if ( key === "disabled" ) {
6769 this.buttons.button( "option", key, value );
6770 }
6771
6772 this._super( key, value );
6773 },
6774
6775 refresh: function() {
6776 var rtl = this.element.css( "direction" ) === "rtl";
6777
6778 this.buttons = this.element.find( this.options.items )
6779 .filter( ":ui-button" )
6780 .button( "refresh" )
6781 .end()
6782 .not( ":ui-button" )
6783 .button()
6784 .end()
6785 .map(function() {
6786 return $( this ).button( "widget" )[ 0 ];
6787 })
6788 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
6789 .filter( ":first" )
6790 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
6791 .end()
6792 .filter( ":last" )
6793 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
6794 .end()
6795 .end();
6796 },
6797
6798 _destroy: function() {
6799 this.element.removeClass( "ui-buttonset" );
6800 this.buttons
6801 .map(function() {
6802 return $( this ).button( "widget" )[ 0 ];
6803 })
6804 .removeClass( "ui-corner-left ui-corner-right" )
6805 .end()
6806 .button( "destroy" );
6807 }
6808 });
6809
6810 }( jQuery ) );
6811 (function( $, undefined ) {
6812
6813 $.extend($.ui, { datepicker: { version: "1.10.3" } });
6814
6815 var PROP_NAME = "datepicker",
6816 instActive;
6817
6818 /* Date picker manager.
6819 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
6820 Settings for (groups of) date pickers are maintained in an instance object,
6821 allowing multiple different settings on the same page. */
6822
6823 function Datepicker() {
6824 this._curInst = null; // The current instance in use
6825 this._keyEvent = false; // If the last event was a key event
6826 this._disabledInputs = []; // List of date picker inputs that have been disabled
6827 this._datepickerShowing = false; // True if the popup picker is showing , false if not
6828 this._inDialog = false; // True if showing within a "dialog", false if not
6829 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
6830 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
6831 this._appendClass = "ui-datepicker-append"; // The name of the append marker class
6832 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
6833 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
6834 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
6835 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
6836 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
6837 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
6838 this.regional = []; // Available regional settings, indexed by language code
6839 this.regional[""] = { // Default regional settings
6840 closeText: "Done", // Display text for close link
6841 prevText: "Prev", // Display text for previous month link
6842 nextText: "Next", // Display text for next month link
6843 currentText: "Today", // Display text for current month link
6844 monthNames: ["January","February","March","April","May","June",
6845 "July","August","September","October","November","December"], // Names of months for drop-down and formatting
6846 monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
6847 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
6848 dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
6849 dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
6850 weekHeader: "Wk", // Column header for week of the year
6851 dateFormat: "mm/dd/yy", // See format options on parseDate
6852 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
6853 isRTL: false, // True if right-to-left language, false if left-to-right
6854 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
6855 yearSuffix: "" // Additional text to append to the year in the month headers
6856 };
6857 this._defaults = { // Global defaults for all the date picker instances
6858 showOn: "focus", // "focus" for popup on focus,
6859 // "button" for trigger button, or "both" for either
6860 showAnim: "fadeIn", // Name of jQuery animation for popup
6861 showOptions: {}, // Options for enhanced animations
6862 defaultDate: null, // Used when field is blank: actual date,
6863 // +/-number for offset from today, null for today
6864 appendText: "", // Display text following the input box, e.g. showing the format
6865 buttonText: "...", // Text for trigger button
6866 buttonImage: "", // URL for trigger button image
6867 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
6868 hideIfNoPrevNext: false, // True to hide next/previous month links
6869 // if not applicable, false to just disable them
6870 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
6871 gotoCurrent: false, // True if today link goes back to current selection instead
6872 changeMonth: false, // True if month can be selected directly, false if only prev/next
6873 changeYear: false, // True if year can be selected directly, false if only prev/next
6874 yearRange: "c-10:c+10", // Range of years to display in drop-down,
6875 // either relative to today's year (-nn:+nn), relative to currently displayed year
6876 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
6877 showOtherMonths: false, // True to show dates in other months, false to leave blank
6878 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
6879 showWeek: false, // True to show week of the year, false to not show it
6880 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
6881 // takes a Date and returns the number of the week for it
6882 shortYearCutoff: "+10", // Short year values < this are in the current century,
6883 // > this are in the previous century,
6884 // string value starting with "+" for current year + value
6885 minDate: null, // The earliest selectable date, or null for no limit
6886 maxDate: null, // The latest selectable date, or null for no limit
6887 duration: "fast", // Duration of display/closure
6888 beforeShowDay: null, // Function that takes a date and returns an array with
6889 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
6890 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
6891 beforeShow: null, // Function that takes an input field and
6892 // returns a set of custom settings for the date picker
6893 onSelect: null, // Define a callback function when a date is selected
6894 onChangeMonthYear: null, // Define a callback function when the month or year is changed
6895 onClose: null, // Define a callback function when the datepicker is closed
6896 numberOfMonths: 1, // Number of months to show at a time
6897 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
6898 stepMonths: 1, // Number of months to step back/forward
6899 stepBigMonths: 12, // Number of months to step back/forward for the big links
6900 altField: "", // Selector for an alternate field to store selected dates into
6901 altFormat: "", // The date format to use for the alternate field
6902 constrainInput: true, // The input is constrained by the current date format
6903 showButtonPanel: false, // True to show button panel, false to not show it
6904 autoSize: false, // True to size the input for the date format, false to leave as is
6905 disabled: false // The initial disabled state
6906 };
6907 $.extend(this._defaults, this.regional[""]);
6908 this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
6909 }
6910
6911 $.extend(Datepicker.prototype, {
6912 /* Class name added to elements to indicate already configured with a date picker. */
6913 markerClassName: "hasDatepicker",
6914
6915 //Keep track of the maximum number of rows displayed (see #7043)
6916 maxRows: 4,
6917
6918 // TODO rename to "widget" when switching to widget factory
6919 _widgetDatepicker: function() {
6920 return this.dpDiv;
6921 },
6922
6923 /* Override the default settings for all instances of the date picker.
6924 * @param settings object - the new settings to use as defaults (anonymous object)
6925 * @return the manager object
6926 */
6927 setDefaults: function(settings) {
6928 extendRemove(this._defaults, settings || {});
6929 return this;
6930 },
6931
6932 /* Attach the date picker to a jQuery selection.
6933 * @param target element - the target input field or division or span
6934 * @param settings object - the new settings to use for this date picker instance (anonymous)
6935 */
6936 _attachDatepicker: function(target, settings) {
6937 var nodeName, inline, inst;
6938 nodeName = target.nodeName.toLowerCase();
6939 inline = (nodeName === "div" || nodeName === "span");
6940 if (!target.id) {
6941 this.uuid += 1;
6942 target.id = "dp" + this.uuid;
6943 }
6944 inst = this._newInst($(target), inline);
6945 inst.settings = $.extend({}, settings || {});
6946 if (nodeName === "input") {
6947 this._connectDatepicker(target, inst);
6948 } else if (inline) {
6949 this._inlineDatepicker(target, inst);
6950 }
6951 },
6952
6953 /* Create a new instance object. */
6954 _newInst: function(target, inline) {
6955 var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
6956 return {id: id, input: target, // associated target
6957 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
6958 drawMonth: 0, drawYear: 0, // month being drawn
6959 inline: inline, // is datepicker inline or not
6960 dpDiv: (!inline ? this.dpDiv : // presentation div
6961 bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
6962 },
6963
6964 /* Attach the date picker to an input field. */
6965 _connectDatepicker: function(target, inst) {
6966 var input = $(target);
6967 inst.append = $([]);
6968 inst.trigger = $([]);
6969 if (input.hasClass(this.markerClassName)) {
6970 return;
6971 }
6972 this._attachments(input, inst);
6973 input.addClass(this.markerClassName).keydown(this._doKeyDown).
6974 keypress(this._doKeyPress).keyup(this._doKeyUp);
6975 this._autoSize(inst);
6976 $.data(target, PROP_NAME, inst);
6977 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
6978 if( inst.settings.disabled ) {
6979 this._disableDatepicker( target );
6980 }
6981 },
6982
6983 /* Make attachments based on settings. */
6984 _attachments: function(input, inst) {
6985 var showOn, buttonText, buttonImage,
6986 appendText = this._get(inst, "appendText"),
6987 isRTL = this._get(inst, "isRTL");
6988
6989 if (inst.append) {
6990 inst.append.remove();
6991 }
6992 if (appendText) {
6993 inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
6994 input[isRTL ? "before" : "after"](inst.append);
6995 }
6996
6997 input.unbind("focus", this._showDatepicker);
6998
6999 if (inst.trigger) {
7000 inst.trigger.remove();
7001 }
7002
7003 showOn = this._get(inst, "showOn");
7004 if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
7005 input.focus(this._showDatepicker);
7006 }
7007 if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
7008 buttonText = this._get(inst, "buttonText");
7009 buttonImage = this._get(inst, "buttonImage");
7010 inst.trigger = $(this._get(inst, "buttonImageOnly") ?
7011 $("<img/>").addClass(this._triggerClass).
7012 attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
7013 $("<button type='button'></button>").addClass(this._triggerClass).
7014 html(!buttonImage ? buttonText : $("<img/>").attr(
7015 { src:buttonImage, alt:buttonText, title:buttonText })));
7016 input[isRTL ? "before" : "after"](inst.trigger);
7017 inst.trigger.click(function() {
7018 if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
7019 $.datepicker._hideDatepicker();
7020 } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
7021 $.datepicker._hideDatepicker();
7022 $.datepicker._showDatepicker(input[0]);
7023 } else {
7024 $.datepicker._showDatepicker(input[0]);
7025 }
7026 return false;
7027 });
7028 }
7029 },
7030
7031 /* Apply the maximum length for the date format. */
7032 _autoSize: function(inst) {
7033 if (this._get(inst, "autoSize") && !inst.inline) {
7034 var findMax, max, maxI, i,
7035 date = new Date(2009, 12 - 1, 20), // Ensure double digits
7036 dateFormat = this._get(inst, "dateFormat");
7037
7038 if (dateFormat.match(/[DM]/)) {
7039 findMax = function(names) {
7040 max = 0;
7041 maxI = 0;
7042 for (i = 0; i < names.length; i++) {
7043 if (names[i].length > max) {
7044 max = names[i].length;
7045 maxI = i;
7046 }
7047 }
7048 return maxI;
7049 };
7050 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
7051 "monthNames" : "monthNamesShort"))));
7052 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
7053 "dayNames" : "dayNamesShort"))) + 20 - date.getDay());
7054 }
7055 inst.input.attr("size", this._formatDate(inst, date).length);
7056 }
7057 },
7058
7059 /* Attach an inline date picker to a div. */
7060 _inlineDatepicker: function(target, inst) {
7061 var divSpan = $(target);
7062 if (divSpan.hasClass(this.markerClassName)) {
7063 return;
7064 }
7065 divSpan.addClass(this.markerClassName).append(inst.dpDiv);
7066 $.data(target, PROP_NAME, inst);
7067 this._setDate(inst, this._getDefaultDate(inst), true);
7068 this._updateDatepicker(inst);
7069 this._updateAlternate(inst);
7070 //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7071 if( inst.settings.disabled ) {
7072 this._disableDatepicker( target );
7073 }
7074 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7075 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7076 inst.dpDiv.css( "display", "block" );
7077 },
7078
7079 /* Pop-up the date picker in a "dialog" box.
7080 * @param input element - ignored
7081 * @param date string or Date - the initial date to display
7082 * @param onSelect function - the function to call when a date is selected
7083 * @param settings object - update the dialog date picker instance's settings (anonymous object)
7084 * @param pos int[2] - coordinates for the dialog's position within the screen or
7085 * event - with x/y coordinates or
7086 * leave empty for default (screen centre)
7087 * @return the manager object
7088 */
7089 _dialogDatepicker: function(input, date, onSelect, settings, pos) {
7090 var id, browserWidth, browserHeight, scrollX, scrollY,
7091 inst = this._dialogInst; // internal instance
7092
7093 if (!inst) {
7094 this.uuid += 1;
7095 id = "dp" + this.uuid;
7096 this._dialogInput = $("<input type='text' id='" + id +
7097 "' style='position: absolute; top: -100px; width: 0px;'/>");
7098 this._dialogInput.keydown(this._doKeyDown);
7099 $("body").append(this._dialogInput);
7100 inst = this._dialogInst = this._newInst(this._dialogInput, false);
7101 inst.settings = {};
7102 $.data(this._dialogInput[0], PROP_NAME, inst);
7103 }
7104 extendRemove(inst.settings, settings || {});
7105 date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
7106 this._dialogInput.val(date);
7107
7108 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
7109 if (!this._pos) {
7110 browserWidth = document.documentElement.clientWidth;
7111 browserHeight = document.documentElement.clientHeight;
7112 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7113 scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7114 this._pos = // should use actual width/height below
7115 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
7116 }
7117
7118 // move input on screen for focus, but hidden behind dialog
7119 this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
7120 inst.settings.onSelect = onSelect;
7121 this._inDialog = true;
7122 this.dpDiv.addClass(this._dialogClass);
7123 this._showDatepicker(this._dialogInput[0]);
7124 if ($.blockUI) {
7125 $.blockUI(this.dpDiv);
7126 }
7127 $.data(this._dialogInput[0], PROP_NAME, inst);
7128 return this;
7129 },
7130
7131 /* Detach a datepicker from its control.
7132 * @param target element - the target input field or division or span
7133 */
7134 _destroyDatepicker: function(target) {
7135 var nodeName,
7136 $target = $(target),
7137 inst = $.data(target, PROP_NAME);
7138
7139 if (!$target.hasClass(this.markerClassName)) {
7140 return;
7141 }
7142
7143 nodeName = target.nodeName.toLowerCase();
7144 $.removeData(target, PROP_NAME);
7145 if (nodeName === "input") {
7146 inst.append.remove();
7147 inst.trigger.remove();
7148 $target.removeClass(this.markerClassName).
7149 unbind("focus", this._showDatepicker).
7150 unbind("keydown", this._doKeyDown).
7151 unbind("keypress", this._doKeyPress).
7152 unbind("keyup", this._doKeyUp);
7153 } else if (nodeName === "div" || nodeName === "span") {
7154 $target.removeClass(this.markerClassName).empty();
7155 }
7156 },
7157
7158 /* Enable the date picker to a jQuery selection.
7159 * @param target element - the target input field or division or span
7160 */
7161 _enableDatepicker: function(target) {
7162 var nodeName, inline,
7163 $target = $(target),
7164 inst = $.data(target, PROP_NAME);
7165
7166 if (!$target.hasClass(this.markerClassName)) {
7167 return;
7168 }
7169
7170 nodeName = target.nodeName.toLowerCase();
7171 if (nodeName === "input") {
7172 target.disabled = false;
7173 inst.trigger.filter("button").
7174 each(function() { this.disabled = false; }).end().
7175 filter("img").css({opacity: "1.0", cursor: ""});
7176 } else if (nodeName === "div" || nodeName === "span") {
7177 inline = $target.children("." + this._inlineClass);
7178 inline.children().removeClass("ui-state-disabled");
7179 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
7180 prop("disabled", false);
7181 }
7182 this._disabledInputs = $.map(this._disabledInputs,
7183 function(value) { return (value === target ? null : value); }); // delete entry
7184 },
7185
7186 /* Disable the date picker to a jQuery selection.
7187 * @param target element - the target input field or division or span
7188 */
7189 _disableDatepicker: function(target) {
7190 var nodeName, inline,
7191 $target = $(target),
7192 inst = $.data(target, PROP_NAME);
7193
7194 if (!$target.hasClass(this.markerClassName)) {
7195 return;
7196 }
7197
7198 nodeName = target.nodeName.toLowerCase();
7199 if (nodeName === "input") {
7200 target.disabled = true;
7201 inst.trigger.filter("button").
7202 each(function() { this.disabled = true; }).end().
7203 filter("img").css({opacity: "0.5", cursor: "default"});
7204 } else if (nodeName === "div" || nodeName === "span") {
7205 inline = $target.children("." + this._inlineClass);
7206 inline.children().addClass("ui-state-disabled");
7207 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
7208 prop("disabled", true);
7209 }
7210 this._disabledInputs = $.map(this._disabledInputs,
7211 function(value) { return (value === target ? null : value); }); // delete entry
7212 this._disabledInputs[this._disabledInputs.length] = target;
7213 },
7214
7215 /* Is the first field in a jQuery collection disabled as a datepicker?
7216 * @param target element - the target input field or division or span
7217 * @return boolean - true if disabled, false if enabled
7218 */
7219 _isDisabledDatepicker: function(target) {
7220 if (!target) {
7221 return false;
7222 }
7223 for (var i = 0; i < this._disabledInputs.length; i++) {
7224 if (this._disabledInputs[i] === target) {
7225 return true;
7226 }
7227 }
7228 return false;
7229 },
7230
7231 /* Retrieve the instance data for the target control.
7232 * @param target element - the target input field or division or span
7233 * @return object - the associated instance data
7234 * @throws error if a jQuery problem getting data
7235 */
7236 _getInst: function(target) {
7237 try {
7238 return $.data(target, PROP_NAME);
7239 }
7240 catch (err) {
7241 throw "Missing instance data for this datepicker";
7242 }
7243 },
7244
7245 /* Update or retrieve the settings for a date picker attached to an input field or division.
7246 * @param target element - the target input field or division or span
7247 * @param name object - the new settings to update or
7248 * string - the name of the setting to change or retrieve,
7249 * when retrieving also "all" for all instance settings or
7250 * "defaults" for all global defaults
7251 * @param value any - the new value for the setting
7252 * (omit if above is an object or to retrieve a value)
7253 */
7254 _optionDatepicker: function(target, name, value) {
7255 var settings, date, minDate, maxDate,
7256 inst = this._getInst(target);
7257
7258 if (arguments.length === 2 && typeof name === "string") {
7259 return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
7260 (inst ? (name === "all" ? $.extend({}, inst.settings) :
7261 this._get(inst, name)) : null));
7262 }
7263
7264 settings = name || {};
7265 if (typeof name === "string") {
7266 settings = {};
7267 settings[name] = value;
7268 }
7269
7270 if (inst) {
7271 if (this._curInst === inst) {
7272 this._hideDatepicker();
7273 }
7274
7275 date = this._getDateDatepicker(target, true);
7276 minDate = this._getMinMaxDate(inst, "min");
7277 maxDate = this._getMinMaxDate(inst, "max");
7278 extendRemove(inst.settings, settings);
7279 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
7280 if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
7281 inst.settings.minDate = this._formatDate(inst, minDate);
7282 }
7283 if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
7284 inst.settings.maxDate = this._formatDate(inst, maxDate);
7285 }
7286 if ( "disabled" in settings ) {
7287 if ( settings.disabled ) {
7288 this._disableDatepicker(target);
7289 } else {
7290 this._enableDatepicker(target);
7291 }
7292 }
7293 this._attachments($(target), inst);
7294 this._autoSize(inst);
7295 this._setDate(inst, date);
7296 this._updateAlternate(inst);
7297 this._updateDatepicker(inst);
7298 }
7299 },
7300
7301 // change method deprecated
7302 _changeDatepicker: function(target, name, value) {
7303 this._optionDatepicker(target, name, value);
7304 },
7305
7306 /* Redraw the date picker attached to an input field or division.
7307 * @param target element - the target input field or division or span
7308 */
7309 _refreshDatepicker: function(target) {
7310 var inst = this._getInst(target);
7311 if (inst) {
7312 this._updateDatepicker(inst);
7313 }
7314 },
7315
7316 /* Set the dates for a jQuery selection.
7317 * @param target element - the target input field or division or span
7318 * @param date Date - the new date
7319 */
7320 _setDateDatepicker: function(target, date) {
7321 var inst = this._getInst(target);
7322 if (inst) {
7323 this._setDate(inst, date);
7324 this._updateDatepicker(inst);
7325 this._updateAlternate(inst);
7326 }
7327 },
7328
7329 /* Get the date(s) for the first entry in a jQuery selection.
7330 * @param target element - the target input field or division or span
7331 * @param noDefault boolean - true if no default date is to be used
7332 * @return Date - the current date
7333 */
7334 _getDateDatepicker: function(target, noDefault) {
7335 var inst = this._getInst(target);
7336 if (inst && !inst.inline) {
7337 this._setDateFromField(inst, noDefault);
7338 }
7339 return (inst ? this._getDate(inst) : null);
7340 },
7341
7342 /* Handle keystrokes. */
7343 _doKeyDown: function(event) {
7344 var onSelect, dateStr, sel,
7345 inst = $.datepicker._getInst(event.target),
7346 handled = true,
7347 isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
7348
7349 inst._keyEvent = true;
7350 if ($.datepicker._datepickerShowing) {
7351 switch (event.keyCode) {
7352 case 9: $.datepicker._hideDatepicker();
7353 handled = false;
7354 break; // hide on tab out
7355 case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
7356 $.datepicker._currentClass + ")", inst.dpDiv);
7357 if (sel[0]) {
7358 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
7359 }
7360
7361 onSelect = $.datepicker._get(inst, "onSelect");
7362 if (onSelect) {
7363 dateStr = $.datepicker._formatDate(inst);
7364
7365 // trigger custom callback
7366 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
7367 } else {
7368 $.datepicker._hideDatepicker();
7369 }
7370
7371 return false; // don't submit the form
7372 case 27: $.datepicker._hideDatepicker();
7373 break; // hide on escape
7374 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7375 -$.datepicker._get(inst, "stepBigMonths") :
7376 -$.datepicker._get(inst, "stepMonths")), "M");
7377 break; // previous month/year on page up/+ ctrl
7378 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7379 +$.datepicker._get(inst, "stepBigMonths") :
7380 +$.datepicker._get(inst, "stepMonths")), "M");
7381 break; // next month/year on page down/+ ctrl
7382 case 35: if (event.ctrlKey || event.metaKey) {
7383 $.datepicker._clearDate(event.target);
7384 }
7385 handled = event.ctrlKey || event.metaKey;
7386 break; // clear on ctrl or command +end
7387 case 36: if (event.ctrlKey || event.metaKey) {
7388 $.datepicker._gotoToday(event.target);
7389 }
7390 handled = event.ctrlKey || event.metaKey;
7391 break; // current on ctrl or command +home
7392 case 37: if (event.ctrlKey || event.metaKey) {
7393 $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
7394 }
7395 handled = event.ctrlKey || event.metaKey;
7396 // -1 day on ctrl or command +left
7397 if (event.originalEvent.altKey) {
7398 $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7399 -$.datepicker._get(inst, "stepBigMonths") :
7400 -$.datepicker._get(inst, "stepMonths")), "M");
7401 }
7402 // next month/year on alt +left on Mac
7403 break;
7404 case 38: if (event.ctrlKey || event.metaKey) {
7405 $.datepicker._adjustDate(event.target, -7, "D");
7406 }
7407 handled = event.ctrlKey || event.metaKey;
7408 break; // -1 week on ctrl or command +up
7409 case 39: if (event.ctrlKey || event.metaKey) {
7410 $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
7411 }
7412 handled = event.ctrlKey || event.metaKey;
7413 // +1 day on ctrl or command +right
7414 if (event.originalEvent.altKey) {
7415 $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7416 +$.datepicker._get(inst, "stepBigMonths") :
7417 +$.datepicker._get(inst, "stepMonths")), "M");
7418 }
7419 // next month/year on alt +right
7420 break;
7421 case 40: if (event.ctrlKey || event.metaKey) {
7422 $.datepicker._adjustDate(event.target, +7, "D");
7423 }
7424 handled = event.ctrlKey || event.metaKey;
7425 break; // +1 week on ctrl or command +down
7426 default: handled = false;
7427 }
7428 } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
7429 $.datepicker._showDatepicker(this);
7430 } else {
7431 handled = false;
7432 }
7433
7434 if (handled) {
7435 event.preventDefault();
7436 event.stopPropagation();
7437 }
7438 },
7439
7440 /* Filter entered characters - based on date format. */
7441 _doKeyPress: function(event) {
7442 var chars, chr,
7443 inst = $.datepicker._getInst(event.target);
7444
7445 if ($.datepicker._get(inst, "constrainInput")) {
7446 chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
7447 chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
7448 return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
7449 }
7450 },
7451
7452 /* Synchronise manual entry and field/alternate field. */
7453 _doKeyUp: function(event) {
7454 var date,
7455 inst = $.datepicker._getInst(event.target);
7456
7457 if (inst.input.val() !== inst.lastVal) {
7458 try {
7459 date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
7460 (inst.input ? inst.input.val() : null),
7461 $.datepicker._getFormatConfig(inst));
7462
7463 if (date) { // only if valid
7464 $.datepicker._setDateFromField(inst);
7465 $.datepicker._updateAlternate(inst);
7466 $.datepicker._updateDatepicker(inst);
7467 }
7468 }
7469 catch (err) {
7470 }
7471 }
7472 return true;
7473 },
7474
7475 /* Pop-up the date picker for a given input field.
7476 * If false returned from beforeShow event handler do not show.
7477 * @param input element - the input field attached to the date picker or
7478 * event - if triggered by focus
7479 */
7480 _showDatepicker: function(input) {
7481 input = input.target || input;
7482 if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
7483 input = $("input", input.parentNode)[0];
7484 }
7485
7486 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
7487 return;
7488 }
7489
7490 var inst, beforeShow, beforeShowSettings, isFixed,
7491 offset, showAnim, duration;
7492
7493 inst = $.datepicker._getInst(input);
7494 if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
7495 $.datepicker._curInst.dpDiv.stop(true, true);
7496 if ( inst && $.datepicker._datepickerShowing ) {
7497 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
7498 }
7499 }
7500
7501 beforeShow = $.datepicker._get(inst, "beforeShow");
7502 beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
7503 if(beforeShowSettings === false){
7504 return;
7505 }
7506 extendRemove(inst.settings, beforeShowSettings);
7507
7508 inst.lastVal = null;
7509 $.datepicker._lastInput = input;
7510 $.datepicker._setDateFromField(inst);
7511
7512 if ($.datepicker._inDialog) { // hide cursor
7513 input.value = "";
7514 }
7515 if (!$.datepicker._pos) { // position below input
7516 $.datepicker._pos = $.datepicker._findPos(input);
7517 $.datepicker._pos[1] += input.offsetHeight; // add the height
7518 }
7519
7520 isFixed = false;
7521 $(input).parents().each(function() {
7522 isFixed |= $(this).css("position") === "fixed";
7523 return !isFixed;
7524 });
7525
7526 offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
7527 $.datepicker._pos = null;
7528 //to avoid flashes on Firefox
7529 inst.dpDiv.empty();
7530 // determine sizing offscreen
7531 inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
7532 $.datepicker._updateDatepicker(inst);
7533 // fix width for dynamic number of date pickers
7534 // and adjust position before showing
7535 offset = $.datepicker._checkOffset(inst, offset, isFixed);
7536 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
7537 "static" : (isFixed ? "fixed" : "absolute")), display: "none",
7538 left: offset.left + "px", top: offset.top + "px"});
7539
7540 if (!inst.inline) {
7541 showAnim = $.datepicker._get(inst, "showAnim");
7542 duration = $.datepicker._get(inst, "duration");
7543 inst.dpDiv.zIndex($(input).zIndex()+1);
7544 $.datepicker._datepickerShowing = true;
7545
7546 if ( $.effects && $.effects.effect[ showAnim ] ) {
7547 inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
7548 } else {
7549 inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
7550 }
7551
7552 if ( $.datepicker._shouldFocusInput( inst ) ) {
7553 inst.input.focus();
7554 }
7555
7556 $.datepicker._curInst = inst;
7557 }
7558 },
7559
7560 /* Generate the date picker content. */
7561 _updateDatepicker: function(inst) {
7562 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
7563 instActive = inst; // for delegate hover events
7564 inst.dpDiv.empty().append(this._generateHTML(inst));
7565 this._attachHandlers(inst);
7566 inst.dpDiv.find("." + this._dayOverClass + " a").mouseover();
7567
7568 var origyearshtml,
7569 numMonths = this._getNumberOfMonths(inst),
7570 cols = numMonths[1],
7571 width = 17;
7572
7573 inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
7574 if (cols > 1) {
7575 inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
7576 }
7577 inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
7578 "Class"]("ui-datepicker-multi");
7579 inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
7580 "Class"]("ui-datepicker-rtl");
7581
7582 if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
7583 inst.input.focus();
7584 }
7585
7586 // deffered render of the years select (to avoid flashes on Firefox)
7587 if( inst.yearshtml ){
7588 origyearshtml = inst.yearshtml;
7589 setTimeout(function(){
7590 //assure that inst.yearshtml didn't change.
7591 if( origyearshtml === inst.yearshtml && inst.yearshtml ){
7592 inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
7593 }
7594 origyearshtml = inst.yearshtml = null;
7595 }, 0);
7596 }
7597 },
7598
7599 // #6694 - don't focus the input if it's already focused
7600 // this breaks the change event in IE
7601 // Support: IE and jQuery <1.9
7602 _shouldFocusInput: function( inst ) {
7603 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
7604 },
7605
7606 /* Check positioning to remain on screen. */
7607 _checkOffset: function(inst, offset, isFixed) {
7608 var dpWidth = inst.dpDiv.outerWidth(),
7609 dpHeight = inst.dpDiv.outerHeight(),
7610 inputWidth = inst.input ? inst.input.outerWidth() : 0,
7611 inputHeight = inst.input ? inst.input.outerHeight() : 0,
7612 viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
7613 viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
7614
7615 offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
7616 offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
7617 offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
7618
7619 // now check if datepicker is showing outside window viewport - move to a better place if so.
7620 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
7621 Math.abs(offset.left + dpWidth - viewWidth) : 0);
7622 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
7623 Math.abs(dpHeight + inputHeight) : 0);
7624
7625 return offset;
7626 },
7627
7628 /* Find an object's position on the screen. */
7629 _findPos: function(obj) {
7630 var position,
7631 inst = this._getInst(obj),
7632 isRTL = this._get(inst, "isRTL");
7633
7634 while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
7635 obj = obj[isRTL ? "previousSibling" : "nextSibling"];
7636 }
7637
7638 position = $(obj).offset();
7639 return [position.left, position.top];
7640 },
7641
7642 /* Hide the date picker from view.
7643 * @param input element - the input field attached to the date picker
7644 */
7645 _hideDatepicker: function(input) {
7646 var showAnim, duration, postProcess, onClose,
7647 inst = this._curInst;
7648
7649 if (!inst || (input && inst !== $.data(input, PROP_NAME))) {
7650 return;
7651 }
7652
7653 if (this._datepickerShowing) {
7654 showAnim = this._get(inst, "showAnim");
7655 duration = this._get(inst, "duration");
7656 postProcess = function() {
7657 $.datepicker._tidyDialog(inst);
7658 };
7659
7660 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
7661 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
7662 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
7663 } else {
7664 inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
7665 (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
7666 }
7667
7668 if (!showAnim) {
7669 postProcess();
7670 }
7671 this._datepickerShowing = false;
7672
7673 onClose = this._get(inst, "onClose");
7674 if (onClose) {
7675 onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
7676 }
7677
7678 this._lastInput = null;
7679 if (this._inDialog) {
7680 this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
7681 if ($.blockUI) {
7682 $.unblockUI();
7683 $("body").append(this.dpDiv);
7684 }
7685 }
7686 this._inDialog = false;
7687 }
7688 },
7689
7690 /* Tidy up after a dialog display. */
7691 _tidyDialog: function(inst) {
7692 inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
7693 },
7694
7695 /* Close date picker if clicked elsewhere. */
7696 _checkExternalClick: function(event) {
7697 if (!$.datepicker._curInst) {
7698 return;
7699 }
7700
7701 var $target = $(event.target),
7702 inst = $.datepicker._getInst($target[0]);
7703
7704 if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
7705 $target.parents("#" + $.datepicker._mainDivId).length === 0 &&
7706 !$target.hasClass($.datepicker.markerClassName) &&
7707 !$target.closest("." + $.datepicker._triggerClass).length &&
7708 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
7709 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
7710 $.datepicker._hideDatepicker();
7711 }
7712 },
7713
7714 /* Adjust one of the date sub-fields. */
7715 _adjustDate: function(id, offset, period) {
7716 var target = $(id),
7717 inst = this._getInst(target[0]);
7718
7719 if (this._isDisabledDatepicker(target[0])) {
7720 return;
7721 }
7722 this._adjustInstDate(inst, offset +
7723 (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
7724 period);
7725 this._updateDatepicker(inst);
7726 },
7727
7728 /* Action for current link. */
7729 _gotoToday: function(id) {
7730 var date,
7731 target = $(id),
7732 inst = this._getInst(target[0]);
7733
7734 if (this._get(inst, "gotoCurrent") && inst.currentDay) {
7735 inst.selectedDay = inst.currentDay;
7736 inst.drawMonth = inst.selectedMonth = inst.currentMonth;
7737 inst.drawYear = inst.selectedYear = inst.currentYear;
7738 } else {
7739 date = new Date();
7740 inst.selectedDay = date.getDate();
7741 inst.drawMonth = inst.selectedMonth = date.getMonth();
7742 inst.drawYear = inst.selectedYear = date.getFullYear();
7743 }
7744 this._notifyChange(inst);
7745 this._adjustDate(target);
7746 },
7747
7748 /* Action for selecting a new month/year. */
7749 _selectMonthYear: function(id, select, period) {
7750 var target = $(id),
7751 inst = this._getInst(target[0]);
7752
7753 inst["selected" + (period === "M" ? "Month" : "Year")] =
7754 inst["draw" + (period === "M" ? "Month" : "Year")] =
7755 parseInt(select.options[select.selectedIndex].value,10);
7756
7757 this._notifyChange(inst);
7758 this._adjustDate(target);
7759 },
7760
7761 /* Action for selecting a day. */
7762 _selectDay: function(id, month, year, td) {
7763 var inst,
7764 target = $(id);
7765
7766 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
7767 return;
7768 }
7769
7770 inst = this._getInst(target[0]);
7771 inst.selectedDay = inst.currentDay = $("a", td).html();
7772 inst.selectedMonth = inst.currentMonth = month;
7773 inst.selectedYear = inst.currentYear = year;
7774 this._selectDate(id, this._formatDate(inst,
7775 inst.currentDay, inst.currentMonth, inst.currentYear));
7776 },
7777
7778 /* Erase the input field and hide the date picker. */
7779 _clearDate: function(id) {
7780 var target = $(id);
7781 this._selectDate(target, "");
7782 },
7783
7784 /* Update the input field with the selected date. */
7785 _selectDate: function(id, dateStr) {
7786 var onSelect,
7787 target = $(id),
7788 inst = this._getInst(target[0]);
7789
7790 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
7791 if (inst.input) {
7792 inst.input.val(dateStr);
7793 }
7794 this._updateAlternate(inst);
7795
7796 onSelect = this._get(inst, "onSelect");
7797 if (onSelect) {
7798 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
7799 } else if (inst.input) {
7800 inst.input.trigger("change"); // fire the change event
7801 }
7802
7803 if (inst.inline){
7804 this._updateDatepicker(inst);
7805 } else {
7806 this._hideDatepicker();
7807 this._lastInput = inst.input[0];
7808 if (typeof(inst.input[0]) !== "object") {
7809 inst.input.focus(); // restore focus
7810 }
7811 this._lastInput = null;
7812 }
7813 },
7814
7815 /* Update any alternate field to synchronise with the main field. */
7816 _updateAlternate: function(inst) {
7817 var altFormat, date, dateStr,
7818 altField = this._get(inst, "altField");
7819
7820 if (altField) { // update alternate field too
7821 altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
7822 date = this._getDate(inst);
7823 dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
7824 $(altField).each(function() { $(this).val(dateStr); });
7825 }
7826 },
7827
7828 /* Set as beforeShowDay function to prevent selection of weekends.
7829 * @param date Date - the date to customise
7830 * @return [boolean, string] - is this date selectable?, what is its CSS class?
7831 */
7832 noWeekends: function(date) {
7833 var day = date.getDay();
7834 return [(day > 0 && day < 6), ""];
7835 },
7836
7837 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
7838 * @param date Date - the date to get the week for
7839 * @return number - the number of the week within the year that contains this date
7840 */
7841 iso8601Week: function(date) {
7842 var time,
7843 checkDate = new Date(date.getTime());
7844
7845 // Find Thursday of this week starting on Monday
7846 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
7847
7848 time = checkDate.getTime();
7849 checkDate.setMonth(0); // Compare with Jan 1
7850 checkDate.setDate(1);
7851 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
7852 },
7853
7854 /* Parse a string value into a date object.
7855 * See formatDate below for the possible formats.
7856 *
7857 * @param format string - the expected format of the date
7858 * @param value string - the date in the above format
7859 * @param settings Object - attributes include:
7860 * shortYearCutoff number - the cutoff year for determining the century (optional)
7861 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
7862 * dayNames string[7] - names of the days from Sunday (optional)
7863 * monthNamesShort string[12] - abbreviated names of the months (optional)
7864 * monthNames string[12] - names of the months (optional)
7865 * @return Date - the extracted date value or null if value is blank
7866 */
7867 parseDate: function (format, value, settings) {
7868 if (format == null || value == null) {
7869 throw "Invalid arguments";
7870 }
7871
7872 value = (typeof value === "object" ? value.toString() : value + "");
7873 if (value === "") {
7874 return null;
7875 }
7876
7877 var iFormat, dim, extra,
7878 iValue = 0,
7879 shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
7880 shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
7881 new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
7882 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
7883 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
7884 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
7885 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
7886 year = -1,
7887 month = -1,
7888 day = -1,
7889 doy = -1,
7890 literal = false,
7891 date,
7892 // Check whether a format character is doubled
7893 lookAhead = function(match) {
7894 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
7895 if (matches) {
7896 iFormat++;
7897 }
7898 return matches;
7899 },
7900 // Extract a number from the string value
7901 getNumber = function(match) {
7902 var isDoubled = lookAhead(match),
7903 size = (match === "@" ? 14 : (match === "!" ? 20 :
7904 (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
7905 digits = new RegExp("^\\d{1," + size + "}"),
7906 num = value.substring(iValue).match(digits);
7907 if (!num) {
7908 throw "Missing number at position " + iValue;
7909 }
7910 iValue += num[0].length;
7911 return parseInt(num[0], 10);
7912 },
7913 // Extract a name from the string value and convert to an index
7914 getName = function(match, shortNames, longNames) {
7915 var index = -1,
7916 names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
7917 return [ [k, v] ];
7918 }).sort(function (a, b) {
7919 return -(a[1].length - b[1].length);
7920 });
7921
7922 $.each(names, function (i, pair) {
7923 var name = pair[1];
7924 if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
7925 index = pair[0];
7926 iValue += name.length;
7927 return false;
7928 }
7929 });
7930 if (index !== -1) {
7931 return index + 1;
7932 } else {
7933 throw "Unknown name at position " + iValue;
7934 }
7935 },
7936 // Confirm that a literal character matches the string value
7937 checkLiteral = function() {
7938 if (value.charAt(iValue) !== format.charAt(iFormat)) {
7939 throw "Unexpected literal at position " + iValue;
7940 }
7941 iValue++;
7942 };
7943
7944 for (iFormat = 0; iFormat < format.length; iFormat++) {
7945 if (literal) {
7946 if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
7947 literal = false;
7948 } else {
7949 checkLiteral();
7950 }
7951 } else {
7952 switch (format.charAt(iFormat)) {
7953 case "d":
7954 day = getNumber("d");
7955 break;
7956 case "D":
7957 getName("D", dayNamesShort, dayNames);
7958 break;
7959 case "o":
7960 doy = getNumber("o");
7961 break;
7962 case "m":
7963 month = getNumber("m");
7964 break;
7965 case "M":
7966 month = getName("M", monthNamesShort, monthNames);
7967 break;
7968 case "y":
7969 year = getNumber("y");
7970 break;
7971 case "@":
7972 date = new Date(getNumber("@"));
7973 year = date.getFullYear();
7974 month = date.getMonth() + 1;
7975 day = date.getDate();
7976 break;
7977 case "!":
7978 date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
7979 year = date.getFullYear();
7980 month = date.getMonth() + 1;
7981 day = date.getDate();
7982 break;
7983 case "'":
7984 if (lookAhead("'")){
7985 checkLiteral();
7986 } else {
7987 literal = true;
7988 }
7989 break;
7990 default:
7991 checkLiteral();
7992 }
7993 }
7994 }
7995
7996 if (iValue < value.length){
7997 extra = value.substr(iValue);
7998 if (!/^\s+/.test(extra)) {
7999 throw "Extra/unparsed characters found in date: " + extra;
8000 }
8001 }
8002
8003 if (year === -1) {
8004 year = new Date().getFullYear();
8005 } else if (year < 100) {
8006 year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8007 (year <= shortYearCutoff ? 0 : -100);
8008 }
8009
8010 if (doy > -1) {
8011 month = 1;
8012 day = doy;
8013 do {
8014 dim = this._getDaysInMonth(year, month - 1);
8015 if (day <= dim) {
8016 break;
8017 }
8018 month++;
8019 day -= dim;
8020 } while (true);
8021 }
8022
8023 date = this._daylightSavingAdjust(new Date(year, month - 1, day));
8024 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
8025 throw "Invalid date"; // E.g. 31/02/00
8026 }
8027 return date;
8028 },
8029
8030 /* Standard date formats. */
8031 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
8032 COOKIE: "D, dd M yy",
8033 ISO_8601: "yy-mm-dd",
8034 RFC_822: "D, d M y",
8035 RFC_850: "DD, dd-M-y",
8036 RFC_1036: "D, d M y",
8037 RFC_1123: "D, d M yy",
8038 RFC_2822: "D, d M yy",
8039 RSS: "D, d M y", // RFC 822
8040 TICKS: "!",
8041 TIMESTAMP: "@",
8042 W3C: "yy-mm-dd", // ISO 8601
8043
8044 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
8045 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
8046
8047 /* Format a date object into a string value.
8048 * The format can be combinations of the following:
8049 * d - day of month (no leading zero)
8050 * dd - day of month (two digit)
8051 * o - day of year (no leading zeros)
8052 * oo - day of year (three digit)
8053 * D - day name short
8054 * DD - day name long
8055 * m - month of year (no leading zero)
8056 * mm - month of year (two digit)
8057 * M - month name short
8058 * MM - month name long
8059 * y - year (two digit)
8060 * yy - year (four digit)
8061 * @ - Unix timestamp (ms since 01/01/1970)
8062 * ! - Windows ticks (100ns since 01/01/0001)
8063 * "..." - literal text
8064 * '' - single quote
8065 *
8066 * @param format string - the desired format of the date
8067 * @param date Date - the date value to format
8068 * @param settings Object - attributes include:
8069 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8070 * dayNames string[7] - names of the days from Sunday (optional)
8071 * monthNamesShort string[12] - abbreviated names of the months (optional)
8072 * monthNames string[12] - names of the months (optional)
8073 * @return string - the date in the above format
8074 */
8075 formatDate: function (format, date, settings) {
8076 if (!date) {
8077 return "";
8078 }
8079
8080 var iFormat,
8081 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
8082 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
8083 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
8084 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
8085 // Check whether a format character is doubled
8086 lookAhead = function(match) {
8087 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
8088 if (matches) {
8089 iFormat++;
8090 }
8091 return matches;
8092 },
8093 // Format a number, with leading zero if necessary
8094 formatNumber = function(match, value, len) {
8095 var num = "" + value;
8096 if (lookAhead(match)) {
8097 while (num.length < len) {
8098 num = "0" + num;
8099 }
8100 }
8101 return num;
8102 },
8103 // Format a name, short or long as requested
8104 formatName = function(match, value, shortNames, longNames) {
8105 return (lookAhead(match) ? longNames[value] : shortNames[value]);
8106 },
8107 output = "",
8108 literal = false;
8109
8110 if (date) {
8111 for (iFormat = 0; iFormat < format.length; iFormat++) {
8112 if (literal) {
8113 if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
8114 literal = false;
8115 } else {
8116 output += format.charAt(iFormat);
8117 }
8118 } else {
8119 switch (format.charAt(iFormat)) {
8120 case "d":
8121 output += formatNumber("d", date.getDate(), 2);
8122 break;
8123 case "D":
8124 output += formatName("D", date.getDay(), dayNamesShort, dayNames);
8125 break;
8126 case "o":
8127 output += formatNumber("o",
8128 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
8129 break;
8130 case "m":
8131 output += formatNumber("m", date.getMonth() + 1, 2);
8132 break;
8133 case "M":
8134 output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
8135 break;
8136 case "y":
8137 output += (lookAhead("y") ? date.getFullYear() :
8138 (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
8139 break;
8140 case "@":
8141 output += date.getTime();
8142 break;
8143 case "!":
8144 output += date.getTime() * 10000 + this._ticksTo1970;
8145 break;
8146 case "'":
8147 if (lookAhead("'")) {
8148 output += "'";
8149 } else {
8150 literal = true;
8151 }
8152 break;
8153 default:
8154 output += format.charAt(iFormat);
8155 }
8156 }
8157 }
8158 }
8159 return output;
8160 },
8161
8162 /* Extract all possible characters from the date format. */
8163 _possibleChars: function (format) {
8164 var iFormat,
8165 chars = "",
8166 literal = false,
8167 // Check whether a format character is doubled
8168 lookAhead = function(match) {
8169 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
8170 if (matches) {
8171 iFormat++;
8172 }
8173 return matches;
8174 };
8175
8176 for (iFormat = 0; iFormat < format.length; iFormat++) {
8177 if (literal) {
8178 if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
8179 literal = false;
8180 } else {
8181 chars += format.charAt(iFormat);
8182 }
8183 } else {
8184 switch (format.charAt(iFormat)) {
8185 case "d": case "m": case "y": case "@":
8186 chars += "0123456789";
8187 break;
8188 case "D": case "M":
8189 return null; // Accept anything
8190 case "'":
8191 if (lookAhead("'")) {
8192 chars += "'";
8193 } else {
8194 literal = true;
8195 }
8196 break;
8197 default:
8198 chars += format.charAt(iFormat);
8199 }
8200 }
8201 }
8202 return chars;
8203 },
8204
8205 /* Get a setting value, defaulting if necessary. */
8206 _get: function(inst, name) {
8207 return inst.settings[name] !== undefined ?
8208 inst.settings[name] : this._defaults[name];
8209 },
8210
8211 /* Parse existing date and initialise date picker. */
8212 _setDateFromField: function(inst, noDefault) {
8213 if (inst.input.val() === inst.lastVal) {
8214 return;
8215 }
8216
8217 var dateFormat = this._get(inst, "dateFormat"),
8218 dates = inst.lastVal = inst.input ? inst.input.val() : null,
8219 defaultDate = this._getDefaultDate(inst),
8220 date = defaultDate,
8221 settings = this._getFormatConfig(inst);
8222
8223 try {
8224 date = this.parseDate(dateFormat, dates, settings) || defaultDate;
8225 } catch (event) {
8226 dates = (noDefault ? "" : dates);
8227 }
8228 inst.selectedDay = date.getDate();
8229 inst.drawMonth = inst.selectedMonth = date.getMonth();
8230 inst.drawYear = inst.selectedYear = date.getFullYear();
8231 inst.currentDay = (dates ? date.getDate() : 0);
8232 inst.currentMonth = (dates ? date.getMonth() : 0);
8233 inst.currentYear = (dates ? date.getFullYear() : 0);
8234 this._adjustInstDate(inst);
8235 },
8236
8237 /* Retrieve the default date shown on opening. */
8238 _getDefaultDate: function(inst) {
8239 return this._restrictMinMax(inst,
8240 this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
8241 },
8242
8243 /* A date may be specified as an exact value or a relative one. */
8244 _determineDate: function(inst, date, defaultDate) {
8245 var offsetNumeric = function(offset) {
8246 var date = new Date();
8247 date.setDate(date.getDate() + offset);
8248 return date;
8249 },
8250 offsetString = function(offset) {
8251 try {
8252 return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
8253 offset, $.datepicker._getFormatConfig(inst));
8254 }
8255 catch (e) {
8256 // Ignore
8257 }
8258
8259 var date = (offset.toLowerCase().match(/^c/) ?
8260 $.datepicker._getDate(inst) : null) || new Date(),
8261 year = date.getFullYear(),
8262 month = date.getMonth(),
8263 day = date.getDate(),
8264 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
8265 matches = pattern.exec(offset);
8266
8267 while (matches) {
8268 switch (matches[2] || "d") {
8269 case "d" : case "D" :
8270 day += parseInt(matches[1],10); break;
8271 case "w" : case "W" :
8272 day += parseInt(matches[1],10) * 7; break;
8273 case "m" : case "M" :
8274 month += parseInt(matches[1],10);
8275 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
8276 break;
8277 case "y": case "Y" :
8278 year += parseInt(matches[1],10);
8279 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
8280 break;
8281 }
8282 matches = pattern.exec(offset);
8283 }
8284 return new Date(year, month, day);
8285 },
8286 newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
8287 (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
8288
8289 newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
8290 if (newDate) {
8291 newDate.setHours(0);
8292 newDate.setMinutes(0);
8293 newDate.setSeconds(0);
8294 newDate.setMilliseconds(0);
8295 }
8296 return this._daylightSavingAdjust(newDate);
8297 },
8298
8299 /* Handle switch to/from daylight saving.
8300 * Hours may be non-zero on daylight saving cut-over:
8301 * > 12 when midnight changeover, but then cannot generate
8302 * midnight datetime, so jump to 1AM, otherwise reset.
8303 * @param date (Date) the date to check
8304 * @return (Date) the corrected date
8305 */
8306 _daylightSavingAdjust: function(date) {
8307 if (!date) {
8308 return null;
8309 }
8310 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
8311 return date;
8312 },
8313
8314 /* Set the date(s) directly. */
8315 _setDate: function(inst, date, noChange) {
8316 var clear = !date,
8317 origMonth = inst.selectedMonth,
8318 origYear = inst.selectedYear,
8319 newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
8320
8321 inst.selectedDay = inst.currentDay = newDate.getDate();
8322 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
8323 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
8324 if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
8325 this._notifyChange(inst);
8326 }
8327 this._adjustInstDate(inst);
8328 if (inst.input) {
8329 inst.input.val(clear ? "" : this._formatDate(inst));
8330 }
8331 },
8332
8333 /* Retrieve the date(s) directly. */
8334 _getDate: function(inst) {
8335 var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
8336 this._daylightSavingAdjust(new Date(
8337 inst.currentYear, inst.currentMonth, inst.currentDay)));
8338 return startDate;
8339 },
8340
8341 /* Attach the onxxx handlers. These are declared statically so
8342 * they work with static code transformers like Caja.
8343 */
8344 _attachHandlers: function(inst) {
8345 var stepMonths = this._get(inst, "stepMonths"),
8346 id = "#" + inst.id.replace( /\\\\/g, "\\" );
8347 inst.dpDiv.find("[data-handler]").map(function () {
8348 var handler = {
8349 prev: function () {
8350 $.datepicker._adjustDate(id, -stepMonths, "M");
8351 },
8352 next: function () {
8353 $.datepicker._adjustDate(id, +stepMonths, "M");
8354 },
8355 hide: function () {
8356 $.datepicker._hideDatepicker();
8357 },
8358 today: function () {
8359 $.datepicker._gotoToday(id);
8360 },
8361 selectDay: function () {
8362 $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
8363 return false;
8364 },
8365 selectMonth: function () {
8366 $.datepicker._selectMonthYear(id, this, "M");
8367 return false;
8368 },
8369 selectYear: function () {
8370 $.datepicker._selectMonthYear(id, this, "Y");
8371 return false;
8372 }
8373 };
8374 $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
8375 });
8376 },
8377
8378 /* Generate the HTML for the current state of the date picker. */
8379 _generateHTML: function(inst) {
8380 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
8381 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
8382 monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
8383 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
8384 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
8385 printDate, dRow, tbody, daySettings, otherMonth, unselectable,
8386 tempDate = new Date(),
8387 today = this._daylightSavingAdjust(
8388 new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
8389 isRTL = this._get(inst, "isRTL"),
8390 showButtonPanel = this._get(inst, "showButtonPanel"),
8391 hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
8392 navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
8393 numMonths = this._getNumberOfMonths(inst),
8394 showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
8395 stepMonths = this._get(inst, "stepMonths"),
8396 isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
8397 currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
8398 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
8399 minDate = this._getMinMaxDate(inst, "min"),
8400 maxDate = this._getMinMaxDate(inst, "max"),
8401 drawMonth = inst.drawMonth - showCurrentAtPos,
8402 drawYear = inst.drawYear;
8403
8404 if (drawMonth < 0) {
8405 drawMonth += 12;
8406 drawYear--;
8407 }
8408 if (maxDate) {
8409 maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
8410 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
8411 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
8412 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
8413 drawMonth--;
8414 if (drawMonth < 0) {
8415 drawMonth = 11;
8416 drawYear--;
8417 }
8418 }
8419 }
8420 inst.drawMonth = drawMonth;
8421 inst.drawYear = drawYear;
8422
8423 prevText = this._get(inst, "prevText");
8424 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
8425 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
8426 this._getFormatConfig(inst)));
8427
8428 prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
8429 "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
8430 " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
8431 (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>"));
8432
8433 nextText = this._get(inst, "nextText");
8434 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
8435 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
8436 this._getFormatConfig(inst)));
8437
8438 next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
8439 "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
8440 " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
8441 (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>"));
8442
8443 currentText = this._get(inst, "currentText");
8444 gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
8445 currentText = (!navigationAsDateFormat ? currentText :
8446 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
8447
8448 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'>" +
8449 this._get(inst, "closeText") + "</button>" : "");
8450
8451 buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
8452 (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'" +
8453 ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
8454
8455 firstDay = parseInt(this._get(inst, "firstDay"),10);
8456 firstDay = (isNaN(firstDay) ? 0 : firstDay);
8457
8458 showWeek = this._get(inst, "showWeek");
8459 dayNames = this._get(inst, "dayNames");
8460 dayNamesMin = this._get(inst, "dayNamesMin");
8461 monthNames = this._get(inst, "monthNames");
8462 monthNamesShort = this._get(inst, "monthNamesShort");
8463 beforeShowDay = this._get(inst, "beforeShowDay");
8464 showOtherMonths = this._get(inst, "showOtherMonths");
8465 selectOtherMonths = this._get(inst, "selectOtherMonths");
8466 defaultDate = this._getDefaultDate(inst);
8467 html = "";
8468 dow;
8469 for (row = 0; row < numMonths[0]; row++) {
8470 group = "";
8471 this.maxRows = 4;
8472 for (col = 0; col < numMonths[1]; col++) {
8473 selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
8474 cornerClass = " ui-corner-all";
8475 calender = "";
8476 if (isMultiMonth) {
8477 calender += "<div class='ui-datepicker-group";
8478 if (numMonths[1] > 1) {
8479 switch (col) {
8480 case 0: calender += " ui-datepicker-group-first";
8481 cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
8482 case numMonths[1]-1: calender += " ui-datepicker-group-last";
8483 cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
8484 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
8485 }
8486 }
8487 calender += "'>";
8488 }
8489 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
8490 (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
8491 (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
8492 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
8493 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
8494 "</div><table class='ui-datepicker-calendar'><thead>" +
8495 "<tr>";
8496 thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
8497 for (dow = 0; dow < 7; dow++) { // days of the week
8498 day = (dow + firstDay) % 7;
8499 thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
8500 "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
8501 }
8502 calender += thead + "</tr></thead><tbody>";
8503 daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
8504 if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
8505 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
8506 }
8507 leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
8508 curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
8509 numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
8510 this.maxRows = numRows;
8511 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
8512 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
8513 calender += "<tr>";
8514 tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
8515 this._get(inst, "calculateWeek")(printDate) + "</td>");
8516 for (dow = 0; dow < 7; dow++) { // create date picker days
8517 daySettings = (beforeShowDay ?
8518 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
8519 otherMonth = (printDate.getMonth() !== drawMonth);
8520 unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
8521 (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
8522 tbody += "<td class='" +
8523 ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
8524 (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
8525 ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
8526 (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
8527 // or defaultDate is current printedDate and defaultDate is selectedDate
8528 " " + this._dayOverClass : "") + // highlight selected day
8529 (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days
8530 (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
8531 (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
8532 (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
8533 ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + // cell title
8534 (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
8535 (otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
8536 (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
8537 (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
8538 (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
8539 (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
8540 "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
8541 printDate.setDate(printDate.getDate() + 1);
8542 printDate = this._daylightSavingAdjust(printDate);
8543 }
8544 calender += tbody + "</tr>";
8545 }
8546 drawMonth++;
8547 if (drawMonth > 11) {
8548 drawMonth = 0;
8549 drawYear++;
8550 }
8551 calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
8552 ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
8553 group += calender;
8554 }
8555 html += group;
8556 }
8557 html += buttonPanel;
8558 inst._keyEvent = false;
8559 return html;
8560 },
8561
8562 /* Generate the month and year header. */
8563 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
8564 secondary, monthNames, monthNamesShort) {
8565
8566 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
8567 changeMonth = this._get(inst, "changeMonth"),
8568 changeYear = this._get(inst, "changeYear"),
8569 showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
8570 html = "<div class='ui-datepicker-title'>",
8571 monthHtml = "";
8572
8573 // month selection
8574 if (secondary || !changeMonth) {
8575 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
8576 } else {
8577 inMinYear = (minDate && minDate.getFullYear() === drawYear);
8578 inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
8579 monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
8580 for ( month = 0; month < 12; month++) {
8581 if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
8582 monthHtml += "<option value='" + month + "'" +
8583 (month === drawMonth ? " selected='selected'" : "") +
8584 ">" + monthNamesShort[month] + "</option>";
8585 }
8586 }
8587 monthHtml += "</select>";
8588 }
8589
8590 if (!showMonthAfterYear) {
8591 html += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");
8592 }
8593
8594 // year selection
8595 if ( !inst.yearshtml ) {
8596 inst.yearshtml = "";
8597 if (secondary || !changeYear) {
8598 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
8599 } else {
8600 // determine range of years to display
8601 years = this._get(inst, "yearRange").split(":");
8602 thisYear = new Date().getFullYear();
8603 determineYear = function(value) {
8604 var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
8605 (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
8606 parseInt(value, 10)));
8607 return (isNaN(year) ? thisYear : year);
8608 };
8609 year = determineYear(years[0]);
8610 endYear = Math.max(year, determineYear(years[1] || ""));
8611 year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
8612 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
8613 inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
8614 for (; year <= endYear; year++) {
8615 inst.yearshtml += "<option value='" + year + "'" +
8616 (year === drawYear ? " selected='selected'" : "") +
8617 ">" + year + "</option>";
8618 }
8619 inst.yearshtml += "</select>";
8620
8621 html += inst.yearshtml;
8622 inst.yearshtml = null;
8623 }
8624 }
8625
8626 html += this._get(inst, "yearSuffix");
8627 if (showMonthAfterYear) {
8628 html += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;
8629 }
8630 html += "</div>"; // Close datepicker_header
8631 return html;
8632 },
8633
8634 /* Adjust one of the date sub-fields. */
8635 _adjustInstDate: function(inst, offset, period) {
8636 var year = inst.drawYear + (period === "Y" ? offset : 0),
8637 month = inst.drawMonth + (period === "M" ? offset : 0),
8638 day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
8639 date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
8640
8641 inst.selectedDay = date.getDate();
8642 inst.drawMonth = inst.selectedMonth = date.getMonth();
8643 inst.drawYear = inst.selectedYear = date.getFullYear();
8644 if (period === "M" || period === "Y") {
8645 this._notifyChange(inst);
8646 }
8647 },
8648
8649 /* Ensure a date is within any min/max bounds. */
8650 _restrictMinMax: function(inst, date) {
8651 var minDate = this._getMinMaxDate(inst, "min"),
8652 maxDate = this._getMinMaxDate(inst, "max"),
8653 newDate = (minDate && date < minDate ? minDate : date);
8654 return (maxDate && newDate > maxDate ? maxDate : newDate);
8655 },
8656
8657 /* Notify change of month/year. */
8658 _notifyChange: function(inst) {
8659 var onChange = this._get(inst, "onChangeMonthYear");
8660 if (onChange) {
8661 onChange.apply((inst.input ? inst.input[0] : null),
8662 [inst.selectedYear, inst.selectedMonth + 1, inst]);
8663 }
8664 },
8665
8666 /* Determine the number of months to show. */
8667 _getNumberOfMonths: function(inst) {
8668 var numMonths = this._get(inst, "numberOfMonths");
8669 return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
8670 },
8671
8672 /* Determine the current maximum date - ensure no time components are set. */
8673 _getMinMaxDate: function(inst, minMax) {
8674 return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
8675 },
8676
8677 /* Find the number of days in a given month. */
8678 _getDaysInMonth: function(year, month) {
8679 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
8680 },
8681
8682 /* Find the day of the week of the first of a month. */
8683 _getFirstDayOfMonth: function(year, month) {
8684 return new Date(year, month, 1).getDay();
8685 },
8686
8687 /* Determines if we should allow a "next/prev" month display change. */
8688 _canAdjustMonth: function(inst, offset, curYear, curMonth) {
8689 var numMonths = this._getNumberOfMonths(inst),
8690 date = this._daylightSavingAdjust(new Date(curYear,
8691 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
8692
8693 if (offset < 0) {
8694 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
8695 }
8696 return this._isInRange(inst, date);
8697 },
8698
8699 /* Is the given date in the accepted range? */
8700 _isInRange: function(inst, date) {
8701 var yearSplit, currentYear,
8702 minDate = this._getMinMaxDate(inst, "min"),
8703 maxDate = this._getMinMaxDate(inst, "max"),
8704 minYear = null,
8705 maxYear = null,
8706 years = this._get(inst, "yearRange");
8707 if (years){
8708 yearSplit = years.split(":");
8709 currentYear = new Date().getFullYear();
8710 minYear = parseInt(yearSplit[0], 10);
8711 maxYear = parseInt(yearSplit[1], 10);
8712 if ( yearSplit[0].match(/[+\-].*/) ) {
8713 minYear += currentYear;
8714 }
8715 if ( yearSplit[1].match(/[+\-].*/) ) {
8716 maxYear += currentYear;
8717 }
8718 }
8719
8720 return ((!minDate || date.getTime() >= minDate.getTime()) &&
8721 (!maxDate || date.getTime() <= maxDate.getTime()) &&
8722 (!minYear || date.getFullYear() >= minYear) &&
8723 (!maxYear || date.getFullYear() <= maxYear));
8724 },
8725
8726 /* Provide the configuration settings for formatting/parsing. */
8727 _getFormatConfig: function(inst) {
8728 var shortYearCutoff = this._get(inst, "shortYearCutoff");
8729 shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
8730 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
8731 return {shortYearCutoff: shortYearCutoff,
8732 dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
8733 monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
8734 },
8735
8736 /* Format the given date for display. */
8737 _formatDate: function(inst, day, month, year) {
8738 if (!day) {
8739 inst.currentDay = inst.selectedDay;
8740 inst.currentMonth = inst.selectedMonth;
8741 inst.currentYear = inst.selectedYear;
8742 }
8743 var date = (day ? (typeof day === "object" ? day :
8744 this._daylightSavingAdjust(new Date(year, month, day))) :
8745 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
8746 return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
8747 }
8748 });
8749
8750 /*
8751 * Bind hover events for datepicker elements.
8752 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
8753 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
8754 */
8755 function bindHover(dpDiv) {
8756 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
8757 return dpDiv.delegate(selector, "mouseout", function() {
8758 $(this).removeClass("ui-state-hover");
8759 if (this.className.indexOf("ui-datepicker-prev") !== -1) {
8760 $(this).removeClass("ui-datepicker-prev-hover");
8761 }
8762 if (this.className.indexOf("ui-datepicker-next") !== -1) {
8763 $(this).removeClass("ui-datepicker-next-hover");
8764 }
8765 })
8766 .delegate(selector, "mouseover", function(){
8767 if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
8768 $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
8769 $(this).addClass("ui-state-hover");
8770 if (this.className.indexOf("ui-datepicker-prev") !== -1) {
8771 $(this).addClass("ui-datepicker-prev-hover");
8772 }
8773 if (this.className.indexOf("ui-datepicker-next") !== -1) {
8774 $(this).addClass("ui-datepicker-next-hover");
8775 }
8776 }
8777 });
8778 }
8779
8780 /* jQuery extend now ignores nulls! */
8781 function extendRemove(target, props) {
8782 $.extend(target, props);
8783 for (var name in props) {
8784 if (props[name] == null) {
8785 target[name] = props[name];
8786 }
8787 }
8788 return target;
8789 }
8790
8791 /* Invoke the datepicker functionality.
8792 @param options string - a command, optionally followed by additional parameters or
8793 Object - settings for attaching new datepicker functionality
8794 @return jQuery object */
8795 $.fn.datepicker = function(options){
8796
8797 /* Verify an empty collection wasn't passed - Fixes #6976 */
8798 if ( !this.length ) {
8799 return this;
8800 }
8801
8802 /* Initialise the date picker. */
8803 if (!$.datepicker.initialized) {
8804 $(document).mousedown($.datepicker._checkExternalClick);
8805 $.datepicker.initialized = true;
8806 }
8807
8808 /* Append datepicker main container to body if not exist. */
8809 if ($("#"+$.datepicker._mainDivId).length === 0) {
8810 $("body").append($.datepicker.dpDiv);
8811 }
8812
8813 var otherArgs = Array.prototype.slice.call(arguments, 1);
8814 if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
8815 return $.datepicker["_" + options + "Datepicker"].
8816 apply($.datepicker, [this[0]].concat(otherArgs));
8817 }
8818 if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
8819 return $.datepicker["_" + options + "Datepicker"].
8820 apply($.datepicker, [this[0]].concat(otherArgs));
8821 }
8822 return this.each(function() {
8823 typeof options === "string" ?
8824 $.datepicker["_" + options + "Datepicker"].
8825 apply($.datepicker, [this].concat(otherArgs)) :
8826 $.datepicker._attachDatepicker(this, options);
8827 });
8828 };
8829
8830 $.datepicker = new Datepicker(); // singleton instance
8831 $.datepicker.initialized = false;
8832 $.datepicker.uuid = new Date().getTime();
8833 $.datepicker.version = "1.10.3";
8834
8835 })(jQuery);
8836 (function( $, undefined ) {
8837
8838 var sizeRelatedOptions = {
8839 buttons: true,
8840 height: true,
8841 maxHeight: true,
8842 maxWidth: true,
8843 minHeight: true,
8844 minWidth: true,
8845 width: true
8846 },
8847 resizableRelatedOptions = {
8848 maxHeight: true,
8849 maxWidth: true,
8850 minHeight: true,
8851 minWidth: true
8852 };
8853
8854 $.widget( "ui.dialog", {
8855 version: "1.10.3",
8856 options: {
8857 appendTo: "body",
8858 autoOpen: true,
8859 buttons: [],
8860 closeOnEscape: true,
8861 closeText: "close",
8862 dialogClass: "",
8863 draggable: true,
8864 hide: null,
8865 height: "auto",
8866 maxHeight: null,
8867 maxWidth: null,
8868 minHeight: 150,
8869 minWidth: 150,
8870 modal: false,
8871 position: {
8872 my: "center",
8873 at: "center",
8874 of: window,
8875 collision: "fit",
8876 // Ensure the titlebar is always visible
8877 using: function( pos ) {
8878 var topOffset = $( this ).css( pos ).offset().top;
8879 if ( topOffset < 0 ) {
8880 $( this ).css( "top", pos.top - topOffset );
8881 }
8882 }
8883 },
8884 resizable: true,
8885 show: null,
8886 title: null,
8887 width: 300,
8888
8889 // callbacks
8890 beforeClose: null,
8891 close: null,
8892 drag: null,
8893 dragStart: null,
8894 dragStop: null,
8895 focus: null,
8896 open: null,
8897 resize: null,
8898 resizeStart: null,
8899 resizeStop: null
8900 },
8901
8902 _create: function() {
8903 this.originalCss = {
8904 display: this.element[0].style.display,
8905 width: this.element[0].style.width,
8906 minHeight: this.element[0].style.minHeight,
8907 maxHeight: this.element[0].style.maxHeight,
8908 height: this.element[0].style.height
8909 };
8910 this.originalPosition = {
8911 parent: this.element.parent(),
8912 index: this.element.parent().children().index( this.element )
8913 };
8914 this.originalTitle = this.element.attr("title");
8915 this.options.title = this.options.title || this.originalTitle;
8916
8917 this._createWrapper();
8918
8919 this.element
8920 .show()
8921 .removeAttr("title")
8922 .addClass("ui-dialog-content ui-widget-content")
8923 .appendTo( this.uiDialog );
8924
8925 this._createTitlebar();
8926 this._createButtonPane();
8927
8928 if ( this.options.draggable && $.fn.draggable ) {
8929 this._makeDraggable();
8930 }
8931 if ( this.options.resizable && $.fn.resizable ) {
8932 this._makeResizable();
8933 }
8934
8935 this._isOpen = false;
8936 },
8937
8938 _init: function() {
8939 if ( this.options.autoOpen ) {
8940 this.open();
8941 }
8942 },
8943
8944 _appendTo: function() {
8945 var element = this.options.appendTo;
8946 if ( element && (element.jquery || element.nodeType) ) {
8947 return $( element );
8948 }
8949 return this.document.find( element || "body" ).eq( 0 );
8950 },
8951
8952 _destroy: function() {
8953 var next,
8954 originalPosition = this.originalPosition;
8955
8956 this._destroyOverlay();
8957
8958 this.element
8959 .removeUniqueId()
8960 .removeClass("ui-dialog-content ui-widget-content")
8961 .css( this.originalCss )
8962 // Without detaching first, the following becomes really slow
8963 .detach();
8964
8965 this.uiDialog.stop( true, true ).remove();
8966
8967 if ( this.originalTitle ) {
8968 this.element.attr( "title", this.originalTitle );
8969 }
8970
8971 next = originalPosition.parent.children().eq( originalPosition.index );
8972 // Don't try to place the dialog next to itself (#8613)
8973 if ( next.length && next[0] !== this.element[0] ) {
8974 next.before( this.element );
8975 } else {
8976 originalPosition.parent.append( this.element );
8977 }
8978 },
8979
8980 widget: function() {
8981 return this.uiDialog;
8982 },
8983
8984 disable: $.noop,
8985 enable: $.noop,
8986
8987 close: function( event ) {
8988 var that = this;
8989
8990 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
8991 return;
8992 }
8993
8994 this._isOpen = false;
8995 this._destroyOverlay();
8996
8997 if ( !this.opener.filter(":focusable").focus().length ) {
8998 // Hiding a focused element doesn't trigger blur in WebKit
8999 // so in case we have nothing to focus on, explicitly blur the active element
9000 // https://bugs.webkit.org/show_bug.cgi?id=47182
9001 $( this.document[0].activeElement ).blur();
9002 }
9003
9004 this._hide( this.uiDialog, this.options.hide, function() {
9005 that._trigger( "close", event );
9006 });
9007 },
9008
9009 isOpen: function() {
9010 return this._isOpen;
9011 },
9012
9013 moveToTop: function() {
9014 this._moveToTop();
9015 },
9016
9017 _moveToTop: function( event, silent ) {
9018 var moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length;
9019 if ( moved && !silent ) {
9020 this._trigger( "focus", event );
9021 }
9022 return moved;
9023 },
9024
9025 open: function() {
9026 var that = this;
9027 if ( this._isOpen ) {
9028 if ( this._moveToTop() ) {
9029 this._focusTabbable();
9030 }
9031 return;
9032 }
9033
9034 this._isOpen = true;
9035 this.opener = $( this.document[0].activeElement );
9036
9037 this._size();
9038 this._position();
9039 this._createOverlay();
9040 this._moveToTop( null, true );
9041 this._show( this.uiDialog, this.options.show, function() {
9042 that._focusTabbable();
9043 that._trigger("focus");
9044 });
9045
9046 this._trigger("open");
9047 },
9048
9049 _focusTabbable: function() {
9050 // Set focus to the first match:
9051 // 1. First element inside the dialog matching [autofocus]
9052 // 2. Tabbable element inside the content element
9053 // 3. Tabbable element inside the buttonpane
9054 // 4. The close button
9055 // 5. The dialog itself
9056 var hasFocus = this.element.find("[autofocus]");
9057 if ( !hasFocus.length ) {
9058 hasFocus = this.element.find(":tabbable");
9059 }
9060 if ( !hasFocus.length ) {
9061 hasFocus = this.uiDialogButtonPane.find(":tabbable");
9062 }
9063 if ( !hasFocus.length ) {
9064 hasFocus = this.uiDialogTitlebarClose.filter(":tabbable");
9065 }
9066 if ( !hasFocus.length ) {
9067 hasFocus = this.uiDialog;
9068 }
9069 hasFocus.eq( 0 ).focus();
9070 },
9071
9072 _keepFocus: function( event ) {
9073 function checkFocus() {
9074 var activeElement = this.document[0].activeElement,
9075 isActive = this.uiDialog[0] === activeElement ||
9076 $.contains( this.uiDialog[0], activeElement );
9077 if ( !isActive ) {
9078 this._focusTabbable();
9079 }
9080 }
9081 event.preventDefault();
9082 checkFocus.call( this );
9083 // support: IE
9084 // IE <= 8 doesn't prevent moving focus even with event.preventDefault()
9085 // so we check again later
9086 this._delay( checkFocus );
9087 },
9088
9089 _createWrapper: function() {
9090 this.uiDialog = $("<div>")
9091 .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
9092 this.options.dialogClass )
9093 .hide()
9094 .attr({
9095 // Setting tabIndex makes the div focusable
9096 tabIndex: -1,
9097 role: "dialog"
9098 })
9099 .appendTo( this._appendTo() );
9100
9101 this._on( this.uiDialog, {
9102 keydown: function( event ) {
9103 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
9104 event.keyCode === $.ui.keyCode.ESCAPE ) {
9105 event.preventDefault();
9106 this.close( event );
9107 return;
9108 }
9109
9110 // prevent tabbing out of dialogs
9111 if ( event.keyCode !== $.ui.keyCode.TAB ) {
9112 return;
9113 }
9114 var tabbables = this.uiDialog.find(":tabbable"),
9115 first = tabbables.filter(":first"),
9116 last = tabbables.filter(":last");
9117
9118 if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
9119 first.focus( 1 );
9120 event.preventDefault();
9121 } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
9122 last.focus( 1 );
9123 event.preventDefault();
9124 }
9125 },
9126 mousedown: function( event ) {
9127 if ( this._moveToTop( event ) ) {
9128 this._focusTabbable();
9129 }
9130 }
9131 });
9132
9133 // We assume that any existing aria-describedby attribute means
9134 // that the dialog content is marked up properly
9135 // otherwise we brute force the content as the description
9136 if ( !this.element.find("[aria-describedby]").length ) {
9137 this.uiDialog.attr({
9138 "aria-describedby": this.element.uniqueId().attr("id")
9139 });
9140 }
9141 },
9142
9143 _createTitlebar: function() {
9144 var uiDialogTitle;
9145
9146 this.uiDialogTitlebar = $("<div>")
9147 .addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix")
9148 .prependTo( this.uiDialog );
9149 this._on( this.uiDialogTitlebar, {
9150 mousedown: function( event ) {
9151 // Don't prevent click on close button (#8838)
9152 // Focusing a dialog that is partially scrolled out of view
9153 // causes the browser to scroll it into view, preventing the click event
9154 if ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) {
9155 // Dialog isn't getting focus when dragging (#8063)
9156 this.uiDialog.focus();
9157 }
9158 }
9159 });
9160
9161 this.uiDialogTitlebarClose = $("<button></button>")
9162 .button({
9163 label: this.options.closeText,
9164 icons: {
9165 primary: "ui-icon-closethick"
9166 },
9167 text: false
9168 })
9169 .addClass("ui-dialog-titlebar-close")
9170 .appendTo( this.uiDialogTitlebar );
9171 this._on( this.uiDialogTitlebarClose, {
9172 click: function( event ) {
9173 event.preventDefault();
9174 this.close( event );
9175 }
9176 });
9177
9178 uiDialogTitle = $("<span>")
9179 .uniqueId()
9180 .addClass("ui-dialog-title")
9181 .prependTo( this.uiDialogTitlebar );
9182 this._title( uiDialogTitle );
9183
9184 this.uiDialog.attr({
9185 "aria-labelledby": uiDialogTitle.attr("id")
9186 });
9187 },
9188
9189 _title: function( title ) {
9190 if ( !this.options.title ) {
9191 title.html("&#160;");
9192 }
9193 title.text( this.options.title );
9194 },
9195
9196 _createButtonPane: function() {
9197 this.uiDialogButtonPane = $("<div>")
9198 .addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");
9199
9200 this.uiButtonSet = $("<div>")
9201 .addClass("ui-dialog-buttonset")
9202 .appendTo( this.uiDialogButtonPane );
9203
9204 this._createButtons();
9205 },
9206
9207 _createButtons: function() {
9208 var that = this,
9209 buttons = this.options.buttons;
9210
9211 // if we already have a button pane, remove it
9212 this.uiDialogButtonPane.remove();
9213 this.uiButtonSet.empty();
9214
9215 if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {
9216 this.uiDialog.removeClass("ui-dialog-buttons");
9217 return;
9218 }
9219
9220 $.each( buttons, function( name, props ) {
9221 var click, buttonOptions;
9222 props = $.isFunction( props ) ?
9223 { click: props, text: name } :
9224 props;
9225 // Default to a non-submitting button
9226 props = $.extend( { type: "button" }, props );
9227 // Change the context for the click callback to be the main element
9228 click = props.click;
9229 props.click = function() {
9230 click.apply( that.element[0], arguments );
9231 };
9232 buttonOptions = {
9233 icons: props.icons,
9234 text: props.showText
9235 };
9236 delete props.icons;
9237 delete props.showText;
9238 $( "<button></button>", props )
9239 .button( buttonOptions )
9240 .appendTo( that.uiButtonSet );
9241 });
9242 this.uiDialog.addClass("ui-dialog-buttons");
9243 this.uiDialogButtonPane.appendTo( this.uiDialog );
9244 },
9245
9246 _makeDraggable: function() {
9247 var that = this,
9248 options = this.options;
9249
9250 function filteredUi( ui ) {
9251 return {
9252 position: ui.position,
9253 offset: ui.offset
9254 };
9255 }
9256
9257 this.uiDialog.draggable({
9258 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
9259 handle: ".ui-dialog-titlebar",
9260 containment: "document",
9261 start: function( event, ui ) {
9262 $( this ).addClass("ui-dialog-dragging");
9263 that._blockFrames();
9264 that._trigger( "dragStart", event, filteredUi( ui ) );
9265 },
9266 drag: function( event, ui ) {
9267 that._trigger( "drag", event, filteredUi( ui ) );
9268 },
9269 stop: function( event, ui ) {
9270 options.position = [
9271 ui.position.left - that.document.scrollLeft(),
9272 ui.position.top - that.document.scrollTop()
9273 ];
9274 $( this ).removeClass("ui-dialog-dragging");
9275 that._unblockFrames();
9276 that._trigger( "dragStop", event, filteredUi( ui ) );
9277 }
9278 });
9279 },
9280
9281 _makeResizable: function() {
9282 var that = this,
9283 options = this.options,
9284 handles = options.resizable,
9285 // .ui-resizable has position: relative defined in the stylesheet
9286 // but dialogs have to use absolute or fixed positioning
9287 position = this.uiDialog.css("position"),
9288 resizeHandles = typeof handles === "string" ?
9289 handles :
9290 "n,e,s,w,se,sw,ne,nw";
9291
9292 function filteredUi( ui ) {
9293 return {
9294 originalPosition: ui.originalPosition,
9295 originalSize: ui.originalSize,
9296 position: ui.position,
9297 size: ui.size
9298 };
9299 }
9300
9301 this.uiDialog.resizable({
9302 cancel: ".ui-dialog-content",
9303 containment: "document",
9304 alsoResize: this.element,
9305 maxWidth: options.maxWidth,
9306 maxHeight: options.maxHeight,
9307 minWidth: options.minWidth,
9308 minHeight: this._minHeight(),
9309 handles: resizeHandles,
9310 start: function( event, ui ) {
9311 $( this ).addClass("ui-dialog-resizing");
9312 that._blockFrames();
9313 that._trigger( "resizeStart", event, filteredUi( ui ) );
9314 },
9315 resize: function( event, ui ) {
9316 that._trigger( "resize", event, filteredUi( ui ) );
9317 },
9318 stop: function( event, ui ) {
9319 options.height = $( this ).height();
9320 options.width = $( this ).width();
9321 $( this ).removeClass("ui-dialog-resizing");
9322 that._unblockFrames();
9323 that._trigger( "resizeStop", event, filteredUi( ui ) );
9324 }
9325 })
9326 .css( "position", position );
9327 },
9328
9329 _minHeight: function() {
9330 var options = this.options;
9331
9332 return options.height === "auto" ?
9333 options.minHeight :
9334 Math.min( options.minHeight, options.height );
9335 },
9336
9337 _position: function() {
9338 // Need to show the dialog to get the actual offset in the position plugin
9339 var isVisible = this.uiDialog.is(":visible");
9340 if ( !isVisible ) {
9341 this.uiDialog.show();
9342 }
9343 this.uiDialog.position( this.options.position );
9344 if ( !isVisible ) {
9345 this.uiDialog.hide();
9346 }
9347 },
9348
9349 _setOptions: function( options ) {
9350 var that = this,
9351 resize = false,
9352 resizableOptions = {};
9353
9354 $.each( options, function( key, value ) {
9355 that._setOption( key, value );
9356
9357 if ( key in sizeRelatedOptions ) {
9358 resize = true;
9359 }
9360 if ( key in resizableRelatedOptions ) {
9361 resizableOptions[ key ] = value;
9362 }
9363 });
9364
9365 if ( resize ) {
9366 this._size();
9367 this._position();
9368 }
9369 if ( this.uiDialog.is(":data(ui-resizable)") ) {
9370 this.uiDialog.resizable( "option", resizableOptions );
9371 }
9372 },
9373
9374 _setOption: function( key, value ) {
9375 /*jshint maxcomplexity:15*/
9376 var isDraggable, isResizable,
9377 uiDialog = this.uiDialog;
9378
9379 if ( key === "dialogClass" ) {
9380 uiDialog
9381 .removeClass( this.options.dialogClass )
9382 .addClass( value );
9383 }
9384
9385 if ( key === "disabled" ) {
9386 return;
9387 }
9388
9389 this._super( key, value );
9390
9391 if ( key === "appendTo" ) {
9392 this.uiDialog.appendTo( this._appendTo() );
9393 }
9394
9395 if ( key === "buttons" ) {
9396 this._createButtons();
9397 }
9398
9399 if ( key === "closeText" ) {
9400 this.uiDialogTitlebarClose.button({
9401 // Ensure that we always pass a string
9402 label: "" + value
9403 });
9404 }
9405
9406 if ( key === "draggable" ) {
9407 isDraggable = uiDialog.is(":data(ui-draggable)");
9408 if ( isDraggable && !value ) {
9409 uiDialog.draggable("destroy");
9410 }
9411
9412 if ( !isDraggable && value ) {
9413 this._makeDraggable();
9414 }
9415 }
9416
9417 if ( key === "position" ) {
9418 this._position();
9419 }
9420
9421 if ( key === "resizable" ) {
9422 // currently resizable, becoming non-resizable
9423 isResizable = uiDialog.is(":data(ui-resizable)");
9424 if ( isResizable && !value ) {
9425 uiDialog.resizable("destroy");
9426 }
9427
9428 // currently resizable, changing handles
9429 if ( isResizable && typeof value === "string" ) {
9430 uiDialog.resizable( "option", "handles", value );
9431 }
9432
9433 // currently non-resizable, becoming resizable
9434 if ( !isResizable && value !== false ) {
9435 this._makeResizable();
9436 }
9437 }
9438
9439 if ( key === "title" ) {
9440 this._title( this.uiDialogTitlebar.find(".ui-dialog-title") );
9441 }
9442 },
9443
9444 _size: function() {
9445 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
9446 // divs will both have width and height set, so we need to reset them
9447 var nonContentHeight, minContentHeight, maxContentHeight,
9448 options = this.options;
9449
9450 // Reset content sizing
9451 this.element.show().css({
9452 width: "auto",
9453 minHeight: 0,
9454 maxHeight: "none",
9455 height: 0
9456 });
9457
9458 if ( options.minWidth > options.width ) {
9459 options.width = options.minWidth;
9460 }
9461
9462 // reset wrapper sizing
9463 // determine the height of all the non-content elements
9464 nonContentHeight = this.uiDialog.css({
9465 height: "auto",
9466 width: options.width
9467 })
9468 .outerHeight();
9469 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
9470 maxContentHeight = typeof options.maxHeight === "number" ?
9471 Math.max( 0, options.maxHeight - nonContentHeight ) :
9472 "none";
9473
9474 if ( options.height === "auto" ) {
9475 this.element.css({
9476 minHeight: minContentHeight,
9477 maxHeight: maxContentHeight,
9478 height: "auto"
9479 });
9480 } else {
9481 this.element.height( Math.max( 0, options.height - nonContentHeight ) );
9482 }
9483
9484 if (this.uiDialog.is(":data(ui-resizable)") ) {
9485 this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
9486 }
9487 },
9488
9489 _blockFrames: function() {
9490 this.iframeBlocks = this.document.find( "iframe" ).map(function() {
9491 var iframe = $( this );
9492
9493 return $( "<div>" )
9494 .css({
9495 position: "absolute",
9496 width: iframe.outerWidth(),
9497 height: iframe.outerHeight()
9498 })
9499 .appendTo( iframe.parent() )
9500 .offset( iframe.offset() )[0];
9501 });
9502 },
9503
9504 _unblockFrames: function() {
9505 if ( this.iframeBlocks ) {
9506 this.iframeBlocks.remove();
9507 delete this.iframeBlocks;
9508 }
9509 },
9510
9511 _allowInteraction: function( event ) {
9512 if ( $( event.target ).closest(".ui-dialog").length ) {
9513 return true;
9514 }
9515
9516 // TODO: Remove hack when datepicker implements
9517 // the .ui-front logic (#8989)
9518 return !!$( event.target ).closest(".ui-datepicker").length;
9519 },
9520
9521 _createOverlay: function() {
9522 if ( !this.options.modal ) {
9523 return;
9524 }
9525
9526 var that = this,
9527 widgetFullName = this.widgetFullName;
9528 if ( !$.ui.dialog.overlayInstances ) {
9529 // Prevent use of anchors and inputs.
9530 // We use a delay in case the overlay is created from an
9531 // event that we're going to be cancelling. (#2804)
9532 this._delay(function() {
9533 // Handle .dialog().dialog("close") (#4065)
9534 if ( $.ui.dialog.overlayInstances ) {
9535 this.document.bind( "focusin.dialog", function( event ) {
9536 if ( !that._allowInteraction( event ) ) {
9537 event.preventDefault();
9538 $(".ui-dialog:visible:last .ui-dialog-content")
9539 .data( widgetFullName )._focusTabbable();
9540 }
9541 });
9542 }
9543 });
9544 }
9545
9546 this.overlay = $("<div>")
9547 .addClass("ui-widget-overlay ui-front")
9548 .appendTo( this._appendTo() );
9549 this._on( this.overlay, {
9550 mousedown: "_keepFocus"
9551 });
9552 $.ui.dialog.overlayInstances++;
9553 },
9554
9555 _destroyOverlay: function() {
9556 if ( !this.options.modal ) {
9557 return;
9558 }
9559
9560 if ( this.overlay ) {
9561 $.ui.dialog.overlayInstances--;
9562
9563 if ( !$.ui.dialog.overlayInstances ) {
9564 this.document.unbind( "focusin.dialog" );
9565 }
9566 this.overlay.remove();
9567 this.overlay = null;
9568 }
9569 }
9570 });
9571
9572 $.ui.dialog.overlayInstances = 0;
9573
9574 // DEPRECATED
9575 if ( $.uiBackCompat !== false ) {
9576 // position option with array notation
9577 // just override with old implementation
9578 $.widget( "ui.dialog", $.ui.dialog, {
9579 _position: function() {
9580 var position = this.options.position,
9581 myAt = [],
9582 offset = [ 0, 0 ],
9583 isVisible;
9584
9585 if ( position ) {
9586 if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) {
9587 myAt = position.split ? position.split(" ") : [ position[0], position[1] ];
9588 if ( myAt.length === 1 ) {
9589 myAt[1] = myAt[0];
9590 }
9591
9592 $.each( [ "left", "top" ], function( i, offsetPosition ) {
9593 if ( +myAt[ i ] === myAt[ i ] ) {
9594 offset[ i ] = myAt[ i ];
9595 myAt[ i ] = offsetPosition;
9596 }
9597 });
9598
9599 position = {
9600 my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " +
9601 myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]),
9602 at: myAt.join(" ")
9603 };
9604 }
9605
9606 position = $.extend( {}, $.ui.dialog.prototype.options.position, position );
9607 } else {
9608 position = $.ui.dialog.prototype.options.position;
9609 }
9610
9611 // need to show the dialog to get the actual offset in the position plugin
9612 isVisible = this.uiDialog.is(":visible");
9613 if ( !isVisible ) {
9614 this.uiDialog.show();
9615 }
9616 this.uiDialog.position( position );
9617 if ( !isVisible ) {
9618 this.uiDialog.hide();
9619 }
9620 }
9621 });
9622 }
9623
9624 }( jQuery ) );
9625 (function( $, undefined ) {
9626
9627 $.widget( "ui.menu", {
9628 version: "1.10.3",
9629 defaultElement: "<ul>",
9630 delay: 300,
9631 options: {
9632 icons: {
9633 submenu: "ui-icon-carat-1-e"
9634 },
9635 menus: "ul",
9636 position: {
9637 my: "left top",
9638 at: "right top"
9639 },
9640 role: "menu",
9641
9642 // callbacks
9643 blur: null,
9644 focus: null,
9645 select: null
9646 },
9647
9648 _create: function() {
9649 this.activeMenu = this.element;
9650 // flag used to prevent firing of the click handler
9651 // as the event bubbles up through nested menus
9652 this.mouseHandled = false;
9653 this.element
9654 .uniqueId()
9655 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
9656 .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
9657 .attr({
9658 role: this.options.role,
9659 tabIndex: 0
9660 })
9661 // need to catch all clicks on disabled menu
9662 // not possible through _on
9663 .bind( "click" + this.eventNamespace, $.proxy(function( event ) {
9664 if ( this.options.disabled ) {
9665 event.preventDefault();
9666 }
9667 }, this ));
9668
9669 if ( this.options.disabled ) {
9670 this.element
9671 .addClass( "ui-state-disabled" )
9672 .attr( "aria-disabled", "true" );
9673 }
9674
9675 this._on({
9676 // Prevent focus from sticking to links inside menu after clicking
9677 // them (focus should always stay on UL during navigation).
9678 "mousedown .ui-menu-item > a": function( event ) {
9679 event.preventDefault();
9680 },
9681 "click .ui-state-disabled > a": function( event ) {
9682 event.preventDefault();
9683 },
9684 "click .ui-menu-item:has(a)": function( event ) {
9685 var target = $( event.target ).closest( ".ui-menu-item" );
9686 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
9687 this.mouseHandled = true;
9688
9689 this.select( event );
9690 // Open submenu on click
9691 if ( target.has( ".ui-menu" ).length ) {
9692 this.expand( event );
9693 } else if ( !this.element.is( ":focus" ) ) {
9694 // Redirect focus to the menu
9695 this.element.trigger( "focus", [ true ] );
9696
9697 // If the active item is on the top level, let it stay active.
9698 // Otherwise, blur the active item since it is no longer visible.
9699 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
9700 clearTimeout( this.timer );
9701 }
9702 }
9703 }
9704 },
9705 "mouseenter .ui-menu-item": function( event ) {
9706 var target = $( event.currentTarget );
9707 // Remove ui-state-active class from siblings of the newly focused menu item
9708 // to avoid a jump caused by adjacent elements both having a class with a border
9709 target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" );
9710 this.focus( event, target );
9711 },
9712 mouseleave: "collapseAll",
9713 "mouseleave .ui-menu": "collapseAll",
9714 focus: function( event, keepActiveItem ) {
9715 // If there's already an active item, keep it active
9716 // If not, activate the first item
9717 var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 );
9718
9719 if ( !keepActiveItem ) {
9720 this.focus( event, item );
9721 }
9722 },
9723 blur: function( event ) {
9724 this._delay(function() {
9725 if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
9726 this.collapseAll( event );
9727 }
9728 });
9729 },
9730 keydown: "_keydown"
9731 });
9732
9733 this.refresh();
9734
9735 // Clicks outside of a menu collapse any open menus
9736 this._on( this.document, {
9737 click: function( event ) {
9738 if ( !$( event.target ).closest( ".ui-menu" ).length ) {
9739 this.collapseAll( event );
9740 }
9741
9742 // Reset the mouseHandled flag
9743 this.mouseHandled = false;
9744 }
9745 });
9746 },
9747
9748 _destroy: function() {
9749 // Destroy (sub)menus
9750 this.element
9751 .removeAttr( "aria-activedescendant" )
9752 .find( ".ui-menu" ).addBack()
9753 .removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" )
9754 .removeAttr( "role" )
9755 .removeAttr( "tabIndex" )
9756 .removeAttr( "aria-labelledby" )
9757 .removeAttr( "aria-expanded" )
9758 .removeAttr( "aria-hidden" )
9759 .removeAttr( "aria-disabled" )
9760 .removeUniqueId()
9761 .show();
9762
9763 // Destroy menu items
9764 this.element.find( ".ui-menu-item" )
9765 .removeClass( "ui-menu-item" )
9766 .removeAttr( "role" )
9767 .removeAttr( "aria-disabled" )
9768 .children( "a" )
9769 .removeUniqueId()
9770 .removeClass( "ui-corner-all ui-state-hover" )
9771 .removeAttr( "tabIndex" )
9772 .removeAttr( "role" )
9773 .removeAttr( "aria-haspopup" )
9774 .children().each( function() {
9775 var elem = $( this );
9776 if ( elem.data( "ui-menu-submenu-carat" ) ) {
9777 elem.remove();
9778 }
9779 });
9780
9781 // Destroy menu dividers
9782 this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
9783 },
9784
9785 _keydown: function( event ) {
9786 /*jshint maxcomplexity:20*/
9787 var match, prev, character, skip, regex,
9788 preventDefault = true;
9789
9790 function escape( value ) {
9791 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
9792 }
9793
9794 switch ( event.keyCode ) {
9795 case $.ui.keyCode.PAGE_UP:
9796 this.previousPage( event );
9797 break;
9798 case $.ui.keyCode.PAGE_DOWN:
9799 this.nextPage( event );
9800 break;
9801 case $.ui.keyCode.HOME:
9802 this._move( "first", "first", event );
9803 break;
9804 case $.ui.keyCode.END:
9805 this._move( "last", "last", event );
9806 break;
9807 case $.ui.keyCode.UP:
9808 this.previous( event );
9809 break;
9810 case $.ui.keyCode.DOWN:
9811 this.next( event );
9812 break;
9813 case $.ui.keyCode.LEFT:
9814 this.collapse( event );
9815 break;
9816 case $.ui.keyCode.RIGHT:
9817 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
9818 this.expand( event );
9819 }
9820 break;
9821 case $.ui.keyCode.ENTER:
9822 case $.ui.keyCode.SPACE:
9823 this._activate( event );
9824 break;
9825 case $.ui.keyCode.ESCAPE:
9826 this.collapse( event );
9827 break;
9828 default:
9829 preventDefault = false;
9830 prev = this.previousFilter || "";
9831 character = String.fromCharCode( event.keyCode );
9832 skip = false;
9833
9834 clearTimeout( this.filterTimer );
9835
9836 if ( character === prev ) {
9837 skip = true;
9838 } else {
9839 character = prev + character;
9840 }
9841
9842 regex = new RegExp( "^" + escape( character ), "i" );
9843 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
9844 return regex.test( $( this ).children( "a" ).text() );
9845 });
9846 match = skip && match.index( this.active.next() ) !== -1 ?
9847 this.active.nextAll( ".ui-menu-item" ) :
9848 match;
9849
9850 // If no matches on the current filter, reset to the last character pressed
9851 // to move down the menu to the first item that starts with that character
9852 if ( !match.length ) {
9853 character = String.fromCharCode( event.keyCode );
9854 regex = new RegExp( "^" + escape( character ), "i" );
9855 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
9856 return regex.test( $( this ).children( "a" ).text() );
9857 });
9858 }
9859
9860 if ( match.length ) {
9861 this.focus( event, match );
9862 if ( match.length > 1 ) {
9863 this.previousFilter = character;
9864 this.filterTimer = this._delay(function() {
9865 delete this.previousFilter;
9866 }, 1000 );
9867 } else {
9868 delete this.previousFilter;
9869 }
9870 } else {
9871 delete this.previousFilter;
9872 }
9873 }
9874
9875 if ( preventDefault ) {
9876 event.preventDefault();
9877 }
9878 },
9879
9880 _activate: function( event ) {
9881 if ( !this.active.is( ".ui-state-disabled" ) ) {
9882 if ( this.active.children( "a[aria-haspopup='true']" ).length ) {
9883 this.expand( event );
9884 } else {
9885 this.select( event );
9886 }
9887 }
9888 },
9889
9890 refresh: function() {
9891 var menus,
9892 icon = this.options.icons.submenu,
9893 submenus = this.element.find( this.options.menus );
9894
9895 // Initialize nested menus
9896 submenus.filter( ":not(.ui-menu)" )
9897 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
9898 .hide()
9899 .attr({
9900 role: this.options.role,
9901 "aria-hidden": "true",
9902 "aria-expanded": "false"
9903 })
9904 .each(function() {
9905 var menu = $( this ),
9906 item = menu.prev( "a" ),
9907 submenuCarat = $( "<span>" )
9908 .addClass( "ui-menu-icon ui-icon " + icon )
9909 .data( "ui-menu-submenu-carat", true );
9910
9911 item
9912 .attr( "aria-haspopup", "true" )
9913 .prepend( submenuCarat );
9914 menu.attr( "aria-labelledby", item.attr( "id" ) );
9915 });
9916
9917 menus = submenus.add( this.element );
9918
9919 // Don't refresh list items that are already adapted
9920 menus.children( ":not(.ui-menu-item):has(a)" )
9921 .addClass( "ui-menu-item" )
9922 .attr( "role", "presentation" )
9923 .children( "a" )
9924 .uniqueId()
9925 .addClass( "ui-corner-all" )
9926 .attr({
9927 tabIndex: -1,
9928 role: this._itemRole()
9929 });
9930
9931 // Initialize unlinked menu-items containing spaces and/or dashes only as dividers
9932 menus.children( ":not(.ui-menu-item)" ).each(function() {
9933 var item = $( this );
9934 // hyphen, em dash, en dash
9935 if ( !/[^\-\u2014\u2013\s]/.test( item.text() ) ) {
9936 item.addClass( "ui-widget-content ui-menu-divider" );
9937 }
9938 });
9939
9940 // Add aria-disabled attribute to any disabled menu item
9941 menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
9942
9943 // If the active item has been removed, blur the menu
9944 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
9945 this.blur();
9946 }
9947 },
9948
9949 _itemRole: function() {
9950 return {
9951 menu: "menuitem",
9952 listbox: "option"
9953 }[ this.options.role ];
9954 },
9955
9956 _setOption: function( key, value ) {
9957 if ( key === "icons" ) {
9958 this.element.find( ".ui-menu-icon" )
9959 .removeClass( this.options.icons.submenu )
9960 .addClass( value.submenu );
9961 }
9962 this._super( key, value );
9963 },
9964
9965 focus: function( event, item ) {
9966 var nested, focused;
9967 this.blur( event, event && event.type === "focus" );
9968
9969 this._scrollIntoView( item );
9970
9971 this.active = item.first();
9972 focused = this.active.children( "a" ).addClass( "ui-state-focus" );
9973 // Only update aria-activedescendant if there's a role
9974 // otherwise we assume focus is managed elsewhere
9975 if ( this.options.role ) {
9976 this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
9977 }
9978
9979 // Highlight active parent menu item, if any
9980 this.active
9981 .parent()
9982 .closest( ".ui-menu-item" )
9983 .children( "a:first" )
9984 .addClass( "ui-state-active" );
9985
9986 if ( event && event.type === "keydown" ) {
9987 this._close();
9988 } else {
9989 this.timer = this._delay(function() {
9990 this._close();
9991 }, this.delay );
9992 }
9993
9994 nested = item.children( ".ui-menu" );
9995 if ( nested.length && ( /^mouse/.test( event.type ) ) ) {
9996 this._startOpening(nested);
9997 }
9998 this.activeMenu = item.parent();
9999
10000 this._trigger( "focus", event, { item: item } );
10001 },
10002
10003 _scrollIntoView: function( item ) {
10004 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
10005 if ( this._hasScroll() ) {
10006 borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
10007 paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
10008 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
10009 scroll = this.activeMenu.scrollTop();
10010 elementHeight = this.activeMenu.height();
10011 itemHeight = item.height();
10012
10013 if ( offset < 0 ) {
10014 this.activeMenu.scrollTop( scroll + offset );
10015 } else if ( offset + itemHeight > elementHeight ) {
10016 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
10017 }
10018 }
10019 },
10020
10021 blur: function( event, fromFocus ) {
10022 if ( !fromFocus ) {
10023 clearTimeout( this.timer );
10024 }
10025
10026 if ( !this.active ) {
10027 return;
10028 }
10029
10030 this.active.children( "a" ).removeClass( "ui-state-focus" );
10031 this.active = null;
10032
10033 this._trigger( "blur", event, { item: this.active } );
10034 },
10035
10036 _startOpening: function( submenu ) {
10037 clearTimeout( this.timer );
10038
10039 // Don't open if already open fixes a Firefox bug that caused a .5 pixel
10040 // shift in the submenu position when mousing over the carat icon
10041 if ( submenu.attr( "aria-hidden" ) !== "true" ) {
10042 return;
10043 }
10044
10045 this.timer = this._delay(function() {
10046 this._close();
10047 this._open( submenu );
10048 }, this.delay );
10049 },
10050
10051 _open: function( submenu ) {
10052 var position = $.extend({
10053 of: this.active
10054 }, this.options.position );
10055
10056 clearTimeout( this.timer );
10057 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
10058 .hide()
10059 .attr( "aria-hidden", "true" );
10060
10061 submenu
10062 .show()
10063 .removeAttr( "aria-hidden" )
10064 .attr( "aria-expanded", "true" )
10065 .position( position );
10066 },
10067
10068 collapseAll: function( event, all ) {
10069 clearTimeout( this.timer );
10070 this.timer = this._delay(function() {
10071 // If we were passed an event, look for the submenu that contains the event
10072 var currentMenu = all ? this.element :
10073 $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
10074
10075 // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
10076 if ( !currentMenu.length ) {
10077 currentMenu = this.element;
10078 }
10079
10080 this._close( currentMenu );
10081
10082 this.blur( event );
10083 this.activeMenu = currentMenu;
10084 }, this.delay );
10085 },
10086
10087 // With no arguments, closes the currently active menu - if nothing is active
10088 // it closes all menus. If passed an argument, it will search for menus BELOW
10089 _close: function( startMenu ) {
10090 if ( !startMenu ) {
10091 startMenu = this.active ? this.active.parent() : this.element;
10092 }
10093
10094 startMenu
10095 .find( ".ui-menu" )
10096 .hide()
10097 .attr( "aria-hidden", "true" )
10098 .attr( "aria-expanded", "false" )
10099 .end()
10100 .find( "a.ui-state-active" )
10101 .removeClass( "ui-state-active" );
10102 },
10103
10104 collapse: function( event ) {
10105 var newItem = this.active &&
10106 this.active.parent().closest( ".ui-menu-item", this.element );
10107 if ( newItem && newItem.length ) {
10108 this._close();
10109 this.focus( event, newItem );
10110 }
10111 },
10112
10113 expand: function( event ) {
10114 var newItem = this.active &&
10115 this.active
10116 .children( ".ui-menu " )
10117 .children( ".ui-menu-item" )
10118 .first();
10119
10120 if ( newItem && newItem.length ) {
10121 this._open( newItem.parent() );
10122
10123 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
10124 this._delay(function() {
10125 this.focus( event, newItem );
10126 });
10127 }
10128 },
10129
10130 next: function( event ) {
10131 this._move( "next", "first", event );
10132 },
10133
10134 previous: function( event ) {
10135 this._move( "prev", "last", event );
10136 },
10137
10138 isFirstItem: function() {
10139 return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
10140 },
10141
10142 isLastItem: function() {
10143 return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
10144 },
10145
10146 _move: function( direction, filter, event ) {
10147 var next;
10148 if ( this.active ) {
10149 if ( direction === "first" || direction === "last" ) {
10150 next = this.active
10151 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
10152 .eq( -1 );
10153 } else {
10154 next = this.active
10155 [ direction + "All" ]( ".ui-menu-item" )
10156 .eq( 0 );
10157 }
10158 }
10159 if ( !next || !next.length || !this.active ) {
10160 next = this.activeMenu.children( ".ui-menu-item" )[ filter ]();
10161 }
10162
10163 this.focus( event, next );
10164 },
10165
10166 nextPage: function( event ) {
10167 var item, base, height;
10168
10169 if ( !this.active ) {
10170 this.next( event );
10171 return;
10172 }
10173 if ( this.isLastItem() ) {
10174 return;
10175 }
10176 if ( this._hasScroll() ) {
10177 base = this.active.offset().top;
10178 height = this.element.height();
10179 this.active.nextAll( ".ui-menu-item" ).each(function() {
10180 item = $( this );
10181 return item.offset().top - base - height < 0;
10182 });
10183
10184 this.focus( event, item );
10185 } else {
10186 this.focus( event, this.activeMenu.children( ".ui-menu-item" )
10187 [ !this.active ? "first" : "last" ]() );
10188 }
10189 },
10190
10191 previousPage: function( event ) {
10192 var item, base, height;
10193 if ( !this.active ) {
10194 this.next( event );
10195 return;
10196 }
10197 if ( this.isFirstItem() ) {
10198 return;
10199 }
10200 if ( this._hasScroll() ) {
10201 base = this.active.offset().top;
10202 height = this.element.height();
10203 this.active.prevAll( ".ui-menu-item" ).each(function() {
10204 item = $( this );
10205 return item.offset().top - base + height > 0;
10206 });
10207
10208 this.focus( event, item );
10209 } else {
10210 this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() );
10211 }
10212 },
10213
10214 _hasScroll: function() {
10215 return this.element.outerHeight() < this.element.prop( "scrollHeight" );
10216 },
10217
10218 select: function( event ) {
10219 // TODO: It should never be possible to not have an active item at this
10220 // point, but the tests don't trigger mouseenter before click.
10221 this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
10222 var ui = { item: this.active };
10223 if ( !this.active.has( ".ui-menu" ).length ) {
10224 this.collapseAll( event, true );
10225 }
10226 this._trigger( "select", event, ui );
10227 }
10228 });
10229
10230 }( jQuery ));
10231 (function( $, undefined ) {
10232
10233 $.widget( "ui.progressbar", {
10234 version: "1.10.3",
10235 options: {
10236 max: 100,
10237 value: 0,
10238
10239 change: null,
10240 complete: null
10241 },
10242
10243 min: 0,
10244
10245 _create: function() {
10246 // Constrain initial value
10247 this.oldValue = this.options.value = this._constrainedValue();
10248
10249 this.element
10250 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
10251 .attr({
10252 // Only set static values, aria-valuenow and aria-valuemax are
10253 // set inside _refreshValue()
10254 role: "progressbar",
10255 "aria-valuemin": this.min
10256 });
10257
10258 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
10259 .appendTo( this.element );
10260
10261 this._refreshValue();
10262 },
10263
10264 _destroy: function() {
10265 this.element
10266 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
10267 .removeAttr( "role" )
10268 .removeAttr( "aria-valuemin" )
10269 .removeAttr( "aria-valuemax" )
10270 .removeAttr( "aria-valuenow" );
10271
10272 this.valueDiv.remove();
10273 },
10274
10275 value: function( newValue ) {
10276 if ( newValue === undefined ) {
10277 return this.options.value;
10278 }
10279
10280 this.options.value = this._constrainedValue( newValue );
10281 this._refreshValue();
10282 },
10283
10284 _constrainedValue: function( newValue ) {
10285 if ( newValue === undefined ) {
10286 newValue = this.options.value;
10287 }
10288
10289 this.indeterminate = newValue === false;
10290
10291 // sanitize value
10292 if ( typeof newValue !== "number" ) {
10293 newValue = 0;
10294 }
10295
10296 return this.indeterminate ? false :
10297 Math.min( this.options.max, Math.max( this.min, newValue ) );
10298 },
10299
10300 _setOptions: function( options ) {
10301 // Ensure "value" option is set after other values (like max)
10302 var value = options.value;
10303 delete options.value;
10304
10305 this._super( options );
10306
10307 this.options.value = this._constrainedValue( value );
10308 this._refreshValue();
10309 },
10310
10311 _setOption: function( key, value ) {
10312 if ( key === "max" ) {
10313 // Don't allow a max less than min
10314 value = Math.max( this.min, value );
10315 }
10316
10317 this._super( key, value );
10318 },
10319
10320 _percentage: function() {
10321 return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
10322 },
10323
10324 _refreshValue: function() {
10325 var value = this.options.value,
10326 percentage = this._percentage();
10327
10328 this.valueDiv
10329 .toggle( this.indeterminate || value > this.min )
10330 .toggleClass( "ui-corner-right", value === this.options.max )
10331 .width( percentage.toFixed(0) + "%" );
10332
10333 this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate );
10334
10335 if ( this.indeterminate ) {
10336 this.element.removeAttr( "aria-valuenow" );
10337 if ( !this.overlayDiv ) {
10338 this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv );
10339 }
10340 } else {
10341 this.element.attr({
10342 "aria-valuemax": this.options.max,
10343 "aria-valuenow": value
10344 });
10345 if ( this.overlayDiv ) {
10346 this.overlayDiv.remove();
10347 this.overlayDiv = null;
10348 }
10349 }
10350
10351 if ( this.oldValue !== value ) {
10352 this.oldValue = value;
10353 this._trigger( "change" );
10354 }
10355 if ( value === this.options.max ) {
10356 this._trigger( "complete" );
10357 }
10358 }
10359 });
10360
10361 })( jQuery );
10362 (function( $, undefined ) {
10363
10364 // number of pages in a slider
10365 // (how many times can you page up/down to go through the whole range)
10366 var numPages = 5;
10367
10368 $.widget( "ui.slider", $.ui.mouse, {
10369 version: "1.10.3",
10370 widgetEventPrefix: "slide",
10371
10372 options: {
10373 animate: false,
10374 distance: 0,
10375 max: 100,
10376 min: 0,
10377 orientation: "horizontal",
10378 range: false,
10379 step: 1,
10380 value: 0,
10381 values: null,
10382
10383 // callbacks
10384 change: null,
10385 slide: null,
10386 start: null,
10387 stop: null
10388 },
10389
10390 _create: function() {
10391 this._keySliding = false;
10392 this._mouseSliding = false;
10393 this._animateOff = true;
10394 this._handleIndex = null;
10395 this._detectOrientation();
10396 this._mouseInit();
10397
10398 this.element
10399 .addClass( "ui-slider" +
10400 " ui-slider-" + this.orientation +
10401 " ui-widget" +
10402 " ui-widget-content" +
10403 " ui-corner-all");
10404
10405 this._refresh();
10406 this._setOption( "disabled", this.options.disabled );
10407
10408 this._animateOff = false;
10409 },
10410
10411 _refresh: function() {
10412 this._createRange();
10413 this._createHandles();
10414 this._setupEvents();
10415 this._refreshValue();
10416 },
10417
10418 _createHandles: function() {
10419 var i, handleCount,
10420 options = this.options,
10421 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
10422 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
10423 handles = [];
10424
10425 handleCount = ( options.values && options.values.length ) || 1;
10426
10427 if ( existingHandles.length > handleCount ) {
10428 existingHandles.slice( handleCount ).remove();
10429 existingHandles = existingHandles.slice( 0, handleCount );
10430 }
10431
10432 for ( i = existingHandles.length; i < handleCount; i++ ) {
10433 handles.push( handle );
10434 }
10435
10436 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
10437
10438 this.handle = this.handles.eq( 0 );
10439
10440 this.handles.each(function( i ) {
10441 $( this ).data( "ui-slider-handle-index", i );
10442 });
10443 },
10444
10445 _createRange: function() {
10446 var options = this.options,
10447 classes = "";
10448
10449 if ( options.range ) {
10450 if ( options.range === true ) {
10451 if ( !options.values ) {
10452 options.values = [ this._valueMin(), this._valueMin() ];
10453 } else if ( options.values.length && options.values.length !== 2 ) {
10454 options.values = [ options.values[0], options.values[0] ];
10455 } else if ( $.isArray( options.values ) ) {
10456 options.values = options.values.slice(0);
10457 }
10458 }
10459
10460 if ( !this.range || !this.range.length ) {
10461 this.range = $( "<div></div>" )
10462 .appendTo( this.element );
10463
10464 classes = "ui-slider-range" +
10465 // note: this isn't the most fittingly semantic framework class for this element,
10466 // but worked best visually with a variety of themes
10467 " ui-widget-header ui-corner-all";
10468 } else {
10469 this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
10470 // Handle range switching from true to min/max
10471 .css({
10472 "left": "",
10473 "bottom": ""
10474 });
10475 }
10476
10477 this.range.addClass( classes +
10478 ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
10479 } else {
10480 this.range = $([]);
10481 }
10482 },
10483
10484 _setupEvents: function() {
10485 var elements = this.handles.add( this.range ).filter( "a" );
10486 this._off( elements );
10487 this._on( elements, this._handleEvents );
10488 this._hoverable( elements );
10489 this._focusable( elements );
10490 },
10491
10492 _destroy: function() {
10493 this.handles.remove();
10494 this.range.remove();
10495
10496 this.element
10497 .removeClass( "ui-slider" +
10498 " ui-slider-horizontal" +
10499 " ui-slider-vertical" +
10500 " ui-widget" +
10501 " ui-widget-content" +
10502 " ui-corner-all" );
10503
10504 this._mouseDestroy();
10505 },
10506
10507 _mouseCapture: function( event ) {
10508 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
10509 that = this,
10510 o = this.options;
10511
10512 if ( o.disabled ) {
10513 return false;
10514 }
10515
10516 this.elementSize = {
10517 width: this.element.outerWidth(),
10518 height: this.element.outerHeight()
10519 };
10520 this.elementOffset = this.element.offset();
10521
10522 position = { x: event.pageX, y: event.pageY };
10523 normValue = this._normValueFromMouse( position );
10524 distance = this._valueMax() - this._valueMin() + 1;
10525 this.handles.each(function( i ) {
10526 var thisDistance = Math.abs( normValue - that.values(i) );
10527 if (( distance > thisDistance ) ||
10528 ( distance === thisDistance &&
10529 (i === that._lastChangedValue || that.values(i) === o.min ))) {
10530 distance = thisDistance;
10531 closestHandle = $( this );
10532 index = i;
10533 }
10534 });
10535
10536 allowed = this._start( event, index );
10537 if ( allowed === false ) {
10538 return false;
10539 }
10540 this._mouseSliding = true;
10541
10542 this._handleIndex = index;
10543
10544 closestHandle
10545 .addClass( "ui-state-active" )
10546 .focus();
10547
10548 offset = closestHandle.offset();
10549 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
10550 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
10551 left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
10552 top: event.pageY - offset.top -
10553 ( closestHandle.height() / 2 ) -
10554 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
10555 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
10556 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
10557 };
10558
10559 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
10560 this._slide( event, index, normValue );
10561 }
10562 this._animateOff = true;
10563 return true;
10564 },
10565
10566 _mouseStart: function() {
10567 return true;
10568 },
10569
10570 _mouseDrag: function( event ) {
10571 var position = { x: event.pageX, y: event.pageY },
10572 normValue = this._normValueFromMouse( position );
10573
10574 this._slide( event, this._handleIndex, normValue );
10575
10576 return false;
10577 },
10578
10579 _mouseStop: function( event ) {
10580 this.handles.removeClass( "ui-state-active" );
10581 this._mouseSliding = false;
10582
10583 this._stop( event, this._handleIndex );
10584 this._change( event, this._handleIndex );
10585
10586 this._handleIndex = null;
10587 this._clickOffset = null;
10588 this._animateOff = false;
10589
10590 return false;
10591 },
10592
10593 _detectOrientation: function() {
10594 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
10595 },
10596
10597 _normValueFromMouse: function( position ) {
10598 var pixelTotal,
10599 pixelMouse,
10600 percentMouse,
10601 valueTotal,
10602 valueMouse;
10603
10604 if ( this.orientation === "horizontal" ) {
10605 pixelTotal = this.elementSize.width;
10606 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
10607 } else {
10608 pixelTotal = this.elementSize.height;
10609 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
10610 }
10611
10612 percentMouse = ( pixelMouse / pixelTotal );
10613 if ( percentMouse > 1 ) {
10614 percentMouse = 1;
10615 }
10616 if ( percentMouse < 0 ) {
10617 percentMouse = 0;
10618 }
10619 if ( this.orientation === "vertical" ) {
10620 percentMouse = 1 - percentMouse;
10621 }
10622
10623 valueTotal = this._valueMax() - this._valueMin();
10624 valueMouse = this._valueMin() + percentMouse * valueTotal;
10625
10626 return this._trimAlignValue( valueMouse );
10627 },
10628
10629 _start: function( event, index ) {
10630 var uiHash = {
10631 handle: this.handles[ index ],
10632 value: this.value()
10633 };
10634 if ( this.options.values && this.options.values.length ) {
10635 uiHash.value = this.values( index );
10636 uiHash.values = this.values();
10637 }
10638 return this._trigger( "start", event, uiHash );
10639 },
10640
10641 _slide: function( event, index, newVal ) {
10642 var otherVal,
10643 newValues,
10644 allowed;
10645
10646 if ( this.options.values && this.options.values.length ) {
10647 otherVal = this.values( index ? 0 : 1 );
10648
10649 if ( ( this.options.values.length === 2 && this.options.range === true ) &&
10650 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
10651 ) {
10652 newVal = otherVal;
10653 }
10654
10655 if ( newVal !== this.values( index ) ) {
10656 newValues = this.values();
10657 newValues[ index ] = newVal;
10658 // A slide can be canceled by returning false from the slide callback
10659 allowed = this._trigger( "slide", event, {
10660 handle: this.handles[ index ],
10661 value: newVal,
10662 values: newValues
10663 } );
10664 otherVal = this.values( index ? 0 : 1 );
10665 if ( allowed !== false ) {
10666 this.values( index, newVal, true );
10667 }
10668 }
10669 } else {
10670 if ( newVal !== this.value() ) {
10671 // A slide can be canceled by returning false from the slide callback
10672 allowed = this._trigger( "slide", event, {
10673 handle: this.handles[ index ],
10674 value: newVal
10675 } );
10676 if ( allowed !== false ) {
10677 this.value( newVal );
10678 }
10679 }
10680 }
10681 },
10682
10683 _stop: function( event, index ) {
10684 var uiHash = {
10685 handle: this.handles[ index ],
10686 value: this.value()
10687 };
10688 if ( this.options.values && this.options.values.length ) {
10689 uiHash.value = this.values( index );
10690 uiHash.values = this.values();
10691 }
10692
10693 this._trigger( "stop", event, uiHash );
10694 },
10695
10696 _change: function( event, index ) {
10697 if ( !this._keySliding && !this._mouseSliding ) {
10698 var uiHash = {
10699 handle: this.handles[ index ],
10700 value: this.value()
10701 };
10702 if ( this.options.values && this.options.values.length ) {
10703 uiHash.value = this.values( index );
10704 uiHash.values = this.values();
10705 }
10706
10707 //store the last changed value index for reference when handles overlap
10708 this._lastChangedValue = index;
10709
10710 this._trigger( "change", event, uiHash );
10711 }
10712 },
10713
10714 value: function( newValue ) {
10715 if ( arguments.length ) {
10716 this.options.value = this._trimAlignValue( newValue );
10717 this._refreshValue();
10718 this._change( null, 0 );
10719 return;
10720 }
10721
10722 return this._value();
10723 },
10724
10725 values: function( index, newValue ) {
10726 var vals,
10727 newValues,
10728 i;
10729
10730 if ( arguments.length > 1 ) {
10731 this.options.values[ index ] = this._trimAlignValue( newValue );
10732 this._refreshValue();
10733 this._change( null, index );
10734 return;
10735 }
10736
10737 if ( arguments.length ) {
10738 if ( $.isArray( arguments[ 0 ] ) ) {
10739 vals = this.options.values;
10740 newValues = arguments[ 0 ];
10741 for ( i = 0; i < vals.length; i += 1 ) {
10742 vals[ i ] = this._trimAlignValue( newValues[ i ] );
10743 this._change( null, i );
10744 }
10745 this._refreshValue();
10746 } else {
10747 if ( this.options.values && this.options.values.length ) {
10748 return this._values( index );
10749 } else {
10750 return this.value();
10751 }
10752 }
10753 } else {
10754 return this._values();
10755 }
10756 },
10757
10758 _setOption: function( key, value ) {
10759 var i,
10760 valsLength = 0;
10761
10762 if ( key === "range" && this.options.range === true ) {
10763 if ( value === "min" ) {
10764 this.options.value = this._values( 0 );
10765 this.options.values = null;
10766 } else if ( value === "max" ) {
10767 this.options.value = this._values( this.options.values.length-1 );
10768 this.options.values = null;
10769 }
10770 }
10771
10772 if ( $.isArray( this.options.values ) ) {
10773 valsLength = this.options.values.length;
10774 }
10775
10776 $.Widget.prototype._setOption.apply( this, arguments );
10777
10778 switch ( key ) {
10779 case "orientation":
10780 this._detectOrientation();
10781 this.element
10782 .removeClass( "ui-slider-horizontal ui-slider-vertical" )
10783 .addClass( "ui-slider-" + this.orientation );
10784 this._refreshValue();
10785 break;
10786 case "value":
10787 this._animateOff = true;
10788 this._refreshValue();
10789 this._change( null, 0 );
10790 this._animateOff = false;
10791 break;
10792 case "values":
10793 this._animateOff = true;
10794 this._refreshValue();
10795 for ( i = 0; i < valsLength; i += 1 ) {
10796 this._change( null, i );
10797 }
10798 this._animateOff = false;
10799 break;
10800 case "min":
10801 case "max":
10802 this._animateOff = true;
10803 this._refreshValue();
10804 this._animateOff = false;
10805 break;
10806 case "range":
10807 this._animateOff = true;
10808 this._refresh();
10809 this._animateOff = false;
10810 break;
10811 }
10812 },
10813
10814 //internal value getter
10815 // _value() returns value trimmed by min and max, aligned by step
10816 _value: function() {
10817 var val = this.options.value;
10818 val = this._trimAlignValue( val );
10819
10820 return val;
10821 },
10822
10823 //internal values getter
10824 // _values() returns array of values trimmed by min and max, aligned by step
10825 // _values( index ) returns single value trimmed by min and max, aligned by step
10826 _values: function( index ) {
10827 var val,
10828 vals,
10829 i;
10830
10831 if ( arguments.length ) {
10832 val = this.options.values[ index ];
10833 val = this._trimAlignValue( val );
10834
10835 return val;
10836 } else if ( this.options.values && this.options.values.length ) {
10837 // .slice() creates a copy of the array
10838 // this copy gets trimmed by min and max and then returned
10839 vals = this.options.values.slice();
10840 for ( i = 0; i < vals.length; i+= 1) {
10841 vals[ i ] = this._trimAlignValue( vals[ i ] );
10842 }
10843
10844 return vals;
10845 } else {
10846 return [];
10847 }
10848 },
10849
10850 // returns the step-aligned value that val is closest to, between (inclusive) min and max
10851 _trimAlignValue: function( val ) {
10852 if ( val <= this._valueMin() ) {
10853 return this._valueMin();
10854 }
10855 if ( val >= this._valueMax() ) {
10856 return this._valueMax();
10857 }
10858 var step = ( this.options.step > 0 ) ? this.options.step : 1,
10859 valModStep = (val - this._valueMin()) % step,
10860 alignValue = val - valModStep;
10861
10862 if ( Math.abs(valModStep) * 2 >= step ) {
10863 alignValue += ( valModStep > 0 ) ? step : ( -step );
10864 }
10865
10866 // Since JavaScript has problems with large floats, round
10867 // the final value to 5 digits after the decimal point (see #4124)
10868 return parseFloat( alignValue.toFixed(5) );
10869 },
10870
10871 _valueMin: function() {
10872 return this.options.min;
10873 },
10874
10875 _valueMax: function() {
10876 return this.options.max;
10877 },
10878
10879 _refreshValue: function() {
10880 var lastValPercent, valPercent, value, valueMin, valueMax,
10881 oRange = this.options.range,
10882 o = this.options,
10883 that = this,
10884 animate = ( !this._animateOff ) ? o.animate : false,
10885 _set = {};
10886
10887 if ( this.options.values && this.options.values.length ) {
10888 this.handles.each(function( i ) {
10889 valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
10890 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
10891 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
10892 if ( that.options.range === true ) {
10893 if ( that.orientation === "horizontal" ) {
10894 if ( i === 0 ) {
10895 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
10896 }
10897 if ( i === 1 ) {
10898 that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
10899 }
10900 } else {
10901 if ( i === 0 ) {
10902 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
10903 }
10904 if ( i === 1 ) {
10905 that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
10906 }
10907 }
10908 }
10909 lastValPercent = valPercent;
10910 });
10911 } else {
10912 value = this.value();
10913 valueMin = this._valueMin();
10914 valueMax = this._valueMax();
10915 valPercent = ( valueMax !== valueMin ) ?
10916 ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
10917 0;
10918 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
10919 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
10920
10921 if ( oRange === "min" && this.orientation === "horizontal" ) {
10922 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
10923 }
10924 if ( oRange === "max" && this.orientation === "horizontal" ) {
10925 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
10926 }
10927 if ( oRange === "min" && this.orientation === "vertical" ) {
10928 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
10929 }
10930 if ( oRange === "max" && this.orientation === "vertical" ) {
10931 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
10932 }
10933 }
10934 },
10935
10936 _handleEvents: {
10937 keydown: function( event ) {
10938 /*jshint maxcomplexity:25*/
10939 var allowed, curVal, newVal, step,
10940 index = $( event.target ).data( "ui-slider-handle-index" );
10941
10942 switch ( event.keyCode ) {
10943 case $.ui.keyCode.HOME:
10944 case $.ui.keyCode.END:
10945 case $.ui.keyCode.PAGE_UP:
10946 case $.ui.keyCode.PAGE_DOWN:
10947 case $.ui.keyCode.UP:
10948 case $.ui.keyCode.RIGHT:
10949 case $.ui.keyCode.DOWN:
10950 case $.ui.keyCode.LEFT:
10951 event.preventDefault();
10952 if ( !this._keySliding ) {
10953 this._keySliding = true;
10954 $( event.target ).addClass( "ui-state-active" );
10955 allowed = this._start( event, index );
10956 if ( allowed === false ) {
10957 return;
10958 }
10959 }
10960 break;
10961 }
10962
10963 step = this.options.step;
10964 if ( this.options.values && this.options.values.length ) {
10965 curVal = newVal = this.values( index );
10966 } else {
10967 curVal = newVal = this.value();
10968 }
10969
10970 switch ( event.keyCode ) {
10971 case $.ui.keyCode.HOME:
10972 newVal = this._valueMin();
10973 break;
10974 case $.ui.keyCode.END:
10975 newVal = this._valueMax();
10976 break;
10977 case $.ui.keyCode.PAGE_UP:
10978 newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) );
10979 break;
10980 case $.ui.keyCode.PAGE_DOWN:
10981 newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) );
10982 break;
10983 case $.ui.keyCode.UP:
10984 case $.ui.keyCode.RIGHT:
10985 if ( curVal === this._valueMax() ) {
10986 return;
10987 }
10988 newVal = this._trimAlignValue( curVal + step );
10989 break;
10990 case $.ui.keyCode.DOWN:
10991 case $.ui.keyCode.LEFT:
10992 if ( curVal === this._valueMin() ) {
10993 return;
10994 }
10995 newVal = this._trimAlignValue( curVal - step );
10996 break;
10997 }
10998
10999 this._slide( event, index, newVal );
11000 },
11001 click: function( event ) {
11002 event.preventDefault();
11003 },
11004 keyup: function( event ) {
11005 var index = $( event.target ).data( "ui-slider-handle-index" );
11006
11007 if ( this._keySliding ) {
11008 this._keySliding = false;
11009 this._stop( event, index );
11010 this._change( event, index );
11011 $( event.target ).removeClass( "ui-state-active" );
11012 }
11013 }
11014 }
11015
11016 });
11017
11018 }(jQuery));
11019 (function( $ ) {
11020
11021 function modifier( fn ) {
11022 return function() {
11023 var previous = this.element.val();
11024 fn.apply( this, arguments );
11025 this._refresh();
11026 if ( previous !== this.element.val() ) {
11027 this._trigger( "change" );
11028 }
11029 };
11030 }
11031
11032 $.widget( "ui.spinner", {
11033 version: "1.10.3",
11034 defaultElement: "<input>",
11035 widgetEventPrefix: "spin",
11036 options: {
11037 culture: null,
11038 icons: {
11039 down: "ui-icon-triangle-1-s",
11040 up: "ui-icon-triangle-1-n"
11041 },
11042 incremental: true,
11043 max: null,
11044 min: null,
11045 numberFormat: null,
11046 page: 10,
11047 step: 1,
11048
11049 change: null,
11050 spin: null,
11051 start: null,
11052 stop: null
11053 },
11054
11055 _create: function() {
11056 // handle string values that need to be parsed
11057 this._setOption( "max", this.options.max );
11058 this._setOption( "min", this.options.min );
11059 this._setOption( "step", this.options.step );
11060
11061 // format the value, but don't constrain
11062 this._value( this.element.val(), true );
11063
11064 this._draw();
11065 this._on( this._events );
11066 this._refresh();
11067
11068 // turning off autocomplete prevents the browser from remembering the
11069 // value when navigating through history, so we re-enable autocomplete
11070 // if the page is unloaded before the widget is destroyed. #7790
11071 this._on( this.window, {
11072 beforeunload: function() {
11073 this.element.removeAttr( "autocomplete" );
11074 }
11075 });
11076 },
11077
11078 _getCreateOptions: function() {
11079 var options = {},
11080 element = this.element;
11081
11082 $.each( [ "min", "max", "step" ], function( i, option ) {
11083 var value = element.attr( option );
11084 if ( value !== undefined && value.length ) {
11085 options[ option ] = value;
11086 }
11087 });
11088
11089 return options;
11090 },
11091
11092 _events: {
11093 keydown: function( event ) {
11094 if ( this._start( event ) && this._keydown( event ) ) {
11095 event.preventDefault();
11096 }
11097 },
11098 keyup: "_stop",
11099 focus: function() {
11100 this.previous = this.element.val();
11101 },
11102 blur: function( event ) {
11103 if ( this.cancelBlur ) {
11104 delete this.cancelBlur;
11105 return;
11106 }
11107
11108 this._stop();
11109 this._refresh();
11110 if ( this.previous !== this.element.val() ) {
11111 this._trigger( "change", event );
11112 }
11113 },
11114 mousewheel: function( event, delta ) {
11115 if ( !delta ) {
11116 return;
11117 }
11118 if ( !this.spinning && !this._start( event ) ) {
11119 return false;
11120 }
11121
11122 this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
11123 clearTimeout( this.mousewheelTimer );
11124 this.mousewheelTimer = this._delay(function() {
11125 if ( this.spinning ) {
11126 this._stop( event );
11127 }
11128 }, 100 );
11129 event.preventDefault();
11130 },
11131 "mousedown .ui-spinner-button": function( event ) {
11132 var previous;
11133
11134 // We never want the buttons to have focus; whenever the user is
11135 // interacting with the spinner, the focus should be on the input.
11136 // If the input is focused then this.previous is properly set from
11137 // when the input first received focus. If the input is not focused
11138 // then we need to set this.previous based on the value before spinning.
11139 previous = this.element[0] === this.document[0].activeElement ?
11140 this.previous : this.element.val();
11141 function checkFocus() {
11142 var isActive = this.element[0] === this.document[0].activeElement;
11143 if ( !isActive ) {
11144 this.element.focus();
11145 this.previous = previous;
11146 // support: IE
11147 // IE sets focus asynchronously, so we need to check if focus
11148 // moved off of the input because the user clicked on the button.
11149 this._delay(function() {
11150 this.previous = previous;
11151 });
11152 }
11153 }
11154
11155 // ensure focus is on (or stays on) the text field
11156 event.preventDefault();
11157 checkFocus.call( this );
11158
11159 // support: IE
11160 // IE doesn't prevent moving focus even with event.preventDefault()
11161 // so we set a flag to know when we should ignore the blur event
11162 // and check (again) if focus moved off of the input.
11163 this.cancelBlur = true;
11164 this._delay(function() {
11165 delete this.cancelBlur;
11166 checkFocus.call( this );
11167 });
11168
11169 if ( this._start( event ) === false ) {
11170 return;
11171 }
11172
11173 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
11174 },
11175 "mouseup .ui-spinner-button": "_stop",
11176 "mouseenter .ui-spinner-button": function( event ) {
11177 // button will add ui-state-active if mouse was down while mouseleave and kept down
11178 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
11179 return;
11180 }
11181
11182 if ( this._start( event ) === false ) {
11183 return false;
11184 }
11185 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
11186 },
11187 // TODO: do we really want to consider this a stop?
11188 // shouldn't we just stop the repeater and wait until mouseup before
11189 // we trigger the stop event?
11190 "mouseleave .ui-spinner-button": "_stop"
11191 },
11192
11193 _draw: function() {
11194 var uiSpinner = this.uiSpinner = this.element
11195 .addClass( "ui-spinner-input" )
11196 .attr( "autocomplete", "off" )
11197 .wrap( this._uiSpinnerHtml() )
11198 .parent()
11199 // add buttons
11200 .append( this._buttonHtml() );
11201
11202 this.element.attr( "role", "spinbutton" );
11203
11204 // button bindings
11205 this.buttons = uiSpinner.find( ".ui-spinner-button" )
11206 .attr( "tabIndex", -1 )
11207 .button()
11208 .removeClass( "ui-corner-all" );
11209
11210 // IE 6 doesn't understand height: 50% for the buttons
11211 // unless the wrapper has an explicit height
11212 if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
11213 uiSpinner.height() > 0 ) {
11214 uiSpinner.height( uiSpinner.height() );
11215 }
11216
11217 // disable spinner if element was already disabled
11218 if ( this.options.disabled ) {
11219 this.disable();
11220 }
11221 },
11222
11223 _keydown: function( event ) {
11224 var options = this.options,
11225 keyCode = $.ui.keyCode;
11226
11227 switch ( event.keyCode ) {
11228 case keyCode.UP:
11229 this._repeat( null, 1, event );
11230 return true;
11231 case keyCode.DOWN:
11232 this._repeat( null, -1, event );
11233 return true;
11234 case keyCode.PAGE_UP:
11235 this._repeat( null, options.page, event );
11236 return true;
11237 case keyCode.PAGE_DOWN:
11238 this._repeat( null, -options.page, event );
11239 return true;
11240 }
11241
11242 return false;
11243 },
11244
11245 _uiSpinnerHtml: function() {
11246 return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
11247 },
11248
11249 _buttonHtml: function() {
11250 return "" +
11251 "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
11252 "<span class='ui-icon " + this.options.icons.up + "'>&#9650;</span>" +
11253 "</a>" +
11254 "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
11255 "<span class='ui-icon " + this.options.icons.down + "'>&#9660;</span>" +
11256 "</a>";
11257 },
11258
11259 _start: function( event ) {
11260 if ( !this.spinning && this._trigger( "start", event ) === false ) {
11261 return false;
11262 }
11263
11264 if ( !this.counter ) {
11265 this.counter = 1;
11266 }
11267 this.spinning = true;
11268 return true;
11269 },
11270
11271 _repeat: function( i, steps, event ) {
11272 i = i || 500;
11273
11274 clearTimeout( this.timer );
11275 this.timer = this._delay(function() {
11276 this._repeat( 40, steps, event );
11277 }, i );
11278
11279 this._spin( steps * this.options.step, event );
11280 },
11281
11282 _spin: function( step, event ) {
11283 var value = this.value() || 0;
11284
11285 if ( !this.counter ) {
11286 this.counter = 1;
11287 }
11288
11289 value = this._adjustValue( value + step * this._increment( this.counter ) );
11290
11291 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
11292 this._value( value );
11293 this.counter++;
11294 }
11295 },
11296
11297 _increment: function( i ) {
11298 var incremental = this.options.incremental;
11299
11300 if ( incremental ) {
11301 return $.isFunction( incremental ) ?
11302 incremental( i ) :
11303 Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 );
11304 }
11305
11306 return 1;
11307 },
11308
11309 _precision: function() {
11310 var precision = this._precisionOf( this.options.step );
11311 if ( this.options.min !== null ) {
11312 precision = Math.max( precision, this._precisionOf( this.options.min ) );
11313 }
11314 return precision;
11315 },
11316
11317 _precisionOf: function( num ) {
11318 var str = num.toString(),
11319 decimal = str.indexOf( "." );
11320 return decimal === -1 ? 0 : str.length - decimal - 1;
11321 },
11322
11323 _adjustValue: function( value ) {
11324 var base, aboveMin,
11325 options = this.options;
11326
11327 // make sure we're at a valid step
11328 // - find out where we are relative to the base (min or 0)
11329 base = options.min !== null ? options.min : 0;
11330 aboveMin = value - base;
11331 // - round to the nearest step
11332 aboveMin = Math.round(aboveMin / options.step) * options.step;
11333 // - rounding is based on 0, so adjust back to our base
11334 value = base + aboveMin;
11335
11336 // fix precision from bad JS floating point math
11337 value = parseFloat( value.toFixed( this._precision() ) );
11338
11339 // clamp the value
11340 if ( options.max !== null && value > options.max) {
11341 return options.max;
11342 }
11343 if ( options.min !== null && value < options.min ) {
11344 return options.min;
11345 }
11346
11347 return value;
11348 },
11349
11350 _stop: function( event ) {
11351 if ( !this.spinning ) {
11352 return;
11353 }
11354
11355 clearTimeout( this.timer );
11356 clearTimeout( this.mousewheelTimer );
11357 this.counter = 0;
11358 this.spinning = false;
11359 this._trigger( "stop", event );
11360 },
11361
11362 _setOption: function( key, value ) {
11363 if ( key === "culture" || key === "numberFormat" ) {
11364 var prevValue = this._parse( this.element.val() );
11365 this.options[ key ] = value;
11366 this.element.val( this._format( prevValue ) );
11367 return;
11368 }
11369
11370 if ( key === "max" || key === "min" || key === "step" ) {
11371 if ( typeof value === "string" ) {
11372 value = this._parse( value );
11373 }
11374 }
11375 if ( key === "icons" ) {
11376 this.buttons.first().find( ".ui-icon" )
11377 .removeClass( this.options.icons.up )
11378 .addClass( value.up );
11379 this.buttons.last().find( ".ui-icon" )
11380 .removeClass( this.options.icons.down )
11381 .addClass( value.down );
11382 }
11383
11384 this._super( key, value );
11385
11386 if ( key === "disabled" ) {
11387 if ( value ) {
11388 this.element.prop( "disabled", true );
11389 this.buttons.button( "disable" );
11390 } else {
11391 this.element.prop( "disabled", false );
11392 this.buttons.button( "enable" );
11393 }
11394 }
11395 },
11396
11397 _setOptions: modifier(function( options ) {
11398 this._super( options );
11399 this._value( this.element.val() );
11400 }),
11401
11402 _parse: function( val ) {
11403 if ( typeof val === "string" && val !== "" ) {
11404 val = window.Globalize && this.options.numberFormat ?
11405 Globalize.parseFloat( val, 10, this.options.culture ) : +val;
11406 }
11407 return val === "" || isNaN( val ) ? null : val;
11408 },
11409
11410 _format: function( value ) {
11411 if ( value === "" ) {
11412 return "";
11413 }
11414 return window.Globalize && this.options.numberFormat ?
11415 Globalize.format( value, this.options.numberFormat, this.options.culture ) :
11416 value;
11417 },
11418
11419 _refresh: function() {
11420 this.element.attr({
11421 "aria-valuemin": this.options.min,
11422 "aria-valuemax": this.options.max,
11423 // TODO: what should we do with values that can't be parsed?
11424 "aria-valuenow": this._parse( this.element.val() )
11425 });
11426 },
11427
11428 // update the value without triggering change
11429 _value: function( value, allowAny ) {
11430 var parsed;
11431 if ( value !== "" ) {
11432 parsed = this._parse( value );
11433 if ( parsed !== null ) {
11434 if ( !allowAny ) {
11435 parsed = this._adjustValue( parsed );
11436 }
11437 value = this._format( parsed );
11438 }
11439 }
11440 this.element.val( value );
11441 this._refresh();
11442 },
11443
11444 _destroy: function() {
11445 this.element
11446 .removeClass( "ui-spinner-input" )
11447 .prop( "disabled", false )
11448 .removeAttr( "autocomplete" )
11449 .removeAttr( "role" )
11450 .removeAttr( "aria-valuemin" )
11451 .removeAttr( "aria-valuemax" )
11452 .removeAttr( "aria-valuenow" );
11453 this.uiSpinner.replaceWith( this.element );
11454 },
11455
11456 stepUp: modifier(function( steps ) {
11457 this._stepUp( steps );
11458 }),
11459 _stepUp: function( steps ) {
11460 if ( this._start() ) {
11461 this._spin( (steps || 1) * this.options.step );
11462 this._stop();
11463 }
11464 },
11465
11466 stepDown: modifier(function( steps ) {
11467 this._stepDown( steps );
11468 }),
11469 _stepDown: function( steps ) {
11470 if ( this._start() ) {
11471 this._spin( (steps || 1) * -this.options.step );
11472 this._stop();
11473 }
11474 },
11475
11476 pageUp: modifier(function( pages ) {
11477 this._stepUp( (pages || 1) * this.options.page );
11478 }),
11479
11480 pageDown: modifier(function( pages ) {
11481 this._stepDown( (pages || 1) * this.options.page );
11482 }),
11483
11484 value: function( newVal ) {
11485 if ( !arguments.length ) {
11486 return this._parse( this.element.val() );
11487 }
11488 modifier( this._value ).call( this, newVal );
11489 },
11490
11491 widget: function() {
11492 return this.uiSpinner;
11493 }
11494 });
11495
11496 }( jQuery ) );
11497 (function( $, undefined ) {
11498
11499 var tabId = 0,
11500 rhash = /#.*$/;
11501
11502 function getNextTabId() {
11503 return ++tabId;
11504 }
11505
11506 function isLocal( anchor ) {
11507 return anchor.hash.length > 1 &&
11508 decodeURIComponent( anchor.href.replace( rhash, "" ) ) ===
11509 decodeURIComponent( location.href.replace( rhash, "" ) );
11510 }
11511
11512 $.widget( "ui.tabs", {
11513 version: "1.10.3",
11514 delay: 300,
11515 options: {
11516 active: null,
11517 collapsible: false,
11518 event: "click",
11519 heightStyle: "content",
11520 hide: null,
11521 show: null,
11522
11523 // callbacks
11524 activate: null,
11525 beforeActivate: null,
11526 beforeLoad: null,
11527 load: null
11528 },
11529
11530 _create: function() {
11531 var that = this,
11532 options = this.options;
11533
11534 this.running = false;
11535
11536 this.element
11537 .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
11538 .toggleClass( "ui-tabs-collapsible", options.collapsible )
11539 // Prevent users from focusing disabled tabs via click
11540 .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
11541 if ( $( this ).is( ".ui-state-disabled" ) ) {
11542 event.preventDefault();
11543 }
11544 })
11545 // support: IE <9
11546 // Preventing the default action in mousedown doesn't prevent IE
11547 // from focusing the element, so if the anchor gets focused, blur.
11548 // We don't have to worry about focusing the previously focused
11549 // element since clicking on a non-focusable element should focus
11550 // the body anyway.
11551 .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
11552 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
11553 this.blur();
11554 }
11555 });
11556
11557 this._processTabs();
11558 options.active = this._initialActive();
11559
11560 // Take disabling tabs via class attribute from HTML
11561 // into account and update option properly.
11562 if ( $.isArray( options.disabled ) ) {
11563 options.disabled = $.unique( options.disabled.concat(
11564 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
11565 return that.tabs.index( li );
11566 })
11567 ) ).sort();
11568 }
11569
11570 // check for length avoids error when initializing empty list
11571 if ( this.options.active !== false && this.anchors.length ) {
11572 this.active = this._findActive( options.active );
11573 } else {
11574 this.active = $();
11575 }
11576
11577 this._refresh();
11578
11579 if ( this.active.length ) {
11580 this.load( options.active );
11581 }
11582 },
11583
11584 _initialActive: function() {
11585 var active = this.options.active,
11586 collapsible = this.options.collapsible,
11587 locationHash = location.hash.substring( 1 );
11588
11589 if ( active === null ) {
11590 // check the fragment identifier in the URL
11591 if ( locationHash ) {
11592 this.tabs.each(function( i, tab ) {
11593 if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
11594 active = i;
11595 return false;
11596 }
11597 });
11598 }
11599
11600 // check for a tab marked active via a class
11601 if ( active === null ) {
11602 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
11603 }
11604
11605 // no active tab, set to false
11606 if ( active === null || active === -1 ) {
11607 active = this.tabs.length ? 0 : false;
11608 }
11609 }
11610
11611 // handle numbers: negative, out of range
11612 if ( active !== false ) {
11613 active = this.tabs.index( this.tabs.eq( active ) );
11614 if ( active === -1 ) {
11615 active = collapsible ? false : 0;
11616 }
11617 }
11618
11619 // don't allow collapsible: false and active: false
11620 if ( !collapsible && active === false && this.anchors.length ) {
11621 active = 0;
11622 }
11623
11624 return active;
11625 },
11626
11627 _getCreateEventData: function() {
11628 return {
11629 tab: this.active,
11630 panel: !this.active.length ? $() : this._getPanelForTab( this.active )
11631 };
11632 },
11633
11634 _tabKeydown: function( event ) {
11635 /*jshint maxcomplexity:15*/
11636 var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
11637 selectedIndex = this.tabs.index( focusedTab ),
11638 goingForward = true;
11639
11640 if ( this._handlePageNav( event ) ) {
11641 return;
11642 }
11643
11644 switch ( event.keyCode ) {
11645 case $.ui.keyCode.RIGHT:
11646 case $.ui.keyCode.DOWN:
11647 selectedIndex++;
11648 break;
11649 case $.ui.keyCode.UP:
11650 case $.ui.keyCode.LEFT:
11651 goingForward = false;
11652 selectedIndex--;
11653 break;
11654 case $.ui.keyCode.END:
11655 selectedIndex = this.anchors.length - 1;
11656 break;
11657 case $.ui.keyCode.HOME:
11658 selectedIndex = 0;
11659 break;
11660 case $.ui.keyCode.SPACE:
11661 // Activate only, no collapsing
11662 event.preventDefault();
11663 clearTimeout( this.activating );
11664 this._activate( selectedIndex );
11665 return;
11666 case $.ui.keyCode.ENTER:
11667 // Toggle (cancel delayed activation, allow collapsing)
11668 event.preventDefault();
11669 clearTimeout( this.activating );
11670 // Determine if we should collapse or activate
11671 this._activate( selectedIndex === this.options.active ? false : selectedIndex );
11672 return;
11673 default:
11674 return;
11675 }
11676
11677 // Focus the appropriate tab, based on which key was pressed
11678 event.preventDefault();
11679 clearTimeout( this.activating );
11680 selectedIndex = this._focusNextTab( selectedIndex, goingForward );
11681
11682 // Navigating with control key will prevent automatic activation
11683 if ( !event.ctrlKey ) {
11684 // Update aria-selected immediately so that AT think the tab is already selected.
11685 // Otherwise AT may confuse the user by stating that they need to activate the tab,
11686 // but the tab will already be activated by the time the announcement finishes.
11687 focusedTab.attr( "aria-selected", "false" );
11688 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
11689
11690 this.activating = this._delay(function() {
11691 this.option( "active", selectedIndex );
11692 }, this.delay );
11693 }
11694 },
11695
11696 _panelKeydown: function( event ) {
11697 if ( this._handlePageNav( event ) ) {
11698 return;
11699 }
11700
11701 // Ctrl+up moves focus to the current tab
11702 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
11703 event.preventDefault();
11704 this.active.focus();
11705 }
11706 },
11707
11708 // Alt+page up/down moves focus to the previous/next tab (and activates)
11709 _handlePageNav: function( event ) {
11710 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
11711 this._activate( this._focusNextTab( this.options.active - 1, false ) );
11712 return true;
11713 }
11714 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
11715 this._activate( this._focusNextTab( this.options.active + 1, true ) );
11716 return true;
11717 }
11718 },
11719
11720 _findNextTab: function( index, goingForward ) {
11721 var lastTabIndex = this.tabs.length - 1;
11722
11723 function constrain() {
11724 if ( index > lastTabIndex ) {
11725 index = 0;
11726 }
11727 if ( index < 0 ) {
11728 index = lastTabIndex;
11729 }
11730 return index;
11731 }
11732
11733 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
11734 index = goingForward ? index + 1 : index - 1;
11735 }
11736
11737 return index;
11738 },
11739
11740 _focusNextTab: function( index, goingForward ) {
11741 index = this._findNextTab( index, goingForward );
11742 this.tabs.eq( index ).focus();
11743 return index;
11744 },
11745
11746 _setOption: function( key, value ) {
11747 if ( key === "active" ) {
11748 // _activate() will handle invalid values and update this.options
11749 this._activate( value );
11750 return;
11751 }
11752
11753 if ( key === "disabled" ) {
11754 // don't use the widget factory's disabled handling
11755 this._setupDisabled( value );
11756 return;
11757 }
11758
11759 this._super( key, value);
11760
11761 if ( key === "collapsible" ) {
11762 this.element.toggleClass( "ui-tabs-collapsible", value );
11763 // Setting collapsible: false while collapsed; open first panel
11764 if ( !value && this.options.active === false ) {
11765 this._activate( 0 );
11766 }
11767 }
11768
11769 if ( key === "event" ) {
11770 this._setupEvents( value );
11771 }
11772
11773 if ( key === "heightStyle" ) {
11774 this._setupHeightStyle( value );
11775 }
11776 },
11777
11778 _tabId: function( tab ) {
11779 return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
11780 },
11781
11782 _sanitizeSelector: function( hash ) {
11783 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
11784 },
11785
11786 refresh: function() {
11787 var options = this.options,
11788 lis = this.tablist.children( ":has(a[href])" );
11789
11790 // get disabled tabs from class attribute from HTML
11791 // this will get converted to a boolean if needed in _refresh()
11792 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
11793 return lis.index( tab );
11794 });
11795
11796 this._processTabs();
11797
11798 // was collapsed or no tabs
11799 if ( options.active === false || !this.anchors.length ) {
11800 options.active = false;
11801 this.active = $();
11802 // was active, but active tab is gone
11803 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
11804 // all remaining tabs are disabled
11805 if ( this.tabs.length === options.disabled.length ) {
11806 options.active = false;
11807 this.active = $();
11808 // activate previous tab
11809 } else {
11810 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
11811 }
11812 // was active, active tab still exists
11813 } else {
11814 // make sure active index is correct
11815 options.active = this.tabs.index( this.active );
11816 }
11817
11818 this._refresh();
11819 },
11820
11821 _refresh: function() {
11822 this._setupDisabled( this.options.disabled );
11823 this._setupEvents( this.options.event );
11824 this._setupHeightStyle( this.options.heightStyle );
11825
11826 this.tabs.not( this.active ).attr({
11827 "aria-selected": "false",
11828 tabIndex: -1
11829 });
11830 this.panels.not( this._getPanelForTab( this.active ) )
11831 .hide()
11832 .attr({
11833 "aria-expanded": "false",
11834 "aria-hidden": "true"
11835 });
11836
11837 // Make sure one tab is in the tab order
11838 if ( !this.active.length ) {
11839 this.tabs.eq( 0 ).attr( "tabIndex", 0 );
11840 } else {
11841 this.active
11842 .addClass( "ui-tabs-active ui-state-active" )
11843 .attr({
11844 "aria-selected": "true",
11845 tabIndex: 0
11846 });
11847 this._getPanelForTab( this.active )
11848 .show()
11849 .attr({
11850 "aria-expanded": "true",
11851 "aria-hidden": "false"
11852 });
11853 }
11854 },
11855
11856 _processTabs: function() {
11857 var that = this;
11858
11859 this.tablist = this._getList()
11860 .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
11861 .attr( "role", "tablist" );
11862
11863 this.tabs = this.tablist.find( "> li:has(a[href])" )
11864 .addClass( "ui-state-default ui-corner-top" )
11865 .attr({
11866 role: "tab",
11867 tabIndex: -1
11868 });
11869
11870 this.anchors = this.tabs.map(function() {
11871 return $( "a", this )[ 0 ];
11872 })
11873 .addClass( "ui-tabs-anchor" )
11874 .attr({
11875 role: "presentation",
11876 tabIndex: -1
11877 });
11878
11879 this.panels = $();
11880
11881 this.anchors.each(function( i, anchor ) {
11882 var selector, panel, panelId,
11883 anchorId = $( anchor ).uniqueId().attr( "id" ),
11884 tab = $( anchor ).closest( "li" ),
11885 originalAriaControls = tab.attr( "aria-controls" );
11886
11887 // inline tab
11888 if ( isLocal( anchor ) ) {
11889 selector = anchor.hash;
11890 panel = that.element.find( that._sanitizeSelector( selector ) );
11891 // remote tab
11892 } else {
11893 panelId = that._tabId( tab );
11894 selector = "#" + panelId;
11895 panel = that.element.find( selector );
11896 if ( !panel.length ) {
11897 panel = that._createPanel( panelId );
11898 panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
11899 }
11900 panel.attr( "aria-live", "polite" );
11901 }
11902
11903 if ( panel.length) {
11904 that.panels = that.panels.add( panel );
11905 }
11906 if ( originalAriaControls ) {
11907 tab.data( "ui-tabs-aria-controls", originalAriaControls );
11908 }
11909 tab.attr({
11910 "aria-controls": selector.substring( 1 ),
11911 "aria-labelledby": anchorId
11912 });
11913 panel.attr( "aria-labelledby", anchorId );
11914 });
11915
11916 this.panels
11917 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
11918 .attr( "role", "tabpanel" );
11919 },
11920
11921 // allow overriding how to find the list for rare usage scenarios (#7715)
11922 _getList: function() {
11923 return this.element.find( "ol,ul" ).eq( 0 );
11924 },
11925
11926 _createPanel: function( id ) {
11927 return $( "<div>" )
11928 .attr( "id", id )
11929 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
11930 .data( "ui-tabs-destroy", true );
11931 },
11932
11933 _setupDisabled: function( disabled ) {
11934 if ( $.isArray( disabled ) ) {
11935 if ( !disabled.length ) {
11936 disabled = false;
11937 } else if ( disabled.length === this.anchors.length ) {
11938 disabled = true;
11939 }
11940 }
11941
11942 // disable tabs
11943 for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
11944 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
11945 $( li )
11946 .addClass( "ui-state-disabled" )
11947 .attr( "aria-disabled", "true" );
11948 } else {
11949 $( li )
11950 .removeClass( "ui-state-disabled" )
11951 .removeAttr( "aria-disabled" );
11952 }
11953 }
11954
11955 this.options.disabled = disabled;
11956 },
11957
11958 _setupEvents: function( event ) {
11959 var events = {
11960 click: function( event ) {
11961 event.preventDefault();
11962 }
11963 };
11964 if ( event ) {
11965 $.each( event.split(" "), function( index, eventName ) {
11966 events[ eventName ] = "_eventHandler";
11967 });
11968 }
11969
11970 this._off( this.anchors.add( this.tabs ).add( this.panels ) );
11971 this._on( this.anchors, events );
11972 this._on( this.tabs, { keydown: "_tabKeydown" } );
11973 this._on( this.panels, { keydown: "_panelKeydown" } );
11974
11975 this._focusable( this.tabs );
11976 this._hoverable( this.tabs );
11977 },
11978
11979 _setupHeightStyle: function( heightStyle ) {
11980 var maxHeight,
11981 parent = this.element.parent();
11982
11983 if ( heightStyle === "fill" ) {
11984 maxHeight = parent.height();
11985 maxHeight -= this.element.outerHeight() - this.element.height();
11986
11987 this.element.siblings( ":visible" ).each(function() {
11988 var elem = $( this ),
11989 position = elem.css( "position" );
11990
11991 if ( position === "absolute" || position === "fixed" ) {
11992 return;
11993 }
11994 maxHeight -= elem.outerHeight( true );
11995 });
11996
11997 this.element.children().not( this.panels ).each(function() {
11998 maxHeight -= $( this ).outerHeight( true );
11999 });
12000
12001 this.panels.each(function() {
12002 $( this ).height( Math.max( 0, maxHeight -
12003 $( this ).innerHeight() + $( this ).height() ) );
12004 })
12005 .css( "overflow", "auto" );
12006 } else if ( heightStyle === "auto" ) {
12007 maxHeight = 0;
12008 this.panels.each(function() {
12009 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
12010 }).height( maxHeight );
12011 }
12012 },
12013
12014 _eventHandler: function( event ) {
12015 var options = this.options,
12016 active = this.active,
12017 anchor = $( event.currentTarget ),
12018 tab = anchor.closest( "li" ),
12019 clickedIsActive = tab[ 0 ] === active[ 0 ],
12020 collapsing = clickedIsActive && options.collapsible,
12021 toShow = collapsing ? $() : this._getPanelForTab( tab ),
12022 toHide = !active.length ? $() : this._getPanelForTab( active ),
12023 eventData = {
12024 oldTab: active,
12025 oldPanel: toHide,
12026 newTab: collapsing ? $() : tab,
12027 newPanel: toShow
12028 };
12029
12030 event.preventDefault();
12031
12032 if ( tab.hasClass( "ui-state-disabled" ) ||
12033 // tab is already loading
12034 tab.hasClass( "ui-tabs-loading" ) ||
12035 // can't switch durning an animation
12036 this.running ||
12037 // click on active header, but not collapsible
12038 ( clickedIsActive && !options.collapsible ) ||
12039 // allow canceling activation
12040 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
12041 return;
12042 }
12043
12044 options.active = collapsing ? false : this.tabs.index( tab );
12045
12046 this.active = clickedIsActive ? $() : tab;
12047 if ( this.xhr ) {
12048 this.xhr.abort();
12049 }
12050
12051 if ( !toHide.length && !toShow.length ) {
12052 $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
12053 }
12054
12055 if ( toShow.length ) {
12056 this.load( this.tabs.index( tab ), event );
12057 }
12058 this._toggle( event, eventData );
12059 },
12060
12061 // handles show/hide for selecting tabs
12062 _toggle: function( event, eventData ) {
12063 var that = this,
12064 toShow = eventData.newPanel,
12065 toHide = eventData.oldPanel;
12066
12067 this.running = true;
12068
12069 function complete() {
12070 that.running = false;
12071 that._trigger( "activate", event, eventData );
12072 }
12073
12074 function show() {
12075 eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
12076
12077 if ( toShow.length && that.options.show ) {
12078 that._show( toShow, that.options.show, complete );
12079 } else {
12080 toShow.show();
12081 complete();
12082 }
12083 }
12084
12085 // start out by hiding, then showing, then completing
12086 if ( toHide.length && this.options.hide ) {
12087 this._hide( toHide, this.options.hide, function() {
12088 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
12089 show();
12090 });
12091 } else {
12092 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
12093 toHide.hide();
12094 show();
12095 }
12096
12097 toHide.attr({
12098 "aria-expanded": "false",
12099 "aria-hidden": "true"
12100 });
12101 eventData.oldTab.attr( "aria-selected", "false" );
12102 // If we're switching tabs, remove the old tab from the tab order.
12103 // If we're opening from collapsed state, remove the previous tab from the tab order.
12104 // If we're collapsing, then keep the collapsing tab in the tab order.
12105 if ( toShow.length && toHide.length ) {
12106 eventData.oldTab.attr( "tabIndex", -1 );
12107 } else if ( toShow.length ) {
12108 this.tabs.filter(function() {
12109 return $( this ).attr( "tabIndex" ) === 0;
12110 })
12111 .attr( "tabIndex", -1 );
12112 }
12113
12114 toShow.attr({
12115 "aria-expanded": "true",
12116 "aria-hidden": "false"
12117 });
12118 eventData.newTab.attr({
12119 "aria-selected": "true",
12120 tabIndex: 0
12121 });
12122 },
12123
12124 _activate: function( index ) {
12125 var anchor,
12126 active = this._findActive( index );
12127
12128 // trying to activate the already active panel
12129 if ( active[ 0 ] === this.active[ 0 ] ) {
12130 return;
12131 }
12132
12133 // trying to collapse, simulate a click on the current active header
12134 if ( !active.length ) {
12135 active = this.active;
12136 }
12137
12138 anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
12139 this._eventHandler({
12140 target: anchor,
12141 currentTarget: anchor,
12142 preventDefault: $.noop
12143 });
12144 },
12145
12146 _findActive: function( index ) {
12147 return index === false ? $() : this.tabs.eq( index );
12148 },
12149
12150 _getIndex: function( index ) {
12151 // meta-function to give users option to provide a href string instead of a numerical index.
12152 if ( typeof index === "string" ) {
12153 index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
12154 }
12155
12156 return index;
12157 },
12158
12159 _destroy: function() {
12160 if ( this.xhr ) {
12161 this.xhr.abort();
12162 }
12163
12164 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
12165
12166 this.tablist
12167 .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
12168 .removeAttr( "role" );
12169
12170 this.anchors
12171 .removeClass( "ui-tabs-anchor" )
12172 .removeAttr( "role" )
12173 .removeAttr( "tabIndex" )
12174 .removeUniqueId();
12175
12176 this.tabs.add( this.panels ).each(function() {
12177 if ( $.data( this, "ui-tabs-destroy" ) ) {
12178 $( this ).remove();
12179 } else {
12180 $( this )
12181 .removeClass( "ui-state-default ui-state-active ui-state-disabled " +
12182 "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
12183 .removeAttr( "tabIndex" )
12184 .removeAttr( "aria-live" )
12185 .removeAttr( "aria-busy" )
12186 .removeAttr( "aria-selected" )
12187 .removeAttr( "aria-labelledby" )
12188 .removeAttr( "aria-hidden" )
12189 .removeAttr( "aria-expanded" )
12190 .removeAttr( "role" );
12191 }
12192 });
12193
12194 this.tabs.each(function() {
12195 var li = $( this ),
12196 prev = li.data( "ui-tabs-aria-controls" );
12197 if ( prev ) {
12198 li
12199 .attr( "aria-controls", prev )
12200 .removeData( "ui-tabs-aria-controls" );
12201 } else {
12202 li.removeAttr( "aria-controls" );
12203 }
12204 });
12205
12206 this.panels.show();
12207
12208 if ( this.options.heightStyle !== "content" ) {
12209 this.panels.css( "height", "" );
12210 }
12211 },
12212
12213 enable: function( index ) {
12214 var disabled = this.options.disabled;
12215 if ( disabled === false ) {
12216 return;
12217 }
12218
12219 if ( index === undefined ) {
12220 disabled = false;
12221 } else {
12222 index = this._getIndex( index );
12223 if ( $.isArray( disabled ) ) {
12224 disabled = $.map( disabled, function( num ) {
12225 return num !== index ? num : null;
12226 });
12227 } else {
12228 disabled = $.map( this.tabs, function( li, num ) {
12229 return num !== index ? num : null;
12230 });
12231 }
12232 }
12233 this._setupDisabled( disabled );
12234 },
12235
12236 disable: function( index ) {
12237 var disabled = this.options.disabled;
12238 if ( disabled === true ) {
12239 return;
12240 }
12241
12242 if ( index === undefined ) {
12243 disabled = true;
12244 } else {
12245 index = this._getIndex( index );
12246 if ( $.inArray( index, disabled ) !== -1 ) {
12247 return;
12248 }
12249 if ( $.isArray( disabled ) ) {
12250 disabled = $.merge( [ index ], disabled ).sort();
12251 } else {
12252 disabled = [ index ];
12253 }
12254 }
12255 this._setupDisabled( disabled );
12256 },
12257
12258 load: function( index, event ) {
12259 index = this._getIndex( index );
12260 var that = this,
12261 tab = this.tabs.eq( index ),
12262 anchor = tab.find( ".ui-tabs-anchor" ),
12263 panel = this._getPanelForTab( tab ),
12264 eventData = {
12265 tab: tab,
12266 panel: panel
12267 };
12268
12269 // not remote
12270 if ( isLocal( anchor[ 0 ] ) ) {
12271 return;
12272 }
12273
12274 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
12275
12276 // support: jQuery <1.8
12277 // jQuery <1.8 returns false if the request is canceled in beforeSend,
12278 // but as of 1.8, $.ajax() always returns a jqXHR object.
12279 if ( this.xhr && this.xhr.statusText !== "canceled" ) {
12280 tab.addClass( "ui-tabs-loading" );
12281 panel.attr( "aria-busy", "true" );
12282
12283 this.xhr
12284 .success(function( response ) {
12285 // support: jQuery <1.8
12286 // http://bugs.jquery.com/ticket/11778
12287 setTimeout(function() {
12288 panel.html( response );
12289 that._trigger( "load", event, eventData );
12290 }, 1 );
12291 })
12292 .complete(function( jqXHR, status ) {
12293 // support: jQuery <1.8
12294 // http://bugs.jquery.com/ticket/11778
12295 setTimeout(function() {
12296 if ( status === "abort" ) {
12297 that.panels.stop( false, true );
12298 }
12299
12300 tab.removeClass( "ui-tabs-loading" );
12301 panel.removeAttr( "aria-busy" );
12302
12303 if ( jqXHR === that.xhr ) {
12304 delete that.xhr;
12305 }
12306 }, 1 );
12307 });
12308 }
12309 },
12310
12311 _ajaxSettings: function( anchor, event, eventData ) {
12312 var that = this;
12313 return {
12314 url: anchor.attr( "href" ),
12315 beforeSend: function( jqXHR, settings ) {
12316 return that._trigger( "beforeLoad", event,
12317 $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
12318 }
12319 };
12320 },
12321
12322 _getPanelForTab: function( tab ) {
12323 var id = $( tab ).attr( "aria-controls" );
12324 return this.element.find( this._sanitizeSelector( "#" + id ) );
12325 }
12326 });
12327
12328 })( jQuery );
12329 (function( $ ) {
12330
12331 var increments = 0;
12332
12333 function addDescribedBy( elem, id ) {
12334 var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
12335 describedby.push( id );
12336 elem
12337 .data( "ui-tooltip-id", id )
12338 .attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
12339 }
12340
12341 function removeDescribedBy( elem ) {
12342 var id = elem.data( "ui-tooltip-id" ),
12343 describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
12344 index = $.inArray( id, describedby );
12345 if ( index !== -1 ) {
12346 describedby.splice( index, 1 );
12347 }
12348
12349 elem.removeData( "ui-tooltip-id" );
12350 describedby = $.trim( describedby.join( " " ) );
12351 if ( describedby ) {
12352 elem.attr( "aria-describedby", describedby );
12353 } else {
12354 elem.removeAttr( "aria-describedby" );
12355 }
12356 }
12357
12358 $.widget( "ui.tooltip", {
12359 version: "1.10.3",
12360 options: {
12361 content: function() {
12362 // support: IE<9, Opera in jQuery <1.7
12363 // .text() can't accept undefined, so coerce to a string
12364 var title = $( this ).attr( "title" ) || "";
12365 // Escape title, since we're going from an attribute to raw HTML
12366 return $( "<a>" ).text( title ).html();
12367 },
12368 hide: true,
12369 // Disabled elements have inconsistent behavior across browsers (#8661)
12370 items: "[title]:not([disabled])",
12371 position: {
12372 my: "left top+15",
12373 at: "left bottom",
12374 collision: "flipfit flip"
12375 },
12376 show: true,
12377 tooltipClass: null,
12378 track: false,
12379
12380 // callbacks
12381 close: null,
12382 open: null
12383 },
12384
12385 _create: function() {
12386 this._on({
12387 mouseover: "open",
12388 focusin: "open"
12389 });
12390
12391 // IDs of generated tooltips, needed for destroy
12392 this.tooltips = {};
12393 // IDs of parent tooltips where we removed the title attribute
12394 this.parents = {};
12395
12396 if ( this.options.disabled ) {
12397 this._disable();
12398 }
12399 },
12400
12401 _setOption: function( key, value ) {
12402 var that = this;
12403
12404 if ( key === "disabled" ) {
12405 this[ value ? "_disable" : "_enable" ]();
12406 this.options[ key ] = value;
12407 // disable element style changes
12408 return;
12409 }
12410
12411 this._super( key, value );
12412
12413 if ( key === "content" ) {
12414 $.each( this.tooltips, function( id, element ) {
12415 that._updateContent( element );
12416 });
12417 }
12418 },
12419
12420 _disable: function() {
12421 var that = this;
12422
12423 // close open tooltips
12424 $.each( this.tooltips, function( id, element ) {
12425 var event = $.Event( "blur" );
12426 event.target = event.currentTarget = element[0];
12427 that.close( event, true );
12428 });
12429
12430 // remove title attributes to prevent native tooltips
12431 this.element.find( this.options.items ).addBack().each(function() {
12432 var element = $( this );
12433 if ( element.is( "[title]" ) ) {
12434 element
12435 .data( "ui-tooltip-title", element.attr( "title" ) )
12436 .attr( "title", "" );
12437 }
12438 });
12439 },
12440
12441 _enable: function() {
12442 // restore title attributes
12443 this.element.find( this.options.items ).addBack().each(function() {
12444 var element = $( this );
12445 if ( element.data( "ui-tooltip-title" ) ) {
12446 element.attr( "title", element.data( "ui-tooltip-title" ) );
12447 }
12448 });
12449 },
12450
12451 open: function( event ) {
12452 var that = this,
12453 target = $( event ? event.target : this.element )
12454 // we need closest here due to mouseover bubbling,
12455 // but always pointing at the same event target
12456 .closest( this.options.items );
12457
12458 // No element to show a tooltip for or the tooltip is already open
12459 if ( !target.length || target.data( "ui-tooltip-id" ) ) {
12460 return;
12461 }
12462
12463 if ( target.attr( "title" ) ) {
12464 target.data( "ui-tooltip-title", target.attr( "title" ) );
12465 }
12466
12467 target.data( "ui-tooltip-open", true );
12468
12469 // kill parent tooltips, custom or native, for hover
12470 if ( event && event.type === "mouseover" ) {
12471 target.parents().each(function() {
12472 var parent = $( this ),
12473 blurEvent;
12474 if ( parent.data( "ui-tooltip-open" ) ) {
12475 blurEvent = $.Event( "blur" );
12476 blurEvent.target = blurEvent.currentTarget = this;
12477 that.close( blurEvent, true );
12478 }
12479 if ( parent.attr( "title" ) ) {
12480 parent.uniqueId();
12481 that.parents[ this.id ] = {
12482 element: this,
12483 title: parent.attr( "title" )
12484 };
12485 parent.attr( "title", "" );
12486 }
12487 });
12488 }
12489
12490 this._updateContent( target, event );
12491 },
12492
12493 _updateContent: function( target, event ) {
12494 var content,
12495 contentOption = this.options.content,
12496 that = this,
12497 eventType = event ? event.type : null;
12498
12499 if ( typeof contentOption === "string" ) {
12500 return this._open( event, target, contentOption );
12501 }
12502
12503 content = contentOption.call( target[0], function( response ) {
12504 // ignore async response if tooltip was closed already
12505 if ( !target.data( "ui-tooltip-open" ) ) {
12506 return;
12507 }
12508 // IE may instantly serve a cached response for ajax requests
12509 // delay this call to _open so the other call to _open runs first
12510 that._delay(function() {
12511 // jQuery creates a special event for focusin when it doesn't
12512 // exist natively. To improve performance, the native event
12513 // object is reused and the type is changed. Therefore, we can't
12514 // rely on the type being correct after the event finished
12515 // bubbling, so we set it back to the previous value. (#8740)
12516 if ( event ) {
12517 event.type = eventType;
12518 }
12519 this._open( event, target, response );
12520 });
12521 });
12522 if ( content ) {
12523 this._open( event, target, content );
12524 }
12525 },
12526
12527 _open: function( event, target, content ) {
12528 var tooltip, events, delayedShow,
12529 positionOption = $.extend( {}, this.options.position );
12530
12531 if ( !content ) {
12532 return;
12533 }
12534
12535 // Content can be updated multiple times. If the tooltip already
12536 // exists, then just update the content and bail.
12537 tooltip = this._find( target );
12538 if ( tooltip.length ) {
12539 tooltip.find( ".ui-tooltip-content" ).html( content );
12540 return;
12541 }
12542
12543 // if we have a title, clear it to prevent the native tooltip
12544 // we have to check first to avoid defining a title if none exists
12545 // (we don't want to cause an element to start matching [title])
12546 //
12547 // We use removeAttr only for key events, to allow IE to export the correct
12548 // accessible attributes. For mouse events, set to empty string to avoid
12549 // native tooltip showing up (happens only when removing inside mouseover).
12550 if ( target.is( "[title]" ) ) {
12551 if ( event && event.type === "mouseover" ) {
12552 target.attr( "title", "" );
12553 } else {
12554 target.removeAttr( "title" );
12555 }
12556 }
12557
12558 tooltip = this._tooltip( target );
12559 addDescribedBy( target, tooltip.attr( "id" ) );
12560 tooltip.find( ".ui-tooltip-content" ).html( content );
12561
12562 function position( event ) {
12563 positionOption.of = event;
12564 if ( tooltip.is( ":hidden" ) ) {
12565 return;
12566 }
12567 tooltip.position( positionOption );
12568 }
12569 if ( this.options.track && event && /^mouse/.test( event.type ) ) {
12570 this._on( this.document, {
12571 mousemove: position
12572 });
12573 // trigger once to override element-relative positioning
12574 position( event );
12575 } else {
12576 tooltip.position( $.extend({
12577 of: target
12578 }, this.options.position ) );
12579 }
12580
12581 tooltip.hide();
12582
12583 this._show( tooltip, this.options.show );
12584 // Handle tracking tooltips that are shown with a delay (#8644). As soon
12585 // as the tooltip is visible, position the tooltip using the most recent
12586 // event.
12587 if ( this.options.show && this.options.show.delay ) {
12588 delayedShow = this.delayedShow = setInterval(function() {
12589 if ( tooltip.is( ":visible" ) ) {
12590 position( positionOption.of );
12591 clearInterval( delayedShow );
12592 }
12593 }, $.fx.interval );
12594 }
12595
12596 this._trigger( "open", event, { tooltip: tooltip } );
12597
12598 events = {
12599 keyup: function( event ) {
12600 if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
12601 var fakeEvent = $.Event(event);
12602 fakeEvent.currentTarget = target[0];
12603 this.close( fakeEvent, true );
12604 }
12605 },
12606 remove: function() {
12607 this._removeTooltip( tooltip );
12608 }
12609 };
12610 if ( !event || event.type === "mouseover" ) {
12611 events.mouseleave = "close";
12612 }
12613 if ( !event || event.type === "focusin" ) {
12614 events.focusout = "close";
12615 }
12616 this._on( true, target, events );
12617 },
12618
12619 close: function( event ) {
12620 var that = this,
12621 target = $( event ? event.currentTarget : this.element ),
12622 tooltip = this._find( target );
12623
12624 // disabling closes the tooltip, so we need to track when we're closing
12625 // to avoid an infinite loop in case the tooltip becomes disabled on close
12626 if ( this.closing ) {
12627 return;
12628 }
12629
12630 // Clear the interval for delayed tracking tooltips
12631 clearInterval( this.delayedShow );
12632
12633 // only set title if we had one before (see comment in _open())
12634 if ( target.data( "ui-tooltip-title" ) ) {
12635 target.attr( "title", target.data( "ui-tooltip-title" ) );
12636 }
12637
12638 removeDescribedBy( target );
12639
12640 tooltip.stop( true );
12641 this._hide( tooltip, this.options.hide, function() {
12642 that._removeTooltip( $( this ) );
12643 });
12644
12645 target.removeData( "ui-tooltip-open" );
12646 this._off( target, "mouseleave focusout keyup" );
12647 // Remove 'remove' binding only on delegated targets
12648 if ( target[0] !== this.element[0] ) {
12649 this._off( target, "remove" );
12650 }
12651 this._off( this.document, "mousemove" );
12652
12653 if ( event && event.type === "mouseleave" ) {
12654 $.each( this.parents, function( id, parent ) {
12655 $( parent.element ).attr( "title", parent.title );
12656 delete that.parents[ id ];
12657 });
12658 }
12659
12660 this.closing = true;
12661 this._trigger( "close", event, { tooltip: tooltip } );
12662 this.closing = false;
12663 },
12664
12665 _tooltip: function( element ) {
12666 var id = "ui-tooltip-" + increments++,
12667 tooltip = $( "<div>" )
12668 .attr({
12669 id: id,
12670 role: "tooltip"
12671 })
12672 .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
12673 ( this.options.tooltipClass || "" ) );
12674 $( "<div>" )
12675 .addClass( "ui-tooltip-content" )
12676 .appendTo( tooltip );
12677 tooltip.appendTo( this.document[0].body );
12678 this.tooltips[ id ] = element;
12679 return tooltip;
12680 },
12681
12682 _find: function( target ) {
12683 var id = target.data( "ui-tooltip-id" );
12684 return id ? $( "#" + id ) : $();
12685 },
12686
12687 _removeTooltip: function( tooltip ) {
12688 tooltip.remove();
12689 delete this.tooltips[ tooltip.attr( "id" ) ];
12690 },
12691
12692 _destroy: function() {
12693 var that = this;
12694
12695 // close open tooltips
12696 $.each( this.tooltips, function( id, element ) {
12697 // Delegate to close method to handle common cleanup
12698 var event = $.Event( "blur" );
12699 event.target = event.currentTarget = element[0];
12700 that.close( event, true );
12701
12702 // Remove immediately; destroying an open tooltip doesn't use the
12703 // hide animation
12704 $( "#" + id ).remove();
12705
12706 // Restore the title
12707 if ( element.data( "ui-tooltip-title" ) ) {
12708 element.attr( "title", element.data( "ui-tooltip-title" ) );
12709 element.removeData( "ui-tooltip-title" );
12710 }
12711 });
12712 }
12713 });
12714
12715 }( jQuery ) );
12716 (function($, undefined) {
12717
12718 var dataSpace = "ui-effects-";
12719
12720 $.effects = {
12721 effect: {}
12722 };
12723
12724 /*!
12725 * jQuery Color Animations v2.1.2
12726 * https://github.com/jquery/jquery-color
12727 *
12728 * Copyright 2013 jQuery Foundation and other contributors
12729 * Released under the MIT license.
12730 * http://jquery.org/license
12731 *
12732 * Date: Wed Jan 16 08:47:09 2013 -0600
12733 */
12734 (function( jQuery, undefined ) {
12735
12736 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
12737
12738 // plusequals test for += 100 -= 100
12739 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
12740 // a set of RE's that can match strings and generate color tuples.
12741 stringParsers = [{
12742 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
12743 parse: function( execResult ) {
12744 return [
12745 execResult[ 1 ],
12746 execResult[ 2 ],
12747 execResult[ 3 ],
12748 execResult[ 4 ]
12749 ];
12750 }
12751 }, {
12752 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
12753 parse: function( execResult ) {
12754 return [
12755 execResult[ 1 ] * 2.55,
12756 execResult[ 2 ] * 2.55,
12757 execResult[ 3 ] * 2.55,
12758 execResult[ 4 ]
12759 ];
12760 }
12761 }, {
12762 // this regex ignores A-F because it's compared against an already lowercased string
12763 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
12764 parse: function( execResult ) {
12765 return [
12766 parseInt( execResult[ 1 ], 16 ),
12767 parseInt( execResult[ 2 ], 16 ),
12768 parseInt( execResult[ 3 ], 16 )
12769 ];
12770 }
12771 }, {
12772 // this regex ignores A-F because it's compared against an already lowercased string
12773 re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
12774 parse: function( execResult ) {
12775 return [
12776 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
12777 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
12778 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
12779 ];
12780 }
12781 }, {
12782 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
12783 space: "hsla",
12784 parse: function( execResult ) {
12785 return [
12786 execResult[ 1 ],
12787 execResult[ 2 ] / 100,
12788 execResult[ 3 ] / 100,
12789 execResult[ 4 ]
12790 ];
12791 }
12792 }],
12793
12794 // jQuery.Color( )
12795 color = jQuery.Color = function( color, green, blue, alpha ) {
12796 return new jQuery.Color.fn.parse( color, green, blue, alpha );
12797 },
12798 spaces = {
12799 rgba: {
12800 props: {
12801 red: {
12802 idx: 0,
12803 type: "byte"
12804 },
12805 green: {
12806 idx: 1,
12807 type: "byte"
12808 },
12809 blue: {
12810 idx: 2,
12811 type: "byte"
12812 }
12813 }
12814 },
12815
12816 hsla: {
12817 props: {
12818 hue: {
12819 idx: 0,
12820 type: "degrees"
12821 },
12822 saturation: {
12823 idx: 1,
12824 type: "percent"
12825 },
12826 lightness: {
12827 idx: 2,
12828 type: "percent"
12829 }
12830 }
12831 }
12832 },
12833 propTypes = {
12834 "byte": {
12835 floor: true,
12836 max: 255
12837 },
12838 "percent": {
12839 max: 1
12840 },
12841 "degrees": {
12842 mod: 360,
12843 floor: true
12844 }
12845 },
12846 support = color.support = {},
12847
12848 // element for support tests
12849 supportElem = jQuery( "<p>" )[ 0 ],
12850
12851 // colors = jQuery.Color.names
12852 colors,
12853
12854 // local aliases of functions called often
12855 each = jQuery.each;
12856
12857 // determine rgba support immediately
12858 supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
12859 support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
12860
12861 // define cache name and alpha properties
12862 // for rgba and hsla spaces
12863 each( spaces, function( spaceName, space ) {
12864 space.cache = "_" + spaceName;
12865 space.props.alpha = {
12866 idx: 3,
12867 type: "percent",
12868 def: 1
12869 };
12870 });
12871
12872 function clamp( value, prop, allowEmpty ) {
12873 var type = propTypes[ prop.type ] || {};
12874
12875 if ( value == null ) {
12876 return (allowEmpty || !prop.def) ? null : prop.def;
12877 }
12878
12879 // ~~ is an short way of doing floor for positive numbers
12880 value = type.floor ? ~~value : parseFloat( value );
12881
12882 // IE will pass in empty strings as value for alpha,
12883 // which will hit this case
12884 if ( isNaN( value ) ) {
12885 return prop.def;
12886 }
12887
12888 if ( type.mod ) {
12889 // we add mod before modding to make sure that negatives values
12890 // get converted properly: -10 -> 350
12891 return (value + type.mod) % type.mod;
12892 }
12893
12894 // for now all property types without mod have min and max
12895 return 0 > value ? 0 : type.max < value ? type.max : value;
12896 }
12897
12898 function stringParse( string ) {
12899 var inst = color(),
12900 rgba = inst._rgba = [];
12901
12902 string = string.toLowerCase();
12903
12904 each( stringParsers, function( i, parser ) {
12905 var parsed,
12906 match = parser.re.exec( string ),
12907 values = match && parser.parse( match ),
12908 spaceName = parser.space || "rgba";
12909
12910 if ( values ) {
12911 parsed = inst[ spaceName ]( values );
12912
12913 // if this was an rgba parse the assignment might happen twice
12914 // oh well....
12915 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
12916 rgba = inst._rgba = parsed._rgba;
12917
12918 // exit each( stringParsers ) here because we matched
12919 return false;
12920 }
12921 });
12922
12923 // Found a stringParser that handled it
12924 if ( rgba.length ) {
12925
12926 // if this came from a parsed string, force "transparent" when alpha is 0
12927 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
12928 if ( rgba.join() === "0,0,0,0" ) {
12929 jQuery.extend( rgba, colors.transparent );
12930 }
12931 return inst;
12932 }
12933
12934 // named colors
12935 return colors[ string ];
12936 }
12937
12938 color.fn = jQuery.extend( color.prototype, {
12939 parse: function( red, green, blue, alpha ) {
12940 if ( red === undefined ) {
12941 this._rgba = [ null, null, null, null ];
12942 return this;
12943 }
12944 if ( red.jquery || red.nodeType ) {
12945 red = jQuery( red ).css( green );
12946 green = undefined;
12947 }
12948
12949 var inst = this,
12950 type = jQuery.type( red ),
12951 rgba = this._rgba = [];
12952
12953 // more than 1 argument specified - assume ( red, green, blue, alpha )
12954 if ( green !== undefined ) {
12955 red = [ red, green, blue, alpha ];
12956 type = "array";
12957 }
12958
12959 if ( type === "string" ) {
12960 return this.parse( stringParse( red ) || colors._default );
12961 }
12962
12963 if ( type === "array" ) {
12964 each( spaces.rgba.props, function( key, prop ) {
12965 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
12966 });
12967 return this;
12968 }
12969
12970 if ( type === "object" ) {
12971 if ( red instanceof color ) {
12972 each( spaces, function( spaceName, space ) {
12973 if ( red[ space.cache ] ) {
12974 inst[ space.cache ] = red[ space.cache ].slice();
12975 }
12976 });
12977 } else {
12978 each( spaces, function( spaceName, space ) {
12979 var cache = space.cache;
12980 each( space.props, function( key, prop ) {
12981
12982 // if the cache doesn't exist, and we know how to convert
12983 if ( !inst[ cache ] && space.to ) {
12984
12985 // if the value was null, we don't need to copy it
12986 // if the key was alpha, we don't need to copy it either
12987 if ( key === "alpha" || red[ key ] == null ) {
12988 return;
12989 }
12990 inst[ cache ] = space.to( inst._rgba );
12991 }
12992
12993 // this is the only case where we allow nulls for ALL properties.
12994 // call clamp with alwaysAllowEmpty
12995 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
12996 });
12997
12998 // everything defined but alpha?
12999 if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
13000 // use the default of 1
13001 inst[ cache ][ 3 ] = 1;
13002 if ( space.from ) {
13003 inst._rgba = space.from( inst[ cache ] );
13004 }
13005 }
13006 });
13007 }
13008 return this;
13009 }
13010 },
13011 is: function( compare ) {
13012 var is = color( compare ),
13013 same = true,
13014 inst = this;
13015
13016 each( spaces, function( _, space ) {
13017 var localCache,
13018 isCache = is[ space.cache ];
13019 if (isCache) {
13020 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
13021 each( space.props, function( _, prop ) {
13022 if ( isCache[ prop.idx ] != null ) {
13023 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
13024 return same;
13025 }
13026 });
13027 }
13028 return same;
13029 });
13030 return same;
13031 },
13032 _space: function() {
13033 var used = [],
13034 inst = this;
13035 each( spaces, function( spaceName, space ) {
13036 if ( inst[ space.cache ] ) {
13037 used.push( spaceName );
13038 }
13039 });
13040 return used.pop();
13041 },
13042 transition: function( other, distance ) {
13043 var end = color( other ),
13044 spaceName = end._space(),
13045 space = spaces[ spaceName ],
13046 startColor = this.alpha() === 0 ? color( "transparent" ) : this,
13047 start = startColor[ space.cache ] || space.to( startColor._rgba ),
13048 result = start.slice();
13049
13050 end = end[ space.cache ];
13051 each( space.props, function( key, prop ) {
13052 var index = prop.idx,
13053 startValue = start[ index ],
13054 endValue = end[ index ],
13055 type = propTypes[ prop.type ] || {};
13056
13057 // if null, don't override start value
13058 if ( endValue === null ) {
13059 return;
13060 }
13061 // if null - use end
13062 if ( startValue === null ) {
13063 result[ index ] = endValue;
13064 } else {
13065 if ( type.mod ) {
13066 if ( endValue - startValue > type.mod / 2 ) {
13067 startValue += type.mod;
13068 } else if ( startValue - endValue > type.mod / 2 ) {
13069 startValue -= type.mod;
13070 }
13071 }
13072 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
13073 }
13074 });
13075 return this[ spaceName ]( result );
13076 },
13077 blend: function( opaque ) {
13078 // if we are already opaque - return ourself
13079 if ( this._rgba[ 3 ] === 1 ) {
13080 return this;
13081 }
13082
13083 var rgb = this._rgba.slice(),
13084 a = rgb.pop(),
13085 blend = color( opaque )._rgba;
13086
13087 return color( jQuery.map( rgb, function( v, i ) {
13088 return ( 1 - a ) * blend[ i ] + a * v;
13089 }));
13090 },
13091 toRgbaString: function() {
13092 var prefix = "rgba(",
13093 rgba = jQuery.map( this._rgba, function( v, i ) {
13094 return v == null ? ( i > 2 ? 1 : 0 ) : v;
13095 });
13096
13097 if ( rgba[ 3 ] === 1 ) {
13098 rgba.pop();
13099 prefix = "rgb(";
13100 }
13101
13102 return prefix + rgba.join() + ")";
13103 },
13104 toHslaString: function() {
13105 var prefix = "hsla(",
13106 hsla = jQuery.map( this.hsla(), function( v, i ) {
13107 if ( v == null ) {
13108 v = i > 2 ? 1 : 0;
13109 }
13110
13111 // catch 1 and 2
13112 if ( i && i < 3 ) {
13113 v = Math.round( v * 100 ) + "%";
13114 }
13115 return v;
13116 });
13117
13118 if ( hsla[ 3 ] === 1 ) {
13119 hsla.pop();
13120 prefix = "hsl(";
13121 }
13122 return prefix + hsla.join() + ")";
13123 },
13124 toHexString: function( includeAlpha ) {
13125 var rgba = this._rgba.slice(),
13126 alpha = rgba.pop();
13127
13128 if ( includeAlpha ) {
13129 rgba.push( ~~( alpha * 255 ) );
13130 }
13131
13132 return "#" + jQuery.map( rgba, function( v ) {
13133
13134 // default to 0 when nulls exist
13135 v = ( v || 0 ).toString( 16 );
13136 return v.length === 1 ? "0" + v : v;
13137 }).join("");
13138 },
13139 toString: function() {
13140 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
13141 }
13142 });
13143 color.fn.parse.prototype = color.fn;
13144
13145 // hsla conversions adapted from:
13146 // https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
13147
13148 function hue2rgb( p, q, h ) {
13149 h = ( h + 1 ) % 1;
13150 if ( h * 6 < 1 ) {
13151 return p + (q - p) * h * 6;
13152 }
13153 if ( h * 2 < 1) {
13154 return q;
13155 }
13156 if ( h * 3 < 2 ) {
13157 return p + (q - p) * ((2/3) - h) * 6;
13158 }
13159 return p;
13160 }
13161
13162 spaces.hsla.to = function ( rgba ) {
13163 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
13164 return [ null, null, null, rgba[ 3 ] ];
13165 }
13166 var r = rgba[ 0 ] / 255,
13167 g = rgba[ 1 ] / 255,
13168 b = rgba[ 2 ] / 255,
13169 a = rgba[ 3 ],
13170 max = Math.max( r, g, b ),
13171 min = Math.min( r, g, b ),
13172 diff = max - min,
13173 add = max + min,
13174 l = add * 0.5,
13175 h, s;
13176
13177 if ( min === max ) {
13178 h = 0;
13179 } else if ( r === max ) {
13180 h = ( 60 * ( g - b ) / diff ) + 360;
13181 } else if ( g === max ) {
13182 h = ( 60 * ( b - r ) / diff ) + 120;
13183 } else {
13184 h = ( 60 * ( r - g ) / diff ) + 240;
13185 }
13186
13187 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
13188 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
13189 if ( diff === 0 ) {
13190 s = 0;
13191 } else if ( l <= 0.5 ) {
13192 s = diff / add;
13193 } else {
13194 s = diff / ( 2 - add );
13195 }
13196 return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
13197 };
13198
13199 spaces.hsla.from = function ( hsla ) {
13200 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
13201 return [ null, null, null, hsla[ 3 ] ];
13202 }
13203 var h = hsla[ 0 ] / 360,
13204 s = hsla[ 1 ],
13205 l = hsla[ 2 ],
13206 a = hsla[ 3 ],
13207 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
13208 p = 2 * l - q;
13209
13210 return [
13211 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
13212 Math.round( hue2rgb( p, q, h ) * 255 ),
13213 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
13214 a
13215 ];
13216 };
13217
13218
13219 each( spaces, function( spaceName, space ) {
13220 var props = space.props,
13221 cache = space.cache,
13222 to = space.to,
13223 from = space.from;
13224
13225 // makes rgba() and hsla()
13226 color.fn[ spaceName ] = function( value ) {
13227
13228 // generate a cache for this space if it doesn't exist
13229 if ( to && !this[ cache ] ) {
13230 this[ cache ] = to( this._rgba );
13231 }
13232 if ( value === undefined ) {
13233 return this[ cache ].slice();
13234 }
13235
13236 var ret,
13237 type = jQuery.type( value ),
13238 arr = ( type === "array" || type === "object" ) ? value : arguments,
13239 local = this[ cache ].slice();
13240
13241 each( props, function( key, prop ) {
13242 var val = arr[ type === "object" ? key : prop.idx ];
13243 if ( val == null ) {
13244 val = local[ prop.idx ];
13245 }
13246 local[ prop.idx ] = clamp( val, prop );
13247 });
13248
13249 if ( from ) {
13250 ret = color( from( local ) );
13251 ret[ cache ] = local;
13252 return ret;
13253 } else {
13254 return color( local );
13255 }
13256 };
13257
13258 // makes red() green() blue() alpha() hue() saturation() lightness()
13259 each( props, function( key, prop ) {
13260 // alpha is included in more than one space
13261 if ( color.fn[ key ] ) {
13262 return;
13263 }
13264 color.fn[ key ] = function( value ) {
13265 var vtype = jQuery.type( value ),
13266 fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
13267 local = this[ fn ](),
13268 cur = local[ prop.idx ],
13269 match;
13270
13271 if ( vtype === "undefined" ) {
13272 return cur;
13273 }
13274
13275 if ( vtype === "function" ) {
13276 value = value.call( this, cur );
13277 vtype = jQuery.type( value );
13278 }
13279 if ( value == null && prop.empty ) {
13280 return this;
13281 }
13282 if ( vtype === "string" ) {
13283 match = rplusequals.exec( value );
13284 if ( match ) {
13285 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
13286 }
13287 }
13288 local[ prop.idx ] = value;
13289 return this[ fn ]( local );
13290 };
13291 });
13292 });
13293
13294 // add cssHook and .fx.step function for each named hook.
13295 // accept a space separated string of properties
13296 color.hook = function( hook ) {
13297 var hooks = hook.split( " " );
13298 each( hooks, function( i, hook ) {
13299 jQuery.cssHooks[ hook ] = {
13300 set: function( elem, value ) {
13301 var parsed, curElem,
13302 backgroundColor = "";
13303
13304 if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
13305 value = color( parsed || value );
13306 if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
13307 curElem = hook === "backgroundColor" ? elem.parentNode : elem;
13308 while (
13309 (backgroundColor === "" || backgroundColor === "transparent") &&
13310 curElem && curElem.style
13311 ) {
13312 try {
13313 backgroundColor = jQuery.css( curElem, "backgroundColor" );
13314 curElem = curElem.parentNode;
13315 } catch ( e ) {
13316 }
13317 }
13318
13319 value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
13320 backgroundColor :
13321 "_default" );
13322 }
13323
13324 value = value.toRgbaString();
13325 }
13326 try {
13327 elem.style[ hook ] = value;
13328 } catch( e ) {
13329 // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
13330 }
13331 }
13332 };
13333 jQuery.fx.step[ hook ] = function( fx ) {
13334 if ( !fx.colorInit ) {
13335 fx.start = color( fx.elem, hook );
13336 fx.end = color( fx.end );
13337 fx.colorInit = true;
13338 }
13339 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
13340 };
13341 });
13342
13343 };
13344
13345 color.hook( stepHooks );
13346
13347 jQuery.cssHooks.borderColor = {
13348 expand: function( value ) {
13349 var expanded = {};
13350
13351 each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
13352 expanded[ "border" + part + "Color" ] = value;
13353 });
13354 return expanded;
13355 }
13356 };
13357
13358 // Basic color names only.
13359 // Usage of any of the other color names requires adding yourself or including
13360 // jquery.color.svg-names.js.
13361 colors = jQuery.Color.names = {
13362 // 4.1. Basic color keywords
13363 aqua: "#00ffff",
13364 black: "#000000",
13365 blue: "#0000ff",
13366 fuchsia: "#ff00ff",
13367 gray: "#808080",
13368 green: "#008000",
13369 lime: "#00ff00",
13370 maroon: "#800000",
13371 navy: "#000080",
13372 olive: "#808000",
13373 purple: "#800080",
13374 red: "#ff0000",
13375 silver: "#c0c0c0",
13376 teal: "#008080",
13377 white: "#ffffff",
13378 yellow: "#ffff00",
13379
13380 // 4.2.3. "transparent" color keyword
13381 transparent: [ null, null, null, 0 ],
13382
13383 _default: "#ffffff"
13384 };
13385
13386 })( jQuery );
13387
13388
13389 /******************************************************************************/
13390 /****************************** CLASS ANIMATIONS ******************************/
13391 /******************************************************************************/
13392 (function() {
13393
13394 var classAnimationActions = [ "add", "remove", "toggle" ],
13395 shorthandStyles = {
13396 border: 1,
13397 borderBottom: 1,
13398 borderColor: 1,
13399 borderLeft: 1,
13400 borderRight: 1,
13401 borderTop: 1,
13402 borderWidth: 1,
13403 margin: 1,
13404 padding: 1
13405 };
13406
13407 $.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
13408 $.fx.step[ prop ] = function( fx ) {
13409 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
13410 jQuery.style( fx.elem, prop, fx.end );
13411 fx.setAttr = true;
13412 }
13413 };
13414 });
13415
13416 function getElementStyles( elem ) {
13417 var key, len,
13418 style = elem.ownerDocument.defaultView ?
13419 elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
13420 elem.currentStyle,
13421 styles = {};
13422
13423 if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
13424 len = style.length;
13425 while ( len-- ) {
13426 key = style[ len ];
13427 if ( typeof style[ key ] === "string" ) {
13428 styles[ $.camelCase( key ) ] = style[ key ];
13429 }
13430 }
13431 // support: Opera, IE <9
13432 } else {
13433 for ( key in style ) {
13434 if ( typeof style[ key ] === "string" ) {
13435 styles[ key ] = style[ key ];
13436 }
13437 }
13438 }
13439
13440 return styles;
13441 }
13442
13443
13444 function styleDifference( oldStyle, newStyle ) {
13445 var diff = {},
13446 name, value;
13447
13448 for ( name in newStyle ) {
13449 value = newStyle[ name ];
13450 if ( oldStyle[ name ] !== value ) {
13451 if ( !shorthandStyles[ name ] ) {
13452 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
13453 diff[ name ] = value;
13454 }
13455 }
13456 }
13457 }
13458
13459 return diff;
13460 }
13461
13462 // support: jQuery <1.8
13463 if ( !$.fn.addBack ) {
13464 $.fn.addBack = function( selector ) {
13465 return this.add( selector == null ?
13466 this.prevObject : this.prevObject.filter( selector )
13467 );
13468 };
13469 }
13470
13471 $.effects.animateClass = function( value, duration, easing, callback ) {
13472 var o = $.speed( duration, easing, callback );
13473
13474 return this.queue( function() {
13475 var animated = $( this ),
13476 baseClass = animated.attr( "class" ) || "",
13477 applyClassChange,
13478 allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
13479
13480 // map the animated objects to store the original styles.
13481 allAnimations = allAnimations.map(function() {
13482 var el = $( this );
13483 return {
13484 el: el,
13485 start: getElementStyles( this )
13486 };
13487 });
13488
13489 // apply class change
13490 applyClassChange = function() {
13491 $.each( classAnimationActions, function(i, action) {
13492 if ( value[ action ] ) {
13493 animated[ action + "Class" ]( value[ action ] );
13494 }
13495 });
13496 };
13497 applyClassChange();
13498
13499 // map all animated objects again - calculate new styles and diff
13500 allAnimations = allAnimations.map(function() {
13501 this.end = getElementStyles( this.el[ 0 ] );
13502 this.diff = styleDifference( this.start, this.end );
13503 return this;
13504 });
13505
13506 // apply original class
13507 animated.attr( "class", baseClass );
13508
13509 // map all animated objects again - this time collecting a promise
13510 allAnimations = allAnimations.map(function() {
13511 var styleInfo = this,
13512 dfd = $.Deferred(),
13513 opts = $.extend({}, o, {
13514 queue: false,
13515 complete: function() {
13516 dfd.resolve( styleInfo );
13517 }
13518 });
13519
13520 this.el.animate( this.diff, opts );
13521 return dfd.promise();
13522 });
13523
13524 // once all animations have completed:
13525 $.when.apply( $, allAnimations.get() ).done(function() {
13526
13527 // set the final class
13528 applyClassChange();
13529
13530 // for each animated element,
13531 // clear all css properties that were animated
13532 $.each( arguments, function() {
13533 var el = this.el;
13534 $.each( this.diff, function(key) {
13535 el.css( key, "" );
13536 });
13537 });
13538
13539 // this is guarnteed to be there if you use jQuery.speed()
13540 // it also handles dequeuing the next anim...
13541 o.complete.call( animated[ 0 ] );
13542 });
13543 });
13544 };
13545
13546 $.fn.extend({
13547 addClass: (function( orig ) {
13548 return function( classNames, speed, easing, callback ) {
13549 return speed ?
13550 $.effects.animateClass.call( this,
13551 { add: classNames }, speed, easing, callback ) :
13552 orig.apply( this, arguments );
13553 };
13554 })( $.fn.addClass ),
13555
13556 removeClass: (function( orig ) {
13557 return function( classNames, speed, easing, callback ) {
13558 return arguments.length > 1 ?
13559 $.effects.animateClass.call( this,
13560 { remove: classNames }, speed, easing, callback ) :
13561 orig.apply( this, arguments );
13562 };
13563 })( $.fn.removeClass ),
13564
13565 toggleClass: (function( orig ) {
13566 return function( classNames, force, speed, easing, callback ) {
13567 if ( typeof force === "boolean" || force === undefined ) {
13568 if ( !speed ) {
13569 // without speed parameter
13570 return orig.apply( this, arguments );
13571 } else {
13572 return $.effects.animateClass.call( this,
13573 (force ? { add: classNames } : { remove: classNames }),
13574 speed, easing, callback );
13575 }
13576 } else {
13577 // without force parameter
13578 return $.effects.animateClass.call( this,
13579 { toggle: classNames }, force, speed, easing );
13580 }
13581 };
13582 })( $.fn.toggleClass ),
13583
13584 switchClass: function( remove, add, speed, easing, callback) {
13585 return $.effects.animateClass.call( this, {
13586 add: add,
13587 remove: remove
13588 }, speed, easing, callback );
13589 }
13590 });
13591
13592 })();
13593
13594 /******************************************************************************/
13595 /*********************************** EFFECTS **********************************/
13596 /******************************************************************************/
13597
13598 (function() {
13599
13600 $.extend( $.effects, {
13601 version: "1.10.3",
13602
13603 // Saves a set of properties in a data storage
13604 save: function( element, set ) {
13605 for( var i=0; i < set.length; i++ ) {
13606 if ( set[ i ] !== null ) {
13607 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
13608 }
13609 }
13610 },
13611
13612 // Restores a set of previously saved properties from a data storage
13613 restore: function( element, set ) {
13614 var val, i;
13615 for( i=0; i < set.length; i++ ) {
13616 if ( set[ i ] !== null ) {
13617 val = element.data( dataSpace + set[ i ] );
13618 // support: jQuery 1.6.2
13619 // http://bugs.jquery.com/ticket/9917
13620 // jQuery 1.6.2 incorrectly returns undefined for any falsy value.
13621 // We can't differentiate between "" and 0 here, so we just assume
13622 // empty string since it's likely to be a more common value...
13623 if ( val === undefined ) {
13624 val = "";
13625 }
13626 element.css( set[ i ], val );
13627 }
13628 }
13629 },
13630
13631 setMode: function( el, mode ) {
13632 if (mode === "toggle") {
13633 mode = el.is( ":hidden" ) ? "show" : "hide";
13634 }
13635 return mode;
13636 },
13637
13638 // Translates a [top,left] array into a baseline value
13639 // this should be a little more flexible in the future to handle a string & hash
13640 getBaseline: function( origin, original ) {
13641 var y, x;
13642 switch ( origin[ 0 ] ) {
13643 case "top": y = 0; break;
13644 case "middle": y = 0.5; break;
13645 case "bottom": y = 1; break;
13646 default: y = origin[ 0 ] / original.height;
13647 }
13648 switch ( origin[ 1 ] ) {
13649 case "left": x = 0; break;
13650 case "center": x = 0.5; break;
13651 case "right": x = 1; break;
13652 default: x = origin[ 1 ] / original.width;
13653 }
13654 return {
13655 x: x,
13656 y: y
13657 };
13658 },
13659
13660 // Wraps the element around a wrapper that copies position properties
13661 createWrapper: function( element ) {
13662
13663 // if the element is already wrapped, return it
13664 if ( element.parent().is( ".ui-effects-wrapper" )) {
13665 return element.parent();
13666 }
13667
13668 // wrap the element
13669 var props = {
13670 width: element.outerWidth(true),
13671 height: element.outerHeight(true),
13672 "float": element.css( "float" )
13673 },
13674 wrapper = $( "<div></div>" )
13675 .addClass( "ui-effects-wrapper" )
13676 .css({
13677 fontSize: "100%",
13678 background: "transparent",
13679 border: "none",
13680 margin: 0,
13681 padding: 0
13682 }),
13683 // Store the size in case width/height are defined in % - Fixes #5245
13684 size = {
13685 width: element.width(),
13686 height: element.height()
13687 },
13688 active = document.activeElement;
13689
13690 // support: Firefox
13691 // Firefox incorrectly exposes anonymous content
13692 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
13693 try {
13694 active.id;
13695 } catch( e ) {
13696 active = document.body;
13697 }
13698
13699 element.wrap( wrapper );
13700
13701 // Fixes #7595 - Elements lose focus when wrapped.
13702 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
13703 $( active ).focus();
13704 }
13705
13706 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
13707
13708 // transfer positioning properties to the wrapper
13709 if ( element.css( "position" ) === "static" ) {
13710 wrapper.css({ position: "relative" });
13711 element.css({ position: "relative" });
13712 } else {
13713 $.extend( props, {
13714 position: element.css( "position" ),
13715 zIndex: element.css( "z-index" )
13716 });
13717 $.each([ "top", "left", "bottom", "right" ], function(i, pos) {
13718 props[ pos ] = element.css( pos );
13719 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
13720 props[ pos ] = "auto";
13721 }
13722 });
13723 element.css({
13724 position: "relative",
13725 top: 0,
13726 left: 0,
13727 right: "auto",
13728 bottom: "auto"
13729 });
13730 }
13731 element.css(size);
13732
13733 return wrapper.css( props ).show();
13734 },
13735
13736 removeWrapper: function( element ) {
13737 var active = document.activeElement;
13738
13739 if ( element.parent().is( ".ui-effects-wrapper" ) ) {
13740 element.parent().replaceWith( element );
13741
13742 // Fixes #7595 - Elements lose focus when wrapped.
13743 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
13744 $( active ).focus();
13745 }
13746 }
13747
13748
13749 return element;
13750 },
13751
13752 setTransition: function( element, list, factor, value ) {
13753 value = value || {};
13754 $.each( list, function( i, x ) {
13755 var unit = element.cssUnit( x );
13756 if ( unit[ 0 ] > 0 ) {
13757 value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
13758 }
13759 });
13760 return value;
13761 }
13762 });
13763
13764 // return an effect options object for the given parameters:
13765 function _normalizeArguments( effect, options, speed, callback ) {
13766
13767 // allow passing all options as the first parameter
13768 if ( $.isPlainObject( effect ) ) {
13769 options = effect;
13770 effect = effect.effect;
13771 }
13772
13773 // convert to an object
13774 effect = { effect: effect };
13775
13776 // catch (effect, null, ...)
13777 if ( options == null ) {
13778 options = {};
13779 }
13780
13781 // catch (effect, callback)
13782 if ( $.isFunction( options ) ) {
13783 callback = options;
13784 speed = null;
13785 options = {};
13786 }
13787
13788 // catch (effect, speed, ?)
13789 if ( typeof options === "number" || $.fx.speeds[ options ] ) {
13790 callback = speed;
13791 speed = options;
13792 options = {};
13793 }
13794
13795 // catch (effect, options, callback)
13796 if ( $.isFunction( speed ) ) {
13797 callback = speed;
13798 speed = null;
13799 }
13800
13801 // add options to effect
13802 if ( options ) {
13803 $.extend( effect, options );
13804 }
13805
13806 speed = speed || options.duration;
13807 effect.duration = $.fx.off ? 0 :
13808 typeof speed === "number" ? speed :
13809 speed in $.fx.speeds ? $.fx.speeds[ speed ] :
13810 $.fx.speeds._default;
13811
13812 effect.complete = callback || options.complete;
13813
13814 return effect;
13815 }
13816
13817 function standardAnimationOption( option ) {
13818 // Valid standard speeds (nothing, number, named speed)
13819 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
13820 return true;
13821 }
13822
13823 // Invalid strings - treat as "normal" speed
13824 if ( typeof option === "string" && !$.effects.effect[ option ] ) {
13825 return true;
13826 }
13827
13828 // Complete callback
13829 if ( $.isFunction( option ) ) {
13830 return true;
13831 }
13832
13833 // Options hash (but not naming an effect)
13834 if ( typeof option === "object" && !option.effect ) {
13835 return true;
13836 }
13837
13838 // Didn't match any standard API
13839 return false;
13840 }
13841
13842 $.fn.extend({
13843 effect: function( /* effect, options, speed, callback */ ) {
13844 var args = _normalizeArguments.apply( this, arguments ),
13845 mode = args.mode,
13846 queue = args.queue,
13847 effectMethod = $.effects.effect[ args.effect ];
13848
13849 if ( $.fx.off || !effectMethod ) {
13850 // delegate to the original method (e.g., .show()) if possible
13851 if ( mode ) {
13852 return this[ mode ]( args.duration, args.complete );
13853 } else {
13854 return this.each( function() {
13855 if ( args.complete ) {
13856 args.complete.call( this );
13857 }
13858 });
13859 }
13860 }
13861
13862 function run( next ) {
13863 var elem = $( this ),
13864 complete = args.complete,
13865 mode = args.mode;
13866
13867 function done() {
13868 if ( $.isFunction( complete ) ) {
13869 complete.call( elem[0] );
13870 }
13871 if ( $.isFunction( next ) ) {
13872 next();
13873 }
13874 }
13875
13876 // If the element already has the correct final state, delegate to
13877 // the core methods so the internal tracking of "olddisplay" works.
13878 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
13879 elem[ mode ]();
13880 done();
13881 } else {
13882 effectMethod.call( elem[0], args, done );
13883 }
13884 }
13885
13886 return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
13887 },
13888
13889 show: (function( orig ) {
13890 return function( option ) {
13891 if ( standardAnimationOption( option ) ) {
13892 return orig.apply( this, arguments );
13893 } else {
13894 var args = _normalizeArguments.apply( this, arguments );
13895 args.mode = "show";
13896 return this.effect.call( this, args );
13897 }
13898 };
13899 })( $.fn.show ),
13900
13901 hide: (function( orig ) {
13902 return function( option ) {
13903 if ( standardAnimationOption( option ) ) {
13904 return orig.apply( this, arguments );
13905 } else {
13906 var args = _normalizeArguments.apply( this, arguments );
13907 args.mode = "hide";
13908 return this.effect.call( this, args );
13909 }
13910 };
13911 })( $.fn.hide ),
13912
13913 toggle: (function( orig ) {
13914 return function( option ) {
13915 if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
13916 return orig.apply( this, arguments );
13917 } else {
13918 var args = _normalizeArguments.apply( this, arguments );
13919 args.mode = "toggle";
13920 return this.effect.call( this, args );
13921 }
13922 };
13923 })( $.fn.toggle ),
13924
13925 // helper functions
13926 cssUnit: function(key) {
13927 var style = this.css( key ),
13928 val = [];
13929
13930 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
13931 if ( style.indexOf( unit ) > 0 ) {
13932 val = [ parseFloat( style ), unit ];
13933 }
13934 });
13935 return val;
13936 }
13937 });
13938
13939 })();
13940
13941 /******************************************************************************/
13942 /*********************************** EASING ***********************************/
13943 /******************************************************************************/
13944
13945 (function() {
13946
13947 // based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
13948
13949 var baseEasings = {};
13950
13951 $.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
13952 baseEasings[ name ] = function( p ) {
13953 return Math.pow( p, i + 2 );
13954 };
13955 });
13956
13957 $.extend( baseEasings, {
13958 Sine: function ( p ) {
13959 return 1 - Math.cos( p * Math.PI / 2 );
13960 },
13961 Circ: function ( p ) {
13962 return 1 - Math.sqrt( 1 - p * p );
13963 },
13964 Elastic: function( p ) {
13965 return p === 0 || p === 1 ? p :
13966 -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
13967 },
13968 Back: function( p ) {
13969 return p * p * ( 3 * p - 2 );
13970 },
13971 Bounce: function ( p ) {
13972 var pow2,
13973 bounce = 4;
13974
13975 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
13976 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
13977 }
13978 });
13979
13980 $.each( baseEasings, function( name, easeIn ) {
13981 $.easing[ "easeIn" + name ] = easeIn;
13982 $.easing[ "easeOut" + name ] = function( p ) {
13983 return 1 - easeIn( 1 - p );
13984 };
13985 $.easing[ "easeInOut" + name ] = function( p ) {
13986 return p < 0.5 ?
13987 easeIn( p * 2 ) / 2 :
13988 1 - easeIn( p * -2 + 2 ) / 2;
13989 };
13990 });
13991
13992 })();
13993
13994 })(jQuery);
13995 (function( $, undefined ) {
13996
13997 var rvertical = /up|down|vertical/,
13998 rpositivemotion = /up|left|vertical|horizontal/;
13999
14000 $.effects.effect.blind = function( o, done ) {
14001 // Create element
14002 var el = $( this ),
14003 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
14004 mode = $.effects.setMode( el, o.mode || "hide" ),
14005 direction = o.direction || "up",
14006 vertical = rvertical.test( direction ),
14007 ref = vertical ? "height" : "width",
14008 ref2 = vertical ? "top" : "left",
14009 motion = rpositivemotion.test( direction ),
14010 animation = {},
14011 show = mode === "show",
14012 wrapper, distance, margin;
14013
14014 // if already wrapped, the wrapper's properties are my property. #6245
14015 if ( el.parent().is( ".ui-effects-wrapper" ) ) {
14016 $.effects.save( el.parent(), props );
14017 } else {
14018 $.effects.save( el, props );
14019 }
14020 el.show();
14021 wrapper = $.effects.createWrapper( el ).css({
14022 overflow: "hidden"
14023 });
14024
14025 distance = wrapper[ ref ]();
14026 margin = parseFloat( wrapper.css( ref2 ) ) || 0;
14027
14028 animation[ ref ] = show ? distance : 0;
14029 if ( !motion ) {
14030 el
14031 .css( vertical ? "bottom" : "right", 0 )
14032 .css( vertical ? "top" : "left", "auto" )
14033 .css({ position: "absolute" });
14034
14035 animation[ ref2 ] = show ? margin : distance + margin;
14036 }
14037
14038 // start at 0 if we are showing
14039 if ( show ) {
14040 wrapper.css( ref, 0 );
14041 if ( ! motion ) {
14042 wrapper.css( ref2, margin + distance );
14043 }
14044 }
14045
14046 // Animate
14047 wrapper.animate( animation, {
14048 duration: o.duration,
14049 easing: o.easing,
14050 queue: false,
14051 complete: function() {
14052 if ( mode === "hide" ) {
14053 el.hide();
14054 }
14055 $.effects.restore( el, props );
14056 $.effects.removeWrapper( el );
14057 done();
14058 }
14059 });
14060
14061 };
14062
14063 })(jQuery);
14064 (function( $, undefined ) {
14065
14066 $.effects.effect.bounce = function( o, done ) {
14067 var el = $( this ),
14068 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
14069
14070 // defaults:
14071 mode = $.effects.setMode( el, o.mode || "effect" ),
14072 hide = mode === "hide",
14073 show = mode === "show",
14074 direction = o.direction || "up",
14075 distance = o.distance,
14076 times = o.times || 5,
14077
14078 // number of internal animations
14079 anims = times * 2 + ( show || hide ? 1 : 0 ),
14080 speed = o.duration / anims,
14081 easing = o.easing,
14082
14083 // utility:
14084 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
14085 motion = ( direction === "up" || direction === "left" ),
14086 i,
14087 upAnim,
14088 downAnim,
14089
14090 // we will need to re-assemble the queue to stack our animations in place
14091 queue = el.queue(),
14092 queuelen = queue.length;
14093
14094 // Avoid touching opacity to prevent clearType and PNG issues in IE
14095 if ( show || hide ) {
14096 props.push( "opacity" );
14097 }
14098
14099 $.effects.save( el, props );
14100 el.show();
14101 $.effects.createWrapper( el ); // Create Wrapper
14102
14103 // default distance for the BIGGEST bounce is the outer Distance / 3
14104 if ( !distance ) {
14105 distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
14106 }
14107
14108 if ( show ) {
14109 downAnim = { opacity: 1 };
14110 downAnim[ ref ] = 0;
14111
14112 // if we are showing, force opacity 0 and set the initial position
14113 // then do the "first" animation
14114 el.css( "opacity", 0 )
14115 .css( ref, motion ? -distance * 2 : distance * 2 )
14116 .animate( downAnim, speed, easing );
14117 }
14118
14119 // start at the smallest distance if we are hiding
14120 if ( hide ) {
14121 distance = distance / Math.pow( 2, times - 1 );
14122 }
14123
14124 downAnim = {};
14125 downAnim[ ref ] = 0;
14126 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
14127 for ( i = 0; i < times; i++ ) {
14128 upAnim = {};
14129 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
14130
14131 el.animate( upAnim, speed, easing )
14132 .animate( downAnim, speed, easing );
14133
14134 distance = hide ? distance * 2 : distance / 2;
14135 }
14136
14137 // Last Bounce when Hiding
14138 if ( hide ) {
14139 upAnim = { opacity: 0 };
14140 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
14141
14142 el.animate( upAnim, speed, easing );
14143 }
14144
14145 el.queue(function() {
14146 if ( hide ) {
14147 el.hide();
14148 }
14149 $.effects.restore( el, props );
14150 $.effects.removeWrapper( el );
14151 done();
14152 });
14153
14154 // inject all the animations we just queued to be first in line (after "inprogress")
14155 if ( queuelen > 1) {
14156 queue.splice.apply( queue,
14157 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
14158 }
14159 el.dequeue();
14160
14161 };
14162
14163 })(jQuery);
14164 (function( $, undefined ) {
14165
14166 $.effects.effect.clip = function( o, done ) {
14167 // Create element
14168 var el = $( this ),
14169 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
14170 mode = $.effects.setMode( el, o.mode || "hide" ),
14171 show = mode === "show",
14172 direction = o.direction || "vertical",
14173 vert = direction === "vertical",
14174 size = vert ? "height" : "width",
14175 position = vert ? "top" : "left",
14176 animation = {},
14177 wrapper, animate, distance;
14178
14179 // Save & Show
14180 $.effects.save( el, props );
14181 el.show();
14182
14183 // Create Wrapper
14184 wrapper = $.effects.createWrapper( el ).css({
14185 overflow: "hidden"
14186 });
14187 animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
14188 distance = animate[ size ]();
14189
14190 // Shift
14191 if ( show ) {
14192 animate.css( size, 0 );
14193 animate.css( position, distance / 2 );
14194 }
14195
14196 // Create Animation Object:
14197 animation[ size ] = show ? distance : 0;
14198 animation[ position ] = show ? 0 : distance / 2;
14199
14200 // Animate
14201 animate.animate( animation, {
14202 queue: false,
14203 duration: o.duration,
14204 easing: o.easing,
14205 complete: function() {
14206 if ( !show ) {
14207 el.hide();
14208 }
14209 $.effects.restore( el, props );
14210 $.effects.removeWrapper( el );
14211 done();
14212 }
14213 });
14214
14215 };
14216
14217 })(jQuery);
14218 (function( $, undefined ) {
14219
14220 $.effects.effect.drop = function( o, done ) {
14221
14222 var el = $( this ),
14223 props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
14224 mode = $.effects.setMode( el, o.mode || "hide" ),
14225 show = mode === "show",
14226 direction = o.direction || "left",
14227 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
14228 motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
14229 animation = {
14230 opacity: show ? 1 : 0
14231 },
14232 distance;
14233
14234 // Adjust
14235 $.effects.save( el, props );
14236 el.show();
14237 $.effects.createWrapper( el );
14238
14239 distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2;
14240
14241 if ( show ) {
14242 el
14243 .css( "opacity", 0 )
14244 .css( ref, motion === "pos" ? -distance : distance );
14245 }
14246
14247 // Animation
14248 animation[ ref ] = ( show ?
14249 ( motion === "pos" ? "+=" : "-=" ) :
14250 ( motion === "pos" ? "-=" : "+=" ) ) +
14251 distance;
14252
14253 // Animate
14254 el.animate( animation, {
14255 queue: false,
14256 duration: o.duration,
14257 easing: o.easing,
14258 complete: function() {
14259 if ( mode === "hide" ) {
14260 el.hide();
14261 }
14262 $.effects.restore( el, props );
14263 $.effects.removeWrapper( el );
14264 done();
14265 }
14266 });
14267 };
14268
14269 })(jQuery);
14270 (function( $, undefined ) {
14271
14272 $.effects.effect.explode = function( o, done ) {
14273
14274 var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
14275 cells = rows,
14276 el = $( this ),
14277 mode = $.effects.setMode( el, o.mode || "hide" ),
14278 show = mode === "show",
14279
14280 // show and then visibility:hidden the element before calculating offset
14281 offset = el.show().css( "visibility", "hidden" ).offset(),
14282
14283 // width and height of a piece
14284 width = Math.ceil( el.outerWidth() / cells ),
14285 height = Math.ceil( el.outerHeight() / rows ),
14286 pieces = [],
14287
14288 // loop
14289 i, j, left, top, mx, my;
14290
14291 // children animate complete:
14292 function childComplete() {
14293 pieces.push( this );
14294 if ( pieces.length === rows * cells ) {
14295 animComplete();
14296 }
14297 }
14298
14299 // clone the element for each row and cell.
14300 for( i = 0; i < rows ; i++ ) { // ===>
14301 top = offset.top + i * height;
14302 my = i - ( rows - 1 ) / 2 ;
14303
14304 for( j = 0; j < cells ; j++ ) { // |||
14305 left = offset.left + j * width;
14306 mx = j - ( cells - 1 ) / 2 ;
14307
14308 // Create a clone of the now hidden main element that will be absolute positioned
14309 // within a wrapper div off the -left and -top equal to size of our pieces
14310 el
14311 .clone()
14312 .appendTo( "body" )
14313 .wrap( "<div></div>" )
14314 .css({
14315 position: "absolute",
14316 visibility: "visible",
14317 left: -j * width,
14318 top: -i * height
14319 })
14320
14321 // select the wrapper - make it overflow: hidden and absolute positioned based on
14322 // where the original was located +left and +top equal to the size of pieces
14323 .parent()
14324 .addClass( "ui-effects-explode" )
14325 .css({
14326 position: "absolute",
14327 overflow: "hidden",
14328 width: width,
14329 height: height,
14330 left: left + ( show ? mx * width : 0 ),
14331 top: top + ( show ? my * height : 0 ),
14332 opacity: show ? 0 : 1
14333 }).animate({
14334 left: left + ( show ? 0 : mx * width ),
14335 top: top + ( show ? 0 : my * height ),
14336 opacity: show ? 1 : 0
14337 }, o.duration || 500, o.easing, childComplete );
14338 }
14339 }
14340
14341 function animComplete() {
14342 el.css({
14343 visibility: "visible"
14344 });
14345 $( pieces ).remove();
14346 if ( !show ) {
14347 el.hide();
14348 }
14349 done();
14350 }
14351 };
14352
14353 })(jQuery);
14354 (function( $, undefined ) {
14355
14356 $.effects.effect.fade = function( o, done ) {
14357 var el = $( this ),
14358 mode = $.effects.setMode( el, o.mode || "toggle" );
14359
14360 el.animate({
14361 opacity: mode
14362 }, {
14363 queue: false,
14364 duration: o.duration,
14365 easing: o.easing,
14366 complete: done
14367 });
14368 };
14369
14370 })( jQuery );
14371 (function( $, undefined ) {
14372
14373 $.effects.effect.fold = function( o, done ) {
14374
14375 // Create element
14376 var el = $( this ),
14377 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
14378 mode = $.effects.setMode( el, o.mode || "hide" ),
14379 show = mode === "show",
14380 hide = mode === "hide",
14381 size = o.size || 15,
14382 percent = /([0-9]+)%/.exec( size ),
14383 horizFirst = !!o.horizFirst,
14384 widthFirst = show !== horizFirst,
14385 ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
14386 duration = o.duration / 2,
14387 wrapper, distance,
14388 animation1 = {},
14389 animation2 = {};
14390
14391 $.effects.save( el, props );
14392 el.show();
14393
14394 // Create Wrapper
14395 wrapper = $.effects.createWrapper( el ).css({
14396 overflow: "hidden"
14397 });
14398 distance = widthFirst ?
14399 [ wrapper.width(), wrapper.height() ] :
14400 [ wrapper.height(), wrapper.width() ];
14401
14402 if ( percent ) {
14403 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
14404 }
14405 if ( show ) {
14406 wrapper.css( horizFirst ? {
14407 height: 0,
14408 width: size
14409 } : {
14410 height: size,
14411 width: 0
14412 });
14413 }
14414
14415 // Animation
14416 animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
14417 animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
14418
14419 // Animate
14420 wrapper
14421 .animate( animation1, duration, o.easing )
14422 .animate( animation2, duration, o.easing, function() {
14423 if ( hide ) {
14424 el.hide();
14425 }
14426 $.effects.restore( el, props );
14427 $.effects.removeWrapper( el );
14428 done();
14429 });
14430
14431 };
14432
14433 })(jQuery);
14434 (function( $, undefined ) {
14435
14436 $.effects.effect.highlight = function( o, done ) {
14437 var elem = $( this ),
14438 props = [ "backgroundImage", "backgroundColor", "opacity" ],
14439 mode = $.effects.setMode( elem, o.mode || "show" ),
14440 animation = {
14441 backgroundColor: elem.css( "backgroundColor" )
14442 };
14443
14444 if (mode === "hide") {
14445 animation.opacity = 0;
14446 }
14447
14448 $.effects.save( elem, props );
14449
14450 elem
14451 .show()
14452 .css({
14453 backgroundImage: "none",
14454 backgroundColor: o.color || "#ffff99"
14455 })
14456 .animate( animation, {
14457 queue: false,
14458 duration: o.duration,
14459 easing: o.easing,
14460 complete: function() {
14461 if ( mode === "hide" ) {
14462 elem.hide();
14463 }
14464 $.effects.restore( elem, props );
14465 done();
14466 }
14467 });
14468 };
14469
14470 })(jQuery);
14471 (function( $, undefined ) {
14472
14473 $.effects.effect.pulsate = function( o, done ) {
14474 var elem = $( this ),
14475 mode = $.effects.setMode( elem, o.mode || "show" ),
14476 show = mode === "show",
14477 hide = mode === "hide",
14478 showhide = ( show || mode === "hide" ),
14479
14480 // showing or hiding leaves of the "last" animation
14481 anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
14482 duration = o.duration / anims,
14483 animateTo = 0,
14484 queue = elem.queue(),
14485 queuelen = queue.length,
14486 i;
14487
14488 if ( show || !elem.is(":visible")) {
14489 elem.css( "opacity", 0 ).show();
14490 animateTo = 1;
14491 }
14492
14493 // anims - 1 opacity "toggles"
14494 for ( i = 1; i < anims; i++ ) {
14495 elem.animate({
14496 opacity: animateTo
14497 }, duration, o.easing );
14498 animateTo = 1 - animateTo;
14499 }
14500
14501 elem.animate({
14502 opacity: animateTo
14503 }, duration, o.easing);
14504
14505 elem.queue(function() {
14506 if ( hide ) {
14507 elem.hide();
14508 }
14509 done();
14510 });
14511
14512 // We just queued up "anims" animations, we need to put them next in the queue
14513 if ( queuelen > 1 ) {
14514 queue.splice.apply( queue,
14515 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
14516 }
14517 elem.dequeue();
14518 };
14519
14520 })(jQuery);
14521 (function( $, undefined ) {
14522
14523 $.effects.effect.puff = function( o, done ) {
14524 var elem = $( this ),
14525 mode = $.effects.setMode( elem, o.mode || "hide" ),
14526 hide = mode === "hide",
14527 percent = parseInt( o.percent, 10 ) || 150,
14528 factor = percent / 100,
14529 original = {
14530 height: elem.height(),
14531 width: elem.width(),
14532 outerHeight: elem.outerHeight(),
14533 outerWidth: elem.outerWidth()
14534 };
14535
14536 $.extend( o, {
14537 effect: "scale",
14538 queue: false,
14539 fade: true,
14540 mode: mode,
14541 complete: done,
14542 percent: hide ? percent : 100,
14543 from: hide ?
14544 original :
14545 {
14546 height: original.height * factor,
14547 width: original.width * factor,
14548 outerHeight: original.outerHeight * factor,
14549 outerWidth: original.outerWidth * factor
14550 }
14551 });
14552
14553 elem.effect( o );
14554 };
14555
14556 $.effects.effect.scale = function( o, done ) {
14557
14558 // Create element
14559 var el = $( this ),
14560 options = $.extend( true, {}, o ),
14561 mode = $.effects.setMode( el, o.mode || "effect" ),
14562 percent = parseInt( o.percent, 10 ) ||
14563 ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
14564 direction = o.direction || "both",
14565 origin = o.origin,
14566 original = {
14567 height: el.height(),
14568 width: el.width(),
14569 outerHeight: el.outerHeight(),
14570 outerWidth: el.outerWidth()
14571 },
14572 factor = {
14573 y: direction !== "horizontal" ? (percent / 100) : 1,
14574 x: direction !== "vertical" ? (percent / 100) : 1
14575 };
14576
14577 // We are going to pass this effect to the size effect:
14578 options.effect = "size";
14579 options.queue = false;
14580 options.complete = done;
14581
14582 // Set default origin and restore for show/hide
14583 if ( mode !== "effect" ) {
14584 options.origin = origin || ["middle","center"];
14585 options.restore = true;
14586 }
14587
14588 options.from = o.from || ( mode === "show" ? {
14589 height: 0,
14590 width: 0,
14591 outerHeight: 0,
14592 outerWidth: 0
14593 } : original );
14594 options.to = {
14595 height: original.height * factor.y,
14596 width: original.width * factor.x,
14597 outerHeight: original.outerHeight * factor.y,
14598 outerWidth: original.outerWidth * factor.x
14599 };
14600
14601 // Fade option to support puff
14602 if ( options.fade ) {
14603 if ( mode === "show" ) {
14604 options.from.opacity = 0;
14605 options.to.opacity = 1;
14606 }
14607 if ( mode === "hide" ) {
14608 options.from.opacity = 1;
14609 options.to.opacity = 0;
14610 }
14611 }
14612
14613 // Animate
14614 el.effect( options );
14615
14616 };
14617
14618 $.effects.effect.size = function( o, done ) {
14619
14620 // Create element
14621 var original, baseline, factor,
14622 el = $( this ),
14623 props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
14624
14625 // Always restore
14626 props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
14627
14628 // Copy for children
14629 props2 = [ "width", "height", "overflow" ],
14630 cProps = [ "fontSize" ],
14631 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
14632 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
14633
14634 // Set options
14635 mode = $.effects.setMode( el, o.mode || "effect" ),
14636 restore = o.restore || mode !== "effect",
14637 scale = o.scale || "both",
14638 origin = o.origin || [ "middle", "center" ],
14639 position = el.css( "position" ),
14640 props = restore ? props0 : props1,
14641 zero = {
14642 height: 0,
14643 width: 0,
14644 outerHeight: 0,
14645 outerWidth: 0
14646 };
14647
14648 if ( mode === "show" ) {
14649 el.show();
14650 }
14651 original = {
14652 height: el.height(),
14653 width: el.width(),
14654 outerHeight: el.outerHeight(),
14655 outerWidth: el.outerWidth()
14656 };
14657
14658 if ( o.mode === "toggle" && mode === "show" ) {
14659 el.from = o.to || zero;
14660 el.to = o.from || original;
14661 } else {
14662 el.from = o.from || ( mode === "show" ? zero : original );
14663 el.to = o.to || ( mode === "hide" ? zero : original );
14664 }
14665
14666 // Set scaling factor
14667 factor = {
14668 from: {
14669 y: el.from.height / original.height,
14670 x: el.from.width / original.width
14671 },
14672 to: {
14673 y: el.to.height / original.height,
14674 x: el.to.width / original.width
14675 }
14676 };
14677
14678 // Scale the css box
14679 if ( scale === "box" || scale === "both" ) {
14680
14681 // Vertical props scaling
14682 if ( factor.from.y !== factor.to.y ) {
14683 props = props.concat( vProps );
14684 el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
14685 el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
14686 }
14687
14688 // Horizontal props scaling
14689 if ( factor.from.x !== factor.to.x ) {
14690 props = props.concat( hProps );
14691 el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
14692 el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
14693 }
14694 }
14695
14696 // Scale the content
14697 if ( scale === "content" || scale === "both" ) {
14698
14699 // Vertical props scaling
14700 if ( factor.from.y !== factor.to.y ) {
14701 props = props.concat( cProps ).concat( props2 );
14702 el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
14703 el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
14704 }
14705 }
14706
14707 $.effects.save( el, props );
14708 el.show();
14709 $.effects.createWrapper( el );
14710 el.css( "overflow", "hidden" ).css( el.from );
14711
14712 // Adjust
14713 if (origin) { // Calculate baseline shifts
14714 baseline = $.effects.getBaseline( origin, original );
14715 el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
14716 el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
14717 el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
14718 el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
14719 }
14720 el.css( el.from ); // set top & left
14721
14722 // Animate
14723 if ( scale === "content" || scale === "both" ) { // Scale the children
14724
14725 // Add margins/font-size
14726 vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
14727 hProps = hProps.concat([ "marginLeft", "marginRight" ]);
14728 props2 = props0.concat(vProps).concat(hProps);
14729
14730 el.find( "*[width]" ).each( function(){
14731 var child = $( this ),
14732 c_original = {
14733 height: child.height(),
14734 width: child.width(),
14735 outerHeight: child.outerHeight(),
14736 outerWidth: child.outerWidth()
14737 };
14738 if (restore) {
14739 $.effects.save(child, props2);
14740 }
14741
14742 child.from = {
14743 height: c_original.height * factor.from.y,
14744 width: c_original.width * factor.from.x,
14745 outerHeight: c_original.outerHeight * factor.from.y,
14746 outerWidth: c_original.outerWidth * factor.from.x
14747 };
14748 child.to = {
14749 height: c_original.height * factor.to.y,
14750 width: c_original.width * factor.to.x,
14751 outerHeight: c_original.height * factor.to.y,
14752 outerWidth: c_original.width * factor.to.x
14753 };
14754
14755 // Vertical props scaling
14756 if ( factor.from.y !== factor.to.y ) {
14757 child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
14758 child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
14759 }
14760
14761 // Horizontal props scaling
14762 if ( factor.from.x !== factor.to.x ) {
14763 child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
14764 child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
14765 }
14766
14767 // Animate children
14768 child.css( child.from );
14769 child.animate( child.to, o.duration, o.easing, function() {
14770
14771 // Restore children
14772 if ( restore ) {
14773 $.effects.restore( child, props2 );
14774 }
14775 });
14776 });
14777 }
14778
14779 // Animate
14780 el.animate( el.to, {
14781 queue: false,
14782 duration: o.duration,
14783 easing: o.easing,
14784 complete: function() {
14785 if ( el.to.opacity === 0 ) {
14786 el.css( "opacity", el.from.opacity );
14787 }
14788 if( mode === "hide" ) {
14789 el.hide();
14790 }
14791 $.effects.restore( el, props );
14792 if ( !restore ) {
14793
14794 // we need to calculate our new positioning based on the scaling
14795 if ( position === "static" ) {
14796 el.css({
14797 position: "relative",
14798 top: el.to.top,
14799 left: el.to.left
14800 });
14801 } else {
14802 $.each([ "top", "left" ], function( idx, pos ) {
14803 el.css( pos, function( _, str ) {
14804 var val = parseInt( str, 10 ),
14805 toRef = idx ? el.to.left : el.to.top;
14806
14807 // if original was "auto", recalculate the new value from wrapper
14808 if ( str === "auto" ) {
14809 return toRef + "px";
14810 }
14811
14812 return val + toRef + "px";
14813 });
14814 });
14815 }
14816 }
14817
14818 $.effects.removeWrapper( el );
14819 done();
14820 }
14821 });
14822
14823 };
14824
14825 })(jQuery);
14826 (function( $, undefined ) {
14827
14828 $.effects.effect.shake = function( o, done ) {
14829
14830 var el = $( this ),
14831 props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
14832 mode = $.effects.setMode( el, o.mode || "effect" ),
14833 direction = o.direction || "left",
14834 distance = o.distance || 20,
14835 times = o.times || 3,
14836 anims = times * 2 + 1,
14837 speed = Math.round(o.duration/anims),
14838 ref = (direction === "up" || direction === "down") ? "top" : "left",
14839 positiveMotion = (direction === "up" || direction === "left"),
14840 animation = {},
14841 animation1 = {},
14842 animation2 = {},
14843 i,
14844
14845 // we will need to re-assemble the queue to stack our animations in place
14846 queue = el.queue(),
14847 queuelen = queue.length;
14848
14849 $.effects.save( el, props );
14850 el.show();
14851 $.effects.createWrapper( el );
14852
14853 // Animation
14854 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
14855 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
14856 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
14857
14858 // Animate
14859 el.animate( animation, speed, o.easing );
14860
14861 // Shakes
14862 for ( i = 1; i < times; i++ ) {
14863 el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
14864 }
14865 el
14866 .animate( animation1, speed, o.easing )
14867 .animate( animation, speed / 2, o.easing )
14868 .queue(function() {
14869 if ( mode === "hide" ) {
14870 el.hide();
14871 }
14872 $.effects.restore( el, props );
14873 $.effects.removeWrapper( el );
14874 done();
14875 });
14876
14877 // inject all the animations we just queued to be first in line (after "inprogress")
14878 if ( queuelen > 1) {
14879 queue.splice.apply( queue,
14880 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
14881 }
14882 el.dequeue();
14883
14884 };
14885
14886 })(jQuery);
14887 (function( $, undefined ) {
14888
14889 $.effects.effect.slide = function( o, done ) {
14890
14891 // Create element
14892 var el = $( this ),
14893 props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
14894 mode = $.effects.setMode( el, o.mode || "show" ),
14895 show = mode === "show",
14896 direction = o.direction || "left",
14897 ref = (direction === "up" || direction === "down") ? "top" : "left",
14898 positiveMotion = (direction === "up" || direction === "left"),
14899 distance,
14900 animation = {};
14901
14902 // Adjust
14903 $.effects.save( el, props );
14904 el.show();
14905 distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
14906
14907 $.effects.createWrapper( el ).css({
14908 overflow: "hidden"
14909 });
14910
14911 if ( show ) {
14912 el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
14913 }
14914
14915 // Animation
14916 animation[ ref ] = ( show ?
14917 ( positiveMotion ? "+=" : "-=") :
14918 ( positiveMotion ? "-=" : "+=")) +
14919 distance;
14920
14921 // Animate
14922 el.animate( animation, {
14923 queue: false,
14924 duration: o.duration,
14925 easing: o.easing,
14926 complete: function() {
14927 if ( mode === "hide" ) {
14928 el.hide();
14929 }
14930 $.effects.restore( el, props );
14931 $.effects.removeWrapper( el );
14932 done();
14933 }
14934 });
14935 };
14936
14937 })(jQuery);
14938 (function( $, undefined ) {
14939
14940 $.effects.effect.transfer = function( o, done ) {
14941 var elem = $( this ),
14942 target = $( o.to ),
14943 targetFixed = target.css( "position" ) === "fixed",
14944 body = $("body"),
14945 fixTop = targetFixed ? body.scrollTop() : 0,
14946 fixLeft = targetFixed ? body.scrollLeft() : 0,
14947 endPosition = target.offset(),
14948 animation = {
14949 top: endPosition.top - fixTop ,
14950 left: endPosition.left - fixLeft ,
14951 height: target.innerHeight(),
14952 width: target.innerWidth()
14953 },
14954 startPosition = elem.offset(),
14955 transfer = $( "<div class='ui-effects-transfer'></div>" )
14956 .appendTo( document.body )
14957 .addClass( o.className )
14958 .css({
14959 top: startPosition.top - fixTop ,
14960 left: startPosition.left - fixLeft ,
14961 height: elem.innerHeight(),
14962 width: elem.innerWidth(),
14963 position: targetFixed ? "fixed" : "absolute"
14964 })
14965 .animate( animation, o.duration, o.easing, function() {
14966 transfer.remove();
14967 done();
14968 });
14969 };
14970
14971 })(jQuery);

Небольшая справка по веткам

cnddist – контейнер, в котором хранятся все дистрибутивы всех библиотек и программных пакетов, которые использовались при построении различных версий Contenido. Если какой-то библиотеки в данном хранилище нет, инсталлятор сделает попытку "подтянуть" ее с веба (например, с CPAN). Если библиотека слишком старая, есть очень большая вероятность, что ее там уже нет. Поэтому мы храним весь хлам от всех сборок. Если какой-то дистрибутив вдруг отсутствует в cnddist - напишите нам, мы положим его туда.

koi8 – отмирающая ветка, чей код, выдача и все внутренние библиотеки заточены на кодировку KOI8-R. Вносятся только те дополнения, которые касаются внешнего вида и функционала админки, баги ядра, обязательные обновления портов и мелочи, которые легко скопипастить. В дальнейшем планируется полная остановка поддержки по данной ветке.

utf8 – актуальная ветка, заточенная под UTF-8.

Внутри каждой ветки: core – исходники ядра; install – скрипт установки инсталляции; plugins – плагины; samples – "готовые к употреблению" проекты, которые можно поставить, запустить и посмотреть, как они работают.