[SPIP] +2.1.12
[velocampus/web/www.git] / www / plugins / auto / jquery_ui / javascript / jquery-ui-1.8.16 / ui / jquery-ui.js
1 /*!
2 * jQuery UI 1.8.16
3 *
4 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT or GPL Version 2 licenses.
6 * http://jquery.org/license
7 *
8 * http://docs.jquery.com/UI
9 */
10 (function( $, undefined ) {
11
12 // prevent duplicate loading
13 // this is only a problem because we proxy existing functions
14 // and we don't want to double proxy them
15 $.ui = $.ui || {};
16 if ( $.ui.version ) {
17 return;
18 }
19
20 $.extend( $.ui, {
21 version: "1.8.16",
22
23 keyCode: {
24 ALT: 18,
25 BACKSPACE: 8,
26 CAPS_LOCK: 20,
27 COMMA: 188,
28 COMMAND: 91,
29 COMMAND_LEFT: 91, // COMMAND
30 COMMAND_RIGHT: 93,
31 CONTROL: 17,
32 DELETE: 46,
33 DOWN: 40,
34 END: 35,
35 ENTER: 13,
36 ESCAPE: 27,
37 HOME: 36,
38 INSERT: 45,
39 LEFT: 37,
40 MENU: 93, // COMMAND_RIGHT
41 NUMPAD_ADD: 107,
42 NUMPAD_DECIMAL: 110,
43 NUMPAD_DIVIDE: 111,
44 NUMPAD_ENTER: 108,
45 NUMPAD_MULTIPLY: 106,
46 NUMPAD_SUBTRACT: 109,
47 PAGE_DOWN: 34,
48 PAGE_UP: 33,
49 PERIOD: 190,
50 RIGHT: 39,
51 SHIFT: 16,
52 SPACE: 32,
53 TAB: 9,
54 UP: 38,
55 WINDOWS: 91 // COMMAND
56 }
57 });
58
59 // plugins
60 $.fn.extend({
61 propAttr: $.fn.prop || $.fn.attr,
62
63 _focus: $.fn.focus,
64 focus: function( delay, fn ) {
65 return typeof delay === "number" ?
66 this.each(function() {
67 var elem = this;
68 setTimeout(function() {
69 $( elem ).focus();
70 if ( fn ) {
71 fn.call( elem );
72 }
73 }, delay );
74 }) :
75 this._focus.apply( this, arguments );
76 },
77
78 scrollParent: function() {
79 var scrollParent;
80 if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
81 scrollParent = this.parents().filter(function() {
82 return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
83 }).eq(0);
84 } else {
85 scrollParent = this.parents().filter(function() {
86 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
87 }).eq(0);
88 }
89
90 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
91 },
92
93 zIndex: function( zIndex ) {
94 if ( zIndex !== undefined ) {
95 return this.css( "zIndex", zIndex );
96 }
97
98 if ( this.length ) {
99 var elem = $( this[ 0 ] ), position, value;
100 while ( elem.length && elem[ 0 ] !== document ) {
101 // Ignore z-index if position is set to a value where z-index is ignored by the browser
102 // This makes behavior of this function consistent across browsers
103 // WebKit always returns auto if the element is positioned
104 position = elem.css( "position" );
105 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
106 // IE returns 0 when zIndex is not specified
107 // other browsers return a string
108 // we ignore the case of nested elements with an explicit value of 0
109 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
110 value = parseInt( elem.css( "zIndex" ), 10 );
111 if ( !isNaN( value ) && value !== 0 ) {
112 return value;
113 }
114 }
115 elem = elem.parent();
116 }
117 }
118
119 return 0;
120 },
121
122 disableSelection: function() {
123 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
124 ".ui-disableSelection", function( event ) {
125 event.preventDefault();
126 });
127 },
128
129 enableSelection: function() {
130 return this.unbind( ".ui-disableSelection" );
131 }
132 });
133
134 $.each( [ "Width", "Height" ], function( i, name ) {
135 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
136 type = name.toLowerCase(),
137 orig = {
138 innerWidth: $.fn.innerWidth,
139 innerHeight: $.fn.innerHeight,
140 outerWidth: $.fn.outerWidth,
141 outerHeight: $.fn.outerHeight
142 };
143
144 function reduce( elem, size, border, margin ) {
145 $.each( side, function() {
146 size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
147 if ( border ) {
148 size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
149 }
150 if ( margin ) {
151 size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
152 }
153 });
154 return size;
155 }
156
157 $.fn[ "inner" + name ] = function( size ) {
158 if ( size === undefined ) {
159 return orig[ "inner" + name ].call( this );
160 }
161
162 return this.each(function() {
163 $( this ).css( type, reduce( this, size ) + "px" );
164 });
165 };
166
167 $.fn[ "outer" + name] = function( size, margin ) {
168 if ( typeof size !== "number" ) {
169 return orig[ "outer" + name ].call( this, size );
170 }
171
172 return this.each(function() {
173 $( this).css( type, reduce( this, size, true, margin ) + "px" );
174 });
175 };
176 });
177
178 // selectors
179 function focusable( element, isTabIndexNotNaN ) {
180 var nodeName = element.nodeName.toLowerCase();
181 if ( "area" === nodeName ) {
182 var map = element.parentNode,
183 mapName = map.name,
184 img;
185 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
186 return false;
187 }
188 img = $( "img[usemap=#" + mapName + "]" )[0];
189 return !!img && visible( img );
190 }
191 return ( /input|select|textarea|button|object/.test( nodeName )
192 ? !element.disabled
193 : "a" == nodeName
194 ? element.href || isTabIndexNotNaN
195 : isTabIndexNotNaN)
196 // the element and all of its ancestors must be visible
197 && visible( element );
198 }
199
200 function visible( element ) {
201 return !$( element ).parents().andSelf().filter(function() {
202 return $.curCSS( this, "visibility" ) === "hidden" ||
203 $.expr.filters.hidden( this );
204 }).length;
205 }
206
207 $.extend( $.expr[ ":" ], {
208 data: function( elem, i, match ) {
209 return !!$.data( elem, match[ 3 ] );
210 },
211
212 focusable: function( element ) {
213 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
214 },
215
216 tabbable: function( element ) {
217 var tabIndex = $.attr( element, "tabindex" ),
218 isTabIndexNaN = isNaN( tabIndex );
219 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
220 }
221 });
222
223 // support
224 $(function() {
225 var body = document.body,
226 div = body.appendChild( div = document.createElement( "div" ) );
227
228 $.extend( div.style, {
229 minHeight: "100px",
230 height: "auto",
231 padding: 0,
232 borderWidth: 0
233 });
234
235 $.support.minHeight = div.offsetHeight === 100;
236 $.support.selectstart = "onselectstart" in div;
237
238 // set display to none to avoid a layout bug in IE
239 // http://dev.jquery.com/ticket/4014
240 body.removeChild( div ).style.display = "none";
241 });
242
243
244
245
246
247 // deprecated
248 $.extend( $.ui, {
249 // $.ui.plugin is deprecated. Use the proxy pattern instead.
250 plugin: {
251 add: function( module, option, set ) {
252 var proto = $.ui[ module ].prototype;
253 for ( var i in set ) {
254 proto.plugins[ i ] = proto.plugins[ i ] || [];
255 proto.plugins[ i ].push( [ option, set[ i ] ] );
256 }
257 },
258 call: function( instance, name, args ) {
259 var set = instance.plugins[ name ];
260 if ( !set || !instance.element[ 0 ].parentNode ) {
261 return;
262 }
263
264 for ( var i = 0; i < set.length; i++ ) {
265 if ( instance.options[ set[ i ][ 0 ] ] ) {
266 set[ i ][ 1 ].apply( instance.element, args );
267 }
268 }
269 }
270 },
271
272 // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
273 contains: function( a, b ) {
274 return document.compareDocumentPosition ?
275 a.compareDocumentPosition( b ) & 16 :
276 a !== b && a.contains( b );
277 },
278
279 // only used by resizable
280 hasScroll: function( el, a ) {
281
282 //If overflow is hidden, the element might have extra content, but the user wants to hide it
283 if ( $( el ).css( "overflow" ) === "hidden") {
284 return false;
285 }
286
287 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
288 has = false;
289
290 if ( el[ scroll ] > 0 ) {
291 return true;
292 }
293
294 // TODO: determine which cases actually cause this to happen
295 // if the element doesn't have the scroll set, see if it's possible to
296 // set the scroll
297 el[ scroll ] = 1;
298 has = ( el[ scroll ] > 0 );
299 el[ scroll ] = 0;
300 return has;
301 },
302
303 // these are odd functions, fix the API or move into individual plugins
304 isOverAxis: function( x, reference, size ) {
305 //Determines when x coordinate is over "b" element axis
306 return ( x > reference ) && ( x < ( reference + size ) );
307 },
308 isOver: function( y, x, top, left, height, width ) {
309 //Determines when x, y coordinates is over "b" element
310 return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
311 }
312 });
313
314 })( jQuery );
315 /*!
316 * jQuery UI Widget 1.8.16
317 *
318 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
319 * Dual licensed under the MIT or GPL Version 2 licenses.
320 * http://jquery.org/license
321 *
322 * http://docs.jquery.com/UI/Widget
323 */
324 (function( $, undefined ) {
325
326 // jQuery 1.4+
327 if ( $.cleanData ) {
328 var _cleanData = $.cleanData;
329 $.cleanData = function( elems ) {
330 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
331 try {
332 $( elem ).triggerHandler( "remove" );
333 // http://bugs.jquery.com/ticket/8235
334 } catch( e ) {}
335 }
336 _cleanData( elems );
337 };
338 } else {
339 var _remove = $.fn.remove;
340 $.fn.remove = function( selector, keepData ) {
341 return this.each(function() {
342 if ( !keepData ) {
343 if ( !selector || $.filter( selector, [ this ] ).length ) {
344 $( "*", this ).add( [ this ] ).each(function() {
345 try {
346 $( this ).triggerHandler( "remove" );
347 // http://bugs.jquery.com/ticket/8235
348 } catch( e ) {}
349 });
350 }
351 }
352 return _remove.call( $(this), selector, keepData );
353 });
354 };
355 }
356
357 $.widget = function( name, base, prototype ) {
358 var namespace = name.split( "." )[ 0 ],
359 fullName;
360 name = name.split( "." )[ 1 ];
361 fullName = namespace + "-" + name;
362
363 if ( !prototype ) {
364 prototype = base;
365 base = $.Widget;
366 }
367
368 // create selector for plugin
369 $.expr[ ":" ][ fullName ] = function( elem ) {
370 return !!$.data( elem, name );
371 };
372
373 $[ namespace ] = $[ namespace ] || {};
374 $[ namespace ][ name ] = function( options, element ) {
375 // allow instantiation without initializing for simple inheritance
376 if ( arguments.length ) {
377 this._createWidget( options, element );
378 }
379 };
380
381 var basePrototype = new base();
382 // we need to make the options hash a property directly on the new instance
383 // otherwise we'll modify the options hash on the prototype that we're
384 // inheriting from
385 // $.each( basePrototype, function( key, val ) {
386 // if ( $.isPlainObject(val) ) {
387 // basePrototype[ key ] = $.extend( {}, val );
388 // }
389 // });
390 basePrototype.options = $.extend( true, {}, basePrototype.options );
391 $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
392 namespace: namespace,
393 widgetName: name,
394 widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
395 widgetBaseClass: fullName
396 }, prototype );
397
398 $.widget.bridge( name, $[ namespace ][ name ] );
399 };
400
401 $.widget.bridge = function( name, object ) {
402 $.fn[ name ] = function( options ) {
403 var isMethodCall = typeof options === "string",
404 args = Array.prototype.slice.call( arguments, 1 ),
405 returnValue = this;
406
407 // allow multiple hashes to be passed on init
408 options = !isMethodCall && args.length ?
409 $.extend.apply( null, [ true, options ].concat(args) ) :
410 options;
411
412 // prevent calls to internal methods
413 if ( isMethodCall && options.charAt( 0 ) === "_" ) {
414 return returnValue;
415 }
416
417 if ( isMethodCall ) {
418 this.each(function() {
419 var instance = $.data( this, name ),
420 methodValue = instance && $.isFunction( instance[options] ) ?
421 instance[ options ].apply( instance, args ) :
422 instance;
423 // TODO: add this back in 1.9 and use $.error() (see #5972)
424 // if ( !instance ) {
425 // throw "cannot call methods on " + name + " prior to initialization; " +
426 // "attempted to call method '" + options + "'";
427 // }
428 // if ( !$.isFunction( instance[options] ) ) {
429 // throw "no such method '" + options + "' for " + name + " widget instance";
430 // }
431 // var methodValue = instance[ options ].apply( instance, args );
432 if ( methodValue !== instance && methodValue !== undefined ) {
433 returnValue = methodValue;
434 return false;
435 }
436 });
437 } else {
438 this.each(function() {
439 var instance = $.data( this, name );
440 if ( instance ) {
441 instance.option( options || {} )._init();
442 } else {
443 $.data( this, name, new object( options, this ) );
444 }
445 });
446 }
447
448 return returnValue;
449 };
450 };
451
452 $.Widget = function( options, element ) {
453 // allow instantiation without initializing for simple inheritance
454 if ( arguments.length ) {
455 this._createWidget( options, element );
456 }
457 };
458
459 $.Widget.prototype = {
460 widgetName: "widget",
461 widgetEventPrefix: "",
462 options: {
463 disabled: false
464 },
465 _createWidget: function( options, element ) {
466 // $.widget.bridge stores the plugin instance, but we do it anyway
467 // so that it's stored even before the _create function runs
468 $.data( element, this.widgetName, this );
469 this.element = $( element );
470 this.options = $.extend( true, {},
471 this.options,
472 this._getCreateOptions(),
473 options );
474
475 var self = this;
476 this.element.bind( "remove." + this.widgetName, function() {
477 self.destroy();
478 });
479
480 this._create();
481 this._trigger( "create" );
482 this._init();
483 },
484 _getCreateOptions: function() {
485 return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
486 },
487 _create: function() {},
488 _init: function() {},
489
490 destroy: function() {
491 this.element
492 .unbind( "." + this.widgetName )
493 .removeData( this.widgetName );
494 this.widget()
495 .unbind( "." + this.widgetName )
496 .removeAttr( "aria-disabled" )
497 .removeClass(
498 this.widgetBaseClass + "-disabled " +
499 "ui-state-disabled" );
500 },
501
502 widget: function() {
503 return this.element;
504 },
505
506 option: function( key, value ) {
507 var options = key;
508
509 if ( arguments.length === 0 ) {
510 // don't return a reference to the internal hash
511 return $.extend( {}, this.options );
512 }
513
514 if (typeof key === "string" ) {
515 if ( value === undefined ) {
516 return this.options[ key ];
517 }
518 options = {};
519 options[ key ] = value;
520 }
521
522 this._setOptions( options );
523
524 return this;
525 },
526 _setOptions: function( options ) {
527 var self = this;
528 $.each( options, function( key, value ) {
529 self._setOption( key, value );
530 });
531
532 return this;
533 },
534 _setOption: function( key, value ) {
535 this.options[ key ] = value;
536
537 if ( key === "disabled" ) {
538 this.widget()
539 [ value ? "addClass" : "removeClass"](
540 this.widgetBaseClass + "-disabled" + " " +
541 "ui-state-disabled" )
542 .attr( "aria-disabled", value );
543 }
544
545 return this;
546 },
547
548 enable: function() {
549 return this._setOption( "disabled", false );
550 },
551 disable: function() {
552 return this._setOption( "disabled", true );
553 },
554
555 _trigger: function( type, event, data ) {
556 var callback = this.options[ type ];
557
558 event = $.Event( event );
559 event.type = ( type === this.widgetEventPrefix ?
560 type :
561 this.widgetEventPrefix + type ).toLowerCase();
562 data = data || {};
563
564 // copy original event properties over to the new event
565 // this would happen if we could call $.event.fix instead of $.Event
566 // but we don't have a way to force an event to be fixed multiple times
567 if ( event.originalEvent ) {
568 for ( var i = $.event.props.length, prop; i; ) {
569 prop = $.event.props[ --i ];
570 event[ prop ] = event.originalEvent[ prop ];
571 }
572 }
573
574 this.element.trigger( event, data );
575
576 return !( $.isFunction(callback) &&
577 callback.call( this.element[0], event, data ) === false ||
578 event.isDefaultPrevented() );
579 }
580 };
581
582 })( jQuery );
583 /*!
584 * jQuery UI Mouse 1.8.16
585 *
586 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
587 * Dual licensed under the MIT or GPL Version 2 licenses.
588 * http://jquery.org/license
589 *
590 * http://docs.jquery.com/UI/Mouse
591 *
592 * Depends:
593 * jquery.ui.widget.js
594 */
595 (function( $, undefined ) {
596
597 var mouseHandled = false;
598 $( document ).mouseup( function( e ) {
599 mouseHandled = false;
600 });
601
602 $.widget("ui.mouse", {
603 options: {
604 cancel: ':input,option',
605 distance: 1,
606 delay: 0
607 },
608 _mouseInit: function() {
609 var self = this;
610
611 this.element
612 .bind('mousedown.'+this.widgetName, function(event) {
613 return self._mouseDown(event);
614 })
615 .bind('click.'+this.widgetName, function(event) {
616 if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
617 $.removeData(event.target, self.widgetName + '.preventClickEvent');
618 event.stopImmediatePropagation();
619 return false;
620 }
621 });
622
623 this.started = false;
624 },
625
626 // TODO: make sure destroying one instance of mouse doesn't mess with
627 // other instances of mouse
628 _mouseDestroy: function() {
629 this.element.unbind('.'+this.widgetName);
630 },
631
632 _mouseDown: function(event) {
633 // don't let more than one widget handle mouseStart
634 if( mouseHandled ) { return };
635
636 // we may have missed mouseup (out of window)
637 (this._mouseStarted && this._mouseUp(event));
638
639 this._mouseDownEvent = event;
640
641 var self = this,
642 btnIsLeft = (event.which == 1),
643 // event.target.nodeName works around a bug in IE 8 with
644 // disabled inputs (#7620)
645 elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
646 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
647 return true;
648 }
649
650 this.mouseDelayMet = !this.options.delay;
651 if (!this.mouseDelayMet) {
652 this._mouseDelayTimer = setTimeout(function() {
653 self.mouseDelayMet = true;
654 }, this.options.delay);
655 }
656
657 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
658 this._mouseStarted = (this._mouseStart(event) !== false);
659 if (!this._mouseStarted) {
660 event.preventDefault();
661 return true;
662 }
663 }
664
665 // Click event may never have fired (Gecko & Opera)
666 if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
667 $.removeData(event.target, this.widgetName + '.preventClickEvent');
668 }
669
670 // these delegates are required to keep context
671 this._mouseMoveDelegate = function(event) {
672 return self._mouseMove(event);
673 };
674 this._mouseUpDelegate = function(event) {
675 return self._mouseUp(event);
676 };
677 $(document)
678 .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
679 .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
680
681 event.preventDefault();
682
683 mouseHandled = true;
684 return true;
685 },
686
687 _mouseMove: function(event) {
688 // IE mouseup check - mouseup happened when mouse was out of window
689 if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
690 return this._mouseUp(event);
691 }
692
693 if (this._mouseStarted) {
694 this._mouseDrag(event);
695 return event.preventDefault();
696 }
697
698 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
699 this._mouseStarted =
700 (this._mouseStart(this._mouseDownEvent, event) !== false);
701 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
702 }
703
704 return !this._mouseStarted;
705 },
706
707 _mouseUp: function(event) {
708 $(document)
709 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
710 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
711
712 if (this._mouseStarted) {
713 this._mouseStarted = false;
714
715 if (event.target == this._mouseDownEvent.target) {
716 $.data(event.target, this.widgetName + '.preventClickEvent', true);
717 }
718
719 this._mouseStop(event);
720 }
721
722 return false;
723 },
724
725 _mouseDistanceMet: function(event) {
726 return (Math.max(
727 Math.abs(this._mouseDownEvent.pageX - event.pageX),
728 Math.abs(this._mouseDownEvent.pageY - event.pageY)
729 ) >= this.options.distance
730 );
731 },
732
733 _mouseDelayMet: function(event) {
734 return this.mouseDelayMet;
735 },
736
737 // These are placeholder methods, to be overriden by extending plugin
738 _mouseStart: function(event) {},
739 _mouseDrag: function(event) {},
740 _mouseStop: function(event) {},
741 _mouseCapture: function(event) { return true; }
742 });
743
744 })(jQuery);
745 /*
746 * jQuery UI Draggable 1.8.16
747 *
748 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
749 * Dual licensed under the MIT or GPL Version 2 licenses.
750 * http://jquery.org/license
751 *
752 * http://docs.jquery.com/UI/Draggables
753 *
754 * Depends:
755 * jquery.ui.core.js
756 * jquery.ui.mouse.js
757 * jquery.ui.widget.js
758 */
759 (function( $, undefined ) {
760
761 $.widget("ui.draggable", $.ui.mouse, {
762 widgetEventPrefix: "drag",
763 options: {
764 addClasses: true,
765 appendTo: "parent",
766 axis: false,
767 connectToSortable: false,
768 containment: false,
769 cursor: "auto",
770 cursorAt: false,
771 grid: false,
772 handle: false,
773 helper: "original",
774 iframeFix: false,
775 opacity: false,
776 refreshPositions: false,
777 revert: false,
778 revertDuration: 500,
779 scope: "default",
780 scroll: true,
781 scrollSensitivity: 20,
782 scrollSpeed: 20,
783 snap: false,
784 snapMode: "both",
785 snapTolerance: 20,
786 stack: false,
787 zIndex: false
788 },
789 _create: function() {
790
791 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
792 this.element[0].style.position = 'relative';
793
794 (this.options.addClasses && this.element.addClass("ui-draggable"));
795 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
796
797 this._mouseInit();
798
799 },
800
801 destroy: function() {
802 if(!this.element.data('draggable')) return;
803 this.element
804 .removeData("draggable")
805 .unbind(".draggable")
806 .removeClass("ui-draggable"
807 + " ui-draggable-dragging"
808 + " ui-draggable-disabled");
809 this._mouseDestroy();
810
811 return this;
812 },
813
814 _mouseCapture: function(event) {
815
816 var o = this.options;
817
818 // among others, prevent a drag on a resizable-handle
819 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
820 return false;
821
822 //Quit if we're not on a valid handle
823 this.handle = this._getHandle(event);
824 if (!this.handle)
825 return false;
826
827 if ( o.iframeFix ) {
828 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
829 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
830 .css({
831 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
832 position: "absolute", opacity: "0.001", zIndex: 1000
833 })
834 .css($(this).offset())
835 .appendTo("body");
836 });
837 }
838
839 return true;
840
841 },
842
843 _mouseStart: function(event) {
844
845 var o = this.options;
846
847 //Create and append the visible helper
848 this.helper = this._createHelper(event);
849
850 //Cache the helper size
851 this._cacheHelperProportions();
852
853 //If ddmanager is used for droppables, set the global draggable
854 if($.ui.ddmanager)
855 $.ui.ddmanager.current = this;
856
857 /*
858 * - Position generation -
859 * This block generates everything position related - it's the core of draggables.
860 */
861
862 //Cache the margins of the original element
863 this._cacheMargins();
864
865 //Store the helper's css position
866 this.cssPosition = this.helper.css("position");
867 this.scrollParent = this.helper.scrollParent();
868
869 //The element's absolute position on the page minus margins
870 this.offset = this.positionAbs = this.element.offset();
871 this.offset = {
872 top: this.offset.top - this.margins.top,
873 left: this.offset.left - this.margins.left
874 };
875
876 $.extend(this.offset, {
877 click: { //Where the click happened, relative to the element
878 left: event.pageX - this.offset.left,
879 top: event.pageY - this.offset.top
880 },
881 parent: this._getParentOffset(),
882 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
883 });
884
885 //Generate the original position
886 this.originalPosition = this.position = this._generatePosition(event);
887 this.originalPageX = event.pageX;
888 this.originalPageY = event.pageY;
889
890 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
891 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
892
893 //Set a containment if given in the options
894 if(o.containment)
895 this._setContainment();
896
897 //Trigger event + callbacks
898 if(this._trigger("start", event) === false) {
899 this._clear();
900 return false;
901 }
902
903 //Recache the helper size
904 this._cacheHelperProportions();
905
906 //Prepare the droppable offsets
907 if ($.ui.ddmanager && !o.dropBehaviour)
908 $.ui.ddmanager.prepareOffsets(this, event);
909
910 this.helper.addClass("ui-draggable-dragging");
911 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
912
913 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
914 if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event);
915
916 return true;
917 },
918
919 _mouseDrag: function(event, noPropagation) {
920
921 //Compute the helpers position
922 this.position = this._generatePosition(event);
923 this.positionAbs = this._convertPositionTo("absolute");
924
925 //Call plugins and callbacks and use the resulting position if something is returned
926 if (!noPropagation) {
927 var ui = this._uiHash();
928 if(this._trigger('drag', event, ui) === false) {
929 this._mouseUp({});
930 return false;
931 }
932 this.position = ui.position;
933 }
934
935 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
936 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
937 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
938
939 return false;
940 },
941
942 _mouseStop: function(event) {
943
944 //If we are using droppables, inform the manager about the drop
945 var dropped = false;
946 if ($.ui.ddmanager && !this.options.dropBehaviour)
947 dropped = $.ui.ddmanager.drop(this, event);
948
949 //if a drop comes from outside (a sortable)
950 if(this.dropped) {
951 dropped = this.dropped;
952 this.dropped = false;
953 }
954
955 //if the original element is removed, don't bother to continue if helper is set to "original"
956 if((!this.element[0] || !this.element[0].parentNode) && this.options.helper == "original")
957 return false;
958
959 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))) {
960 var self = this;
961 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
962 if(self._trigger("stop", event) !== false) {
963 self._clear();
964 }
965 });
966 } else {
967 if(this._trigger("stop", event) !== false) {
968 this._clear();
969 }
970 }
971
972 return false;
973 },
974
975 _mouseUp: function(event) {
976 if (this.options.iframeFix === true) {
977 $("div.ui-draggable-iframeFix").each(function() {
978 this.parentNode.removeChild(this);
979 }); //Remove frame helpers
980 }
981
982 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
983 if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event);
984
985 return $.ui.mouse.prototype._mouseUp.call(this, event);
986 },
987
988 cancel: function() {
989
990 if(this.helper.is(".ui-draggable-dragging")) {
991 this._mouseUp({});
992 } else {
993 this._clear();
994 }
995
996 return this;
997
998 },
999
1000 _getHandle: function(event) {
1001
1002 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
1003 $(this.options.handle, this.element)
1004 .find("*")
1005 .andSelf()
1006 .each(function() {
1007 if(this == event.target) handle = true;
1008 });
1009
1010 return handle;
1011
1012 },
1013
1014 _createHelper: function(event) {
1015
1016 var o = this.options;
1017 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element);
1018
1019 if(!helper.parents('body').length)
1020 helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
1021
1022 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
1023 helper.css("position", "absolute");
1024
1025 return helper;
1026
1027 },
1028
1029 _adjustOffsetFromHelper: function(obj) {
1030 if (typeof obj == 'string') {
1031 obj = obj.split(' ');
1032 }
1033 if ($.isArray(obj)) {
1034 obj = {left: +obj[0], top: +obj[1] || 0};
1035 }
1036 if ('left' in obj) {
1037 this.offset.click.left = obj.left + this.margins.left;
1038 }
1039 if ('right' in obj) {
1040 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1041 }
1042 if ('top' in obj) {
1043 this.offset.click.top = obj.top + this.margins.top;
1044 }
1045 if ('bottom' in obj) {
1046 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1047 }
1048 },
1049
1050 _getParentOffset: function() {
1051
1052 //Get the offsetParent and cache its position
1053 this.offsetParent = this.helper.offsetParent();
1054 var po = this.offsetParent.offset();
1055
1056 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1057 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1058 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1059 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1060 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
1061 po.left += this.scrollParent.scrollLeft();
1062 po.top += this.scrollParent.scrollTop();
1063 }
1064
1065 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
1066 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
1067 po = { top: 0, left: 0 };
1068
1069 return {
1070 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1071 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1072 };
1073
1074 },
1075
1076 _getRelativeOffset: function() {
1077
1078 if(this.cssPosition == "relative") {
1079 var p = this.element.position();
1080 return {
1081 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1082 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1083 };
1084 } else {
1085 return { top: 0, left: 0 };
1086 }
1087
1088 },
1089
1090 _cacheMargins: function() {
1091 this.margins = {
1092 left: (parseInt(this.element.css("marginLeft"),10) || 0),
1093 top: (parseInt(this.element.css("marginTop"),10) || 0),
1094 right: (parseInt(this.element.css("marginRight"),10) || 0),
1095 bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
1096 };
1097 },
1098
1099 _cacheHelperProportions: function() {
1100 this.helperProportions = {
1101 width: this.helper.outerWidth(),
1102 height: this.helper.outerHeight()
1103 };
1104 },
1105
1106 _setContainment: function() {
1107
1108 var o = this.options;
1109 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
1110 if(o.containment == 'document' || o.containment == 'window') this.containment = [
1111 o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
1112 o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
1113 (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
1114 (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
1115 ];
1116
1117 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
1118 var c = $(o.containment);
1119 var ce = c[0]; if(!ce) return;
1120 var co = c.offset();
1121 var over = ($(ce).css("overflow") != 'hidden');
1122
1123 this.containment = [
1124 (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
1125 (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
1126 (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 - this.margins.right,
1127 (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 - this.margins.bottom
1128 ];
1129 this.relative_container = c;
1130
1131 } else if(o.containment.constructor == Array) {
1132 this.containment = o.containment;
1133 }
1134
1135 },
1136
1137 _convertPositionTo: function(d, pos) {
1138
1139 if(!pos) pos = this.position;
1140 var mod = d == "absolute" ? 1 : -1;
1141 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
1142
1143 return {
1144 top: (
1145 pos.top // The absolute mouse position
1146 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1147 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
1148 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
1149 ),
1150 left: (
1151 pos.left // The absolute mouse position
1152 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1153 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
1154 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
1155 )
1156 };
1157
1158 },
1159
1160 _generatePosition: function(event) {
1161
1162 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
1163 var pageX = event.pageX;
1164 var pageY = event.pageY;
1165
1166 /*
1167 * - Position constraining -
1168 * Constrain the position to a mix of grid, containment.
1169 */
1170
1171 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
1172 var containment;
1173 if(this.containment) {
1174 if (this.relative_container){
1175 var co = this.relative_container.offset();
1176 containment = [ this.containment[0] + co.left,
1177 this.containment[1] + co.top,
1178 this.containment[2] + co.left,
1179 this.containment[3] + co.top ];
1180 }
1181 else {
1182 containment = this.containment;
1183 }
1184
1185 if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left;
1186 if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top;
1187 if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left;
1188 if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top;
1189 }
1190
1191 if(o.grid) {
1192 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
1193 var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
1194 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;
1195
1196 var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
1197 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;
1198 }
1199
1200 }
1201
1202 return {
1203 top: (
1204 pageY // The absolute mouse position
1205 - this.offset.click.top // Click offset (relative to the element)
1206 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
1207 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
1208 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
1209 ),
1210 left: (
1211 pageX // The absolute mouse position
1212 - this.offset.click.left // Click offset (relative to the element)
1213 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
1214 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
1215 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
1216 )
1217 };
1218
1219 },
1220
1221 _clear: function() {
1222 this.helper.removeClass("ui-draggable-dragging");
1223 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
1224 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
1225 this.helper = null;
1226 this.cancelHelperRemoval = false;
1227 },
1228
1229 // From now on bulk stuff - mainly helpers
1230
1231 _trigger: function(type, event, ui) {
1232 ui = ui || this._uiHash();
1233 $.ui.plugin.call(this, type, [event, ui]);
1234 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
1235 return $.Widget.prototype._trigger.call(this, type, event, ui);
1236 },
1237
1238 plugins: {},
1239
1240 _uiHash: function(event) {
1241 return {
1242 helper: this.helper,
1243 position: this.position,
1244 originalPosition: this.originalPosition,
1245 offset: this.positionAbs
1246 };
1247 }
1248
1249 });
1250
1251 $.extend($.ui.draggable, {
1252 version: "1.8.16"
1253 });
1254
1255 $.ui.plugin.add("draggable", "connectToSortable", {
1256 start: function(event, ui) {
1257
1258 var inst = $(this).data("draggable"), o = inst.options,
1259 uiSortable = $.extend({}, ui, { item: inst.element });
1260 inst.sortables = [];
1261 $(o.connectToSortable).each(function() {
1262 var sortable = $.data(this, 'sortable');
1263 if (sortable && !sortable.options.disabled) {
1264 inst.sortables.push({
1265 instance: sortable,
1266 shouldRevert: sortable.options.revert
1267 });
1268 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).
1269 sortable._trigger("activate", event, uiSortable);
1270 }
1271 });
1272
1273 },
1274 stop: function(event, ui) {
1275
1276 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1277 var inst = $(this).data("draggable"),
1278 uiSortable = $.extend({}, ui, { item: inst.element });
1279
1280 $.each(inst.sortables, function() {
1281 if(this.instance.isOver) {
1282
1283 this.instance.isOver = 0;
1284
1285 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
1286 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1287
1288 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
1289 if(this.shouldRevert) this.instance.options.revert = true;
1290
1291 //Trigger the stop of the sortable
1292 this.instance._mouseStop(event);
1293
1294 this.instance.options.helper = this.instance.options._helper;
1295
1296 //If the helper has been the original item, restore properties in the sortable
1297 if(inst.options.helper == 'original')
1298 this.instance.currentItem.css({ top: 'auto', left: 'auto' });
1299
1300 } else {
1301 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1302 this.instance._trigger("deactivate", event, uiSortable);
1303 }
1304
1305 });
1306
1307 },
1308 drag: function(event, ui) {
1309
1310 var inst = $(this).data("draggable"), self = this;
1311
1312 var checkPos = function(o) {
1313 var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
1314 var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
1315 var itemHeight = o.height, itemWidth = o.width;
1316 var itemTop = o.top, itemLeft = o.left;
1317
1318 return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
1319 };
1320
1321 $.each(inst.sortables, function(i) {
1322
1323 //Copy over some variables to allow calling the sortable's native _intersectsWith
1324 this.instance.positionAbs = inst.positionAbs;
1325 this.instance.helperProportions = inst.helperProportions;
1326 this.instance.offset.click = inst.offset.click;
1327
1328 if(this.instance._intersectsWith(this.instance.containerCache)) {
1329
1330 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1331 if(!this.instance.isOver) {
1332
1333 this.instance.isOver = 1;
1334 //Now we fake the start of dragging for the sortable instance,
1335 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1336 //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)
1337 this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true);
1338 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1339 this.instance.options.helper = function() { return ui.helper[0]; };
1340
1341 event.target = this.instance.currentItem[0];
1342 this.instance._mouseCapture(event, true);
1343 this.instance._mouseStart(event, true, true);
1344
1345 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1346 this.instance.offset.click.top = inst.offset.click.top;
1347 this.instance.offset.click.left = inst.offset.click.left;
1348 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1349 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1350
1351 inst._trigger("toSortable", event);
1352 inst.dropped = this.instance.element; //draggable revert needs that
1353 //hack so receive/update callbacks work (mostly)
1354 inst.currentItem = inst.element;
1355 this.instance.fromOutside = inst;
1356
1357 }
1358
1359 //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
1360 if(this.instance.currentItem) this.instance._mouseDrag(event);
1361
1362 } else {
1363
1364 //If it doesn't intersect with the sortable, and it intersected before,
1365 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1366 if(this.instance.isOver) {
1367
1368 this.instance.isOver = 0;
1369 this.instance.cancelHelperRemoval = true;
1370
1371 //Prevent reverting on this forced stop
1372 this.instance.options.revert = false;
1373
1374 // The out event needs to be triggered independently
1375 this.instance._trigger('out', event, this.instance._uiHash(this.instance));
1376
1377 this.instance._mouseStop(event, true);
1378 this.instance.options.helper = this.instance.options._helper;
1379
1380 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1381 this.instance.currentItem.remove();
1382 if(this.instance.placeholder) this.instance.placeholder.remove();
1383
1384 inst._trigger("fromSortable", event);
1385 inst.dropped = false; //draggable revert needs that
1386 }
1387
1388 };
1389
1390 });
1391
1392 }
1393 });
1394
1395 $.ui.plugin.add("draggable", "cursor", {
1396 start: function(event, ui) {
1397 var t = $('body'), o = $(this).data('draggable').options;
1398 if (t.css("cursor")) o._cursor = t.css("cursor");
1399 t.css("cursor", o.cursor);
1400 },
1401 stop: function(event, ui) {
1402 var o = $(this).data('draggable').options;
1403 if (o._cursor) $('body').css("cursor", o._cursor);
1404 }
1405 });
1406
1407 $.ui.plugin.add("draggable", "opacity", {
1408 start: function(event, ui) {
1409 var t = $(ui.helper), o = $(this).data('draggable').options;
1410 if(t.css("opacity")) o._opacity = t.css("opacity");
1411 t.css('opacity', o.opacity);
1412 },
1413 stop: function(event, ui) {
1414 var o = $(this).data('draggable').options;
1415 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
1416 }
1417 });
1418
1419 $.ui.plugin.add("draggable", "scroll", {
1420 start: function(event, ui) {
1421 var i = $(this).data("draggable");
1422 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
1423 },
1424 drag: function(event, ui) {
1425
1426 var i = $(this).data("draggable"), o = i.options, scrolled = false;
1427
1428 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
1429
1430 if(!o.axis || o.axis != 'x') {
1431 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
1432 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1433 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
1434 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1435 }
1436
1437 if(!o.axis || o.axis != 'y') {
1438 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
1439 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1440 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
1441 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1442 }
1443
1444 } else {
1445
1446 if(!o.axis || o.axis != 'x') {
1447 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
1448 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1449 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
1450 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1451 }
1452
1453 if(!o.axis || o.axis != 'y') {
1454 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
1455 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1456 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
1457 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1458 }
1459
1460 }
1461
1462 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
1463 $.ui.ddmanager.prepareOffsets(i, event);
1464
1465 }
1466 });
1467
1468 $.ui.plugin.add("draggable", "snap", {
1469 start: function(event, ui) {
1470
1471 var i = $(this).data("draggable"), o = i.options;
1472 i.snapElements = [];
1473
1474 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
1475 var $t = $(this); var $o = $t.offset();
1476 if(this != i.element[0]) i.snapElements.push({
1477 item: this,
1478 width: $t.outerWidth(), height: $t.outerHeight(),
1479 top: $o.top, left: $o.left
1480 });
1481 });
1482
1483 },
1484 drag: function(event, ui) {
1485
1486 var inst = $(this).data("draggable"), o = inst.options;
1487 var d = o.snapTolerance;
1488
1489 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
1490 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
1491
1492 for (var i = inst.snapElements.length - 1; i >= 0; i--){
1493
1494 var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
1495 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
1496
1497 //Yes, I know, this is insane ;)
1498 if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
1499 if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1500 inst.snapElements[i].snapping = false;
1501 continue;
1502 }
1503
1504 if(o.snapMode != 'inner') {
1505 var ts = Math.abs(t - y2) <= d;
1506 var bs = Math.abs(b - y1) <= d;
1507 var ls = Math.abs(l - x2) <= d;
1508 var rs = Math.abs(r - x1) <= d;
1509 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1510 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1511 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1512 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1513 }
1514
1515 var first = (ts || bs || ls || rs);
1516
1517 if(o.snapMode != 'outer') {
1518 var ts = Math.abs(t - y1) <= d;
1519 var bs = Math.abs(b - y2) <= d;
1520 var ls = Math.abs(l - x1) <= d;
1521 var rs = Math.abs(r - x2) <= d;
1522 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1523 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1524 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1525 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1526 }
1527
1528 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
1529 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1530 inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1531
1532 };
1533
1534 }
1535 });
1536
1537 $.ui.plugin.add("draggable", "stack", {
1538 start: function(event, ui) {
1539
1540 var o = $(this).data("draggable").options;
1541
1542 var group = $.makeArray($(o.stack)).sort(function(a,b) {
1543 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
1544 });
1545 if (!group.length) { return; }
1546
1547 var min = parseInt(group[0].style.zIndex) || 0;
1548 $(group).each(function(i) {
1549 this.style.zIndex = min + i;
1550 });
1551
1552 this[0].style.zIndex = min + group.length;
1553
1554 }
1555 });
1556
1557 $.ui.plugin.add("draggable", "zIndex", {
1558 start: function(event, ui) {
1559 var t = $(ui.helper), o = $(this).data("draggable").options;
1560 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
1561 t.css('zIndex', o.zIndex);
1562 },
1563 stop: function(event, ui) {
1564 var o = $(this).data("draggable").options;
1565 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
1566 }
1567 });
1568
1569 })(jQuery);
1570 /*
1571 * jQuery UI Droppable 1.8.16
1572 *
1573 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
1574 * Dual licensed under the MIT or GPL Version 2 licenses.
1575 * http://jquery.org/license
1576 *
1577 * http://docs.jquery.com/UI/Droppables
1578 *
1579 * Depends:
1580 * jquery.ui.core.js
1581 * jquery.ui.widget.js
1582 * jquery.ui.mouse.js
1583 * jquery.ui.draggable.js
1584 */
1585 (function( $, undefined ) {
1586
1587 $.widget("ui.droppable", {
1588 widgetEventPrefix: "drop",
1589 options: {
1590 accept: '*',
1591 activeClass: false,
1592 addClasses: true,
1593 greedy: false,
1594 hoverClass: false,
1595 scope: 'default',
1596 tolerance: 'intersect'
1597 },
1598 _create: function() {
1599
1600 var o = this.options, accept = o.accept;
1601 this.isover = 0; this.isout = 1;
1602
1603 this.accept = $.isFunction(accept) ? accept : function(d) {
1604 return d.is(accept);
1605 };
1606
1607 //Store the droppable's proportions
1608 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
1609
1610 // Add the reference and positions to the manager
1611 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
1612 $.ui.ddmanager.droppables[o.scope].push(this);
1613
1614 (o.addClasses && this.element.addClass("ui-droppable"));
1615
1616 },
1617
1618 destroy: function() {
1619 var drop = $.ui.ddmanager.droppables[this.options.scope];
1620 for ( var i = 0; i < drop.length; i++ )
1621 if ( drop[i] == this )
1622 drop.splice(i, 1);
1623
1624 this.element
1625 .removeClass("ui-droppable ui-droppable-disabled")
1626 .removeData("droppable")
1627 .unbind(".droppable");
1628
1629 return this;
1630 },
1631
1632 _setOption: function(key, value) {
1633
1634 if(key == 'accept') {
1635 this.accept = $.isFunction(value) ? value : function(d) {
1636 return d.is(value);
1637 };
1638 }
1639 $.Widget.prototype._setOption.apply(this, arguments);
1640 },
1641
1642 _activate: function(event) {
1643 var draggable = $.ui.ddmanager.current;
1644 if(this.options.activeClass) this.element.addClass(this.options.activeClass);
1645 (draggable && this._trigger('activate', event, this.ui(draggable)));
1646 },
1647
1648 _deactivate: function(event) {
1649 var draggable = $.ui.ddmanager.current;
1650 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1651 (draggable && this._trigger('deactivate', event, this.ui(draggable)));
1652 },
1653
1654 _over: function(event) {
1655
1656 var draggable = $.ui.ddmanager.current;
1657 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1658
1659 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1660 if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
1661 this._trigger('over', event, this.ui(draggable));
1662 }
1663
1664 },
1665
1666 _out: function(event) {
1667
1668 var draggable = $.ui.ddmanager.current;
1669 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1670
1671 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1672 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1673 this._trigger('out', event, this.ui(draggable));
1674 }
1675
1676 },
1677
1678 _drop: function(event,custom) {
1679
1680 var draggable = custom || $.ui.ddmanager.current;
1681 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
1682
1683 var childrenIntersection = false;
1684 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
1685 var inst = $.data(this, 'droppable');
1686 if(
1687 inst.options.greedy
1688 && !inst.options.disabled
1689 && inst.options.scope == draggable.options.scope
1690 && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
1691 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
1692 ) { childrenIntersection = true; return false; }
1693 });
1694 if(childrenIntersection) return false;
1695
1696 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1697 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1698 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1699 this._trigger('drop', event, this.ui(draggable));
1700 return this.element;
1701 }
1702
1703 return false;
1704
1705 },
1706
1707 ui: function(c) {
1708 return {
1709 draggable: (c.currentItem || c.element),
1710 helper: c.helper,
1711 position: c.position,
1712 offset: c.positionAbs
1713 };
1714 }
1715
1716 });
1717
1718 $.extend($.ui.droppable, {
1719 version: "1.8.16"
1720 });
1721
1722 $.ui.intersect = function(draggable, droppable, toleranceMode) {
1723
1724 if (!droppable.offset) return false;
1725
1726 var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
1727 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
1728 var l = droppable.offset.left, r = l + droppable.proportions.width,
1729 t = droppable.offset.top, b = t + droppable.proportions.height;
1730
1731 switch (toleranceMode) {
1732 case 'fit':
1733 return (l <= x1 && x2 <= r
1734 && t <= y1 && y2 <= b);
1735 break;
1736 case 'intersect':
1737 return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
1738 && x2 - (draggable.helperProportions.width / 2) < r // Left Half
1739 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
1740 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
1741 break;
1742 case 'pointer':
1743 var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
1744 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
1745 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
1746 return isOver;
1747 break;
1748 case 'touch':
1749 return (
1750 (y1 >= t && y1 <= b) || // Top edge touching
1751 (y2 >= t && y2 <= b) || // Bottom edge touching
1752 (y1 < t && y2 > b) // Surrounded vertically
1753 ) && (
1754 (x1 >= l && x1 <= r) || // Left edge touching
1755 (x2 >= l && x2 <= r) || // Right edge touching
1756 (x1 < l && x2 > r) // Surrounded horizontally
1757 );
1758 break;
1759 default:
1760 return false;
1761 break;
1762 }
1763
1764 };
1765
1766 /*
1767 This manager tracks offsets of draggables and droppables
1768 */
1769 $.ui.ddmanager = {
1770 current: null,
1771 droppables: { 'default': [] },
1772 prepareOffsets: function(t, event) {
1773
1774 var m = $.ui.ddmanager.droppables[t.options.scope] || [];
1775 var type = event ? event.type : null; // workaround for #2317
1776 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
1777
1778 droppablesLoop: for (var i = 0; i < m.length; i++) {
1779
1780 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted
1781 for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
1782 m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue
1783
1784 if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
1785
1786 m[i].offset = m[i].element.offset();
1787 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
1788
1789 }
1790
1791 },
1792 drop: function(draggable, event) {
1793
1794 var dropped = false;
1795 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
1796
1797 if(!this.options) return;
1798 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
1799 dropped = dropped || this._drop.call(this, event);
1800
1801 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1802 this.isout = 1; this.isover = 0;
1803 this._deactivate.call(this, event);
1804 }
1805
1806 });
1807 return dropped;
1808
1809 },
1810 dragStart: function( draggable, event ) {
1811 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
1812 draggable.element.parents( ":not(body,html)" ).bind( "scroll.droppable", function() {
1813 if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
1814 });
1815 },
1816 drag: function(draggable, event) {
1817
1818 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
1819 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
1820
1821 //Run through all droppables and check their positions based on specific tolerance options
1822 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
1823
1824 if(this.options.disabled || this.greedyChild || !this.visible) return;
1825 var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
1826
1827 var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
1828 if(!c) return;
1829
1830 var parentInstance;
1831 if (this.options.greedy) {
1832 var parent = this.element.parents(':data(droppable):eq(0)');
1833 if (parent.length) {
1834 parentInstance = $.data(parent[0], 'droppable');
1835 parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
1836 }
1837 }
1838
1839 // we just moved into a greedy child
1840 if (parentInstance && c == 'isover') {
1841 parentInstance['isover'] = 0;
1842 parentInstance['isout'] = 1;
1843 parentInstance._out.call(parentInstance, event);
1844 }
1845
1846 this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
1847 this[c == "isover" ? "_over" : "_out"].call(this, event);
1848
1849 // we just moved out of a greedy child
1850 if (parentInstance && c == 'isout') {
1851 parentInstance['isout'] = 0;
1852 parentInstance['isover'] = 1;
1853 parentInstance._over.call(parentInstance, event);
1854 }
1855 });
1856
1857 },
1858 dragStop: function( draggable, event ) {
1859 draggable.element.parents( ":not(body,html)" ).unbind( "scroll.droppable" );
1860 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
1861 if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
1862 }
1863 };
1864
1865 })(jQuery);
1866 /*
1867 * jQuery UI Resizable 1.8.16
1868 *
1869 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
1870 * Dual licensed under the MIT or GPL Version 2 licenses.
1871 * http://jquery.org/license
1872 *
1873 * http://docs.jquery.com/UI/Resizables
1874 *
1875 * Depends:
1876 * jquery.ui.core.js
1877 * jquery.ui.mouse.js
1878 * jquery.ui.widget.js
1879 */
1880 (function( $, undefined ) {
1881
1882 $.widget("ui.resizable", $.ui.mouse, {
1883 widgetEventPrefix: "resize",
1884 options: {
1885 alsoResize: false,
1886 animate: false,
1887 animateDuration: "slow",
1888 animateEasing: "swing",
1889 aspectRatio: false,
1890 autoHide: false,
1891 containment: false,
1892 ghost: false,
1893 grid: false,
1894 handles: "e,s,se",
1895 helper: false,
1896 maxHeight: null,
1897 maxWidth: null,
1898 minHeight: 10,
1899 minWidth: 10,
1900 zIndex: 1000
1901 },
1902 _create: function() {
1903
1904 var self = this, o = this.options;
1905 this.element.addClass("ui-resizable");
1906
1907 $.extend(this, {
1908 _aspectRatio: !!(o.aspectRatio),
1909 aspectRatio: o.aspectRatio,
1910 originalElement: this.element,
1911 _proportionallyResizeElements: [],
1912 _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
1913 });
1914
1915 //Wrap the element if it cannot hold child nodes
1916 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
1917
1918 //Opera fix for relative positioning
1919 if (/relative/.test(this.element.css('position')) && $.browser.opera)
1920 this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
1921
1922 //Create a wrapper element and set the wrapper to the new current internal element
1923 this.element.wrap(
1924 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
1925 position: this.element.css('position'),
1926 width: this.element.outerWidth(),
1927 height: this.element.outerHeight(),
1928 top: this.element.css('top'),
1929 left: this.element.css('left')
1930 })
1931 );
1932
1933 //Overwrite the original this.element
1934 this.element = this.element.parent().data(
1935 "resizable", this.element.data('resizable')
1936 );
1937
1938 this.elementIsWrapper = true;
1939
1940 //Move margins to the wrapper
1941 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
1942 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
1943
1944 //Prevent Safari textarea resize
1945 this.originalResizeStyle = this.originalElement.css('resize');
1946 this.originalElement.css('resize', 'none');
1947
1948 //Push the actual element to our proportionallyResize internal array
1949 this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
1950
1951 // avoid IE jump (hard set the margin)
1952 this.originalElement.css({ margin: this.originalElement.css('margin') });
1953
1954 // fix handlers offset
1955 this._proportionallyResize();
1956
1957 }
1958
1959 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' });
1960 if(this.handles.constructor == String) {
1961
1962 if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
1963 var n = this.handles.split(","); this.handles = {};
1964
1965 for(var i = 0; i < n.length; i++) {
1966
1967 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
1968 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
1969
1970 // increase zIndex of sw, se, ne, nw axis
1971 //TODO : this modifies original option
1972 if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
1973
1974 //TODO : What's going on here?
1975 if ('se' == handle) {
1976 axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
1977 };
1978
1979 //Insert into internal handles object and append to element
1980 this.handles[handle] = '.ui-resizable-'+handle;
1981 this.element.append(axis);
1982 }
1983
1984 }
1985
1986 this._renderAxis = function(target) {
1987
1988 target = target || this.element;
1989
1990 for(var i in this.handles) {
1991
1992 if(this.handles[i].constructor == String)
1993 this.handles[i] = $(this.handles[i], this.element).show();
1994
1995 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
1996 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
1997
1998 var axis = $(this.handles[i], this.element), padWrapper = 0;
1999
2000 //Checking the correct pad and border
2001 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
2002
2003 //The padding type i have to apply...
2004 var padPos = [ 'padding',
2005 /ne|nw|n/.test(i) ? 'Top' :
2006 /se|sw|s/.test(i) ? 'Bottom' :
2007 /^e$/.test(i) ? 'Right' : 'Left' ].join("");
2008
2009 target.css(padPos, padWrapper);
2010
2011 this._proportionallyResize();
2012
2013 }
2014
2015 //TODO: What's that good for? There's not anything to be executed left
2016 if(!$(this.handles[i]).length)
2017 continue;
2018
2019 }
2020 };
2021
2022 //TODO: make renderAxis a prototype function
2023 this._renderAxis(this.element);
2024
2025 this._handles = $('.ui-resizable-handle', this.element)
2026 .disableSelection();
2027
2028 //Matching axis name
2029 this._handles.mouseover(function() {
2030 if (!self.resizing) {
2031 if (this.className)
2032 var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
2033 //Axis, default = se
2034 self.axis = axis && axis[1] ? axis[1] : 'se';
2035 }
2036 });
2037
2038 //If we want to auto hide the elements
2039 if (o.autoHide) {
2040 this._handles.hide();
2041 $(this.element)
2042 .addClass("ui-resizable-autohide")
2043 .hover(function() {
2044 if (o.disabled) return;
2045 $(this).removeClass("ui-resizable-autohide");
2046 self._handles.show();
2047 },
2048 function(){
2049 if (o.disabled) return;
2050 if (!self.resizing) {
2051 $(this).addClass("ui-resizable-autohide");
2052 self._handles.hide();
2053 }
2054 });
2055 }
2056
2057 //Initialize the mouse interaction
2058 this._mouseInit();
2059
2060 },
2061
2062 destroy: function() {
2063
2064 this._mouseDestroy();
2065
2066 var _destroy = function(exp) {
2067 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
2068 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
2069 };
2070
2071 //TODO: Unwrap at same DOM position
2072 if (this.elementIsWrapper) {
2073 _destroy(this.element);
2074 var wrapper = this.element;
2075 wrapper.after(
2076 this.originalElement.css({
2077 position: wrapper.css('position'),
2078 width: wrapper.outerWidth(),
2079 height: wrapper.outerHeight(),
2080 top: wrapper.css('top'),
2081 left: wrapper.css('left')
2082 })
2083 ).remove();
2084 }
2085
2086 this.originalElement.css('resize', this.originalResizeStyle);
2087 _destroy(this.originalElement);
2088
2089 return this;
2090 },
2091
2092 _mouseCapture: function(event) {
2093 var handle = false;
2094 for (var i in this.handles) {
2095 if ($(this.handles[i])[0] == event.target) {
2096 handle = true;
2097 }
2098 }
2099
2100 return !this.options.disabled && handle;
2101 },
2102
2103 _mouseStart: function(event) {
2104
2105 var o = this.options, iniPos = this.element.position(), el = this.element;
2106
2107 this.resizing = true;
2108 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
2109
2110 // bugfix for http://dev.jquery.com/ticket/1749
2111 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
2112 el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
2113 }
2114
2115 //Opera fixing relative position
2116 if ($.browser.opera && (/relative/).test(el.css('position')))
2117 el.css({ position: 'relative', top: 'auto', left: 'auto' });
2118
2119 this._renderProxy();
2120
2121 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
2122
2123 if (o.containment) {
2124 curleft += $(o.containment).scrollLeft() || 0;
2125 curtop += $(o.containment).scrollTop() || 0;
2126 }
2127
2128 //Store needed variables
2129 this.offset = this.helper.offset();
2130 this.position = { left: curleft, top: curtop };
2131 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2132 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2133 this.originalPosition = { left: curleft, top: curtop };
2134 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
2135 this.originalMousePosition = { left: event.pageX, top: event.pageY };
2136
2137 //Aspect Ratio
2138 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
2139
2140 var cursor = $('.ui-resizable-' + this.axis).css('cursor');
2141 $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
2142
2143 el.addClass("ui-resizable-resizing");
2144 this._propagate("start", event);
2145 return true;
2146 },
2147
2148 _mouseDrag: function(event) {
2149
2150 //Increase performance, avoid regex
2151 var el = this.helper, o = this.options, props = {},
2152 self = this, smp = this.originalMousePosition, a = this.axis;
2153
2154 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
2155 var trigger = this._change[a];
2156 if (!trigger) return false;
2157
2158 // Calculate the attrs that will be change
2159 var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
2160
2161 // Put this in the mouseDrag handler since the user can start pressing shift while resizing
2162 this._updateVirtualBoundaries(event.shiftKey);
2163 if (this._aspectRatio || event.shiftKey)
2164 data = this._updateRatio(data, event);
2165
2166 data = this._respectSize(data, event);
2167
2168 // plugins callbacks need to be called first
2169 this._propagate("resize", event);
2170
2171 el.css({
2172 top: this.position.top + "px", left: this.position.left + "px",
2173 width: this.size.width + "px", height: this.size.height + "px"
2174 });
2175
2176 if (!this._helper && this._proportionallyResizeElements.length)
2177 this._proportionallyResize();
2178
2179 this._updateCache(data);
2180
2181 // calling the user callback at the end
2182 this._trigger('resize', event, this.ui());
2183
2184 return false;
2185 },
2186
2187 _mouseStop: function(event) {
2188
2189 this.resizing = false;
2190 var o = this.options, self = this;
2191
2192 if(this._helper) {
2193 var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2194 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2195 soffsetw = ista ? 0 : self.sizeDiff.width;
2196
2197 var s = { width: (self.helper.width() - soffsetw), height: (self.helper.height() - soffseth) },
2198 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2199 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2200
2201 if (!o.animate)
2202 this.element.css($.extend(s, { top: top, left: left }));
2203
2204 self.helper.height(self.size.height);
2205 self.helper.width(self.size.width);
2206
2207 if (this._helper && !o.animate) this._proportionallyResize();
2208 }
2209
2210 $('body').css('cursor', 'auto');
2211
2212 this.element.removeClass("ui-resizable-resizing");
2213
2214 this._propagate("stop", event);
2215
2216 if (this._helper) this.helper.remove();
2217 return false;
2218
2219 },
2220
2221 _updateVirtualBoundaries: function(forceAspectRatio) {
2222 var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b;
2223
2224 b = {
2225 minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
2226 maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
2227 minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
2228 maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
2229 };
2230
2231 if(this._aspectRatio || forceAspectRatio) {
2232 // We want to create an enclosing box whose aspect ration is the requested one
2233 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
2234 pMinWidth = b.minHeight * this.aspectRatio;
2235 pMinHeight = b.minWidth / this.aspectRatio;
2236 pMaxWidth = b.maxHeight * this.aspectRatio;
2237 pMaxHeight = b.maxWidth / this.aspectRatio;
2238
2239 if(pMinWidth > b.minWidth) b.minWidth = pMinWidth;
2240 if(pMinHeight > b.minHeight) b.minHeight = pMinHeight;
2241 if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth;
2242 if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight;
2243 }
2244 this._vBoundaries = b;
2245 },
2246
2247 _updateCache: function(data) {
2248 var o = this.options;
2249 this.offset = this.helper.offset();
2250 if (isNumber(data.left)) this.position.left = data.left;
2251 if (isNumber(data.top)) this.position.top = data.top;
2252 if (isNumber(data.height)) this.size.height = data.height;
2253 if (isNumber(data.width)) this.size.width = data.width;
2254 },
2255
2256 _updateRatio: function(data, event) {
2257
2258 var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
2259
2260 if (isNumber(data.height)) data.width = (data.height * this.aspectRatio);
2261 else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio);
2262
2263 if (a == 'sw') {
2264 data.left = cpos.left + (csize.width - data.width);
2265 data.top = null;
2266 }
2267 if (a == 'nw') {
2268 data.top = cpos.top + (csize.height - data.height);
2269 data.left = cpos.left + (csize.width - data.width);
2270 }
2271
2272 return data;
2273 },
2274
2275 _respectSize: function(data, event) {
2276
2277 var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
2278 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
2279 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
2280
2281 if (isminw) data.width = o.minWidth;
2282 if (isminh) data.height = o.minHeight;
2283 if (ismaxw) data.width = o.maxWidth;
2284 if (ismaxh) data.height = o.maxHeight;
2285
2286 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
2287 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
2288
2289 if (isminw && cw) data.left = dw - o.minWidth;
2290 if (ismaxw && cw) data.left = dw - o.maxWidth;
2291 if (isminh && ch) data.top = dh - o.minHeight;
2292 if (ismaxh && ch) data.top = dh - o.maxHeight;
2293
2294 // fixing jump error on top/left - bug #2330
2295 var isNotwh = !data.width && !data.height;
2296 if (isNotwh && !data.left && data.top) data.top = null;
2297 else if (isNotwh && !data.top && data.left) data.left = null;
2298
2299 return data;
2300 },
2301
2302 _proportionallyResize: function() {
2303
2304 var o = this.options;
2305 if (!this._proportionallyResizeElements.length) return;
2306 var element = this.helper || this.element;
2307
2308 for (var i=0; i < this._proportionallyResizeElements.length; i++) {
2309
2310 var prel = this._proportionallyResizeElements[i];
2311
2312 if (!this.borderDif) {
2313 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
2314 p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
2315
2316 this.borderDif = $.map(b, function(v, i) {
2317 var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
2318 return border + padding;
2319 });
2320 }
2321
2322 if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
2323 continue;
2324
2325 prel.css({
2326 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
2327 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
2328 });
2329
2330 };
2331
2332 },
2333
2334 _renderProxy: function() {
2335
2336 var el = this.element, o = this.options;
2337 this.elementOffset = el.offset();
2338
2339 if(this._helper) {
2340
2341 this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
2342
2343 // fix ie6 offset TODO: This seems broken
2344 var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
2345 pxyoffset = ( ie6 ? 2 : -1 );
2346
2347 this.helper.addClass(this._helper).css({
2348 width: this.element.outerWidth() + pxyoffset,
2349 height: this.element.outerHeight() + pxyoffset,
2350 position: 'absolute',
2351 left: this.elementOffset.left - ie6offset +'px',
2352 top: this.elementOffset.top - ie6offset +'px',
2353 zIndex: ++o.zIndex //TODO: Don't modify option
2354 });
2355
2356 this.helper
2357 .appendTo("body")
2358 .disableSelection();
2359
2360 } else {
2361 this.helper = this.element;
2362 }
2363
2364 },
2365
2366 _change: {
2367 e: function(event, dx, dy) {
2368 return { width: this.originalSize.width + dx };
2369 },
2370 w: function(event, dx, dy) {
2371 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2372 return { left: sp.left + dx, width: cs.width - dx };
2373 },
2374 n: function(event, dx, dy) {
2375 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2376 return { top: sp.top + dy, height: cs.height - dy };
2377 },
2378 s: function(event, dx, dy) {
2379 return { height: this.originalSize.height + dy };
2380 },
2381 se: function(event, dx, dy) {
2382 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2383 },
2384 sw: function(event, dx, dy) {
2385 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2386 },
2387 ne: function(event, dx, dy) {
2388 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2389 },
2390 nw: function(event, dx, dy) {
2391 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2392 }
2393 },
2394
2395 _propagate: function(n, event) {
2396 $.ui.plugin.call(this, n, [event, this.ui()]);
2397 (n != "resize" && this._trigger(n, event, this.ui()));
2398 },
2399
2400 plugins: {},
2401
2402 ui: function() {
2403 return {
2404 originalElement: this.originalElement,
2405 element: this.element,
2406 helper: this.helper,
2407 position: this.position,
2408 size: this.size,
2409 originalSize: this.originalSize,
2410 originalPosition: this.originalPosition
2411 };
2412 }
2413
2414 });
2415
2416 $.extend($.ui.resizable, {
2417 version: "1.8.16"
2418 });
2419
2420 /*
2421 * Resizable Extensions
2422 */
2423
2424 $.ui.plugin.add("resizable", "alsoResize", {
2425
2426 start: function (event, ui) {
2427 var self = $(this).data("resizable"), o = self.options;
2428
2429 var _store = function (exp) {
2430 $(exp).each(function() {
2431 var el = $(this);
2432 el.data("resizable-alsoresize", {
2433 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
2434 left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
2435 position: el.css('position') // to reset Opera on stop()
2436 });
2437 });
2438 };
2439
2440 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
2441 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
2442 else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
2443 }else{
2444 _store(o.alsoResize);
2445 }
2446 },
2447
2448 resize: function (event, ui) {
2449 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
2450
2451 var delta = {
2452 height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
2453 top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
2454 },
2455
2456 _alsoResize = function (exp, c) {
2457 $(exp).each(function() {
2458 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {},
2459 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
2460
2461 $.each(css, function (i, prop) {
2462 var sum = (start[prop]||0) + (delta[prop]||0);
2463 if (sum && sum >= 0)
2464 style[prop] = sum || null;
2465 });
2466
2467 // Opera fixing relative position
2468 if ($.browser.opera && /relative/.test(el.css('position'))) {
2469 self._revertToRelativePosition = true;
2470 el.css({ position: 'absolute', top: 'auto', left: 'auto' });
2471 }
2472
2473 el.css(style);
2474 });
2475 };
2476
2477 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2478 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
2479 }else{
2480 _alsoResize(o.alsoResize);
2481 }
2482 },
2483
2484 stop: function (event, ui) {
2485 var self = $(this).data("resizable"), o = self.options;
2486
2487 var _reset = function (exp) {
2488 $(exp).each(function() {
2489 var el = $(this);
2490 // reset position for Opera - no need to verify it was changed
2491 el.css({ position: el.data("resizable-alsoresize").position });
2492 });
2493 };
2494
2495 if (self._revertToRelativePosition) {
2496 self._revertToRelativePosition = false;
2497 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2498 $.each(o.alsoResize, function (exp) { _reset(exp); });
2499 }else{
2500 _reset(o.alsoResize);
2501 }
2502 }
2503
2504 $(this).removeData("resizable-alsoresize");
2505 }
2506 });
2507
2508 $.ui.plugin.add("resizable", "animate", {
2509
2510 stop: function(event, ui) {
2511 var self = $(this).data("resizable"), o = self.options;
2512
2513 var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2514 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2515 soffsetw = ista ? 0 : self.sizeDiff.width;
2516
2517 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
2518 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2519 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2520
2521 self.element.animate(
2522 $.extend(style, top && left ? { top: top, left: left } : {}), {
2523 duration: o.animateDuration,
2524 easing: o.animateEasing,
2525 step: function() {
2526
2527 var data = {
2528 width: parseInt(self.element.css('width'), 10),
2529 height: parseInt(self.element.css('height'), 10),
2530 top: parseInt(self.element.css('top'), 10),
2531 left: parseInt(self.element.css('left'), 10)
2532 };
2533
2534 if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
2535
2536 // propagating resize, and updating values for each animation step
2537 self._updateCache(data);
2538 self._propagate("resize", event);
2539
2540 }
2541 }
2542 );
2543 }
2544
2545 });
2546
2547 $.ui.plugin.add("resizable", "containment", {
2548
2549 start: function(event, ui) {
2550 var self = $(this).data("resizable"), o = self.options, el = self.element;
2551 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
2552 if (!ce) return;
2553
2554 self.containerElement = $(ce);
2555
2556 if (/document/.test(oc) || oc == document) {
2557 self.containerOffset = { left: 0, top: 0 };
2558 self.containerPosition = { left: 0, top: 0 };
2559
2560 self.parentData = {
2561 element: $(document), left: 0, top: 0,
2562 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
2563 };
2564 }
2565
2566 // i'm a node, so compute top, left, right, bottom
2567 else {
2568 var element = $(ce), p = [];
2569 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
2570
2571 self.containerOffset = element.offset();
2572 self.containerPosition = element.position();
2573 self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
2574
2575 var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width,
2576 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
2577
2578 self.parentData = {
2579 element: ce, left: co.left, top: co.top, width: width, height: height
2580 };
2581 }
2582 },
2583
2584 resize: function(event, ui) {
2585 var self = $(this).data("resizable"), o = self.options,
2586 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
2587 pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
2588
2589 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
2590
2591 if (cp.left < (self._helper ? co.left : 0)) {
2592 self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
2593 if (pRatio) self.size.height = self.size.width / o.aspectRatio;
2594 self.position.left = o.helper ? co.left : 0;
2595 }
2596
2597 if (cp.top < (self._helper ? co.top : 0)) {
2598 self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
2599 if (pRatio) self.size.width = self.size.height * o.aspectRatio;
2600 self.position.top = self._helper ? co.top : 0;
2601 }
2602
2603 self.offset.left = self.parentData.left+self.position.left;
2604 self.offset.top = self.parentData.top+self.position.top;
2605
2606 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
2607 hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
2608
2609 var isParent = self.containerElement.get(0) == self.element.parent().get(0),
2610 isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
2611
2612 if(isParent && isOffsetRelative) woset -= self.parentData.left;
2613
2614 if (woset + self.size.width >= self.parentData.width) {
2615 self.size.width = self.parentData.width - woset;
2616 if (pRatio) self.size.height = self.size.width / self.aspectRatio;
2617 }
2618
2619 if (hoset + self.size.height >= self.parentData.height) {
2620 self.size.height = self.parentData.height - hoset;
2621 if (pRatio) self.size.width = self.size.height * self.aspectRatio;
2622 }
2623 },
2624
2625 stop: function(event, ui){
2626 var self = $(this).data("resizable"), o = self.options, cp = self.position,
2627 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
2628
2629 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
2630
2631 if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
2632 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2633
2634 if (self._helper && !o.animate && (/static/).test(ce.css('position')))
2635 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2636
2637 }
2638 });
2639
2640 $.ui.plugin.add("resizable", "ghost", {
2641
2642 start: function(event, ui) {
2643
2644 var self = $(this).data("resizable"), o = self.options, cs = self.size;
2645
2646 self.ghost = self.originalElement.clone();
2647 self.ghost
2648 .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
2649 .addClass('ui-resizable-ghost')
2650 .addClass(typeof o.ghost == 'string' ? o.ghost : '');
2651
2652 self.ghost.appendTo(self.helper);
2653
2654 },
2655
2656 resize: function(event, ui){
2657 var self = $(this).data("resizable"), o = self.options;
2658 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
2659 },
2660
2661 stop: function(event, ui){
2662 var self = $(this).data("resizable"), o = self.options;
2663 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
2664 }
2665
2666 });
2667
2668 $.ui.plugin.add("resizable", "grid", {
2669
2670 resize: function(event, ui) {
2671 var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
2672 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
2673 var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
2674
2675 if (/^(se|s|e)$/.test(a)) {
2676 self.size.width = os.width + ox;
2677 self.size.height = os.height + oy;
2678 }
2679 else if (/^(ne)$/.test(a)) {
2680 self.size.width = os.width + ox;
2681 self.size.height = os.height + oy;
2682 self.position.top = op.top - oy;
2683 }
2684 else if (/^(sw)$/.test(a)) {
2685 self.size.width = os.width + ox;
2686 self.size.height = os.height + oy;
2687 self.position.left = op.left - ox;
2688 }
2689 else {
2690 self.size.width = os.width + ox;
2691 self.size.height = os.height + oy;
2692 self.position.top = op.top - oy;
2693 self.position.left = op.left - ox;
2694 }
2695 }
2696
2697 });
2698
2699 var num = function(v) {
2700 return parseInt(v, 10) || 0;
2701 };
2702
2703 var isNumber = function(value) {
2704 return !isNaN(parseInt(value, 10));
2705 };
2706
2707 })(jQuery);
2708 /*
2709 * jQuery UI Selectable 1.8.16
2710 *
2711 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
2712 * Dual licensed under the MIT or GPL Version 2 licenses.
2713 * http://jquery.org/license
2714 *
2715 * http://docs.jquery.com/UI/Selectables
2716 *
2717 * Depends:
2718 * jquery.ui.core.js
2719 * jquery.ui.mouse.js
2720 * jquery.ui.widget.js
2721 */
2722 (function( $, undefined ) {
2723
2724 $.widget("ui.selectable", $.ui.mouse, {
2725 options: {
2726 appendTo: 'body',
2727 autoRefresh: true,
2728 distance: 0,
2729 filter: '*',
2730 tolerance: 'touch'
2731 },
2732 _create: function() {
2733 var self = this;
2734
2735 this.element.addClass("ui-selectable");
2736
2737 this.dragged = false;
2738
2739 // cache selectee children based on filter
2740 var selectees;
2741 this.refresh = function() {
2742 selectees = $(self.options.filter, self.element[0]);
2743 selectees.each(function() {
2744 var $this = $(this);
2745 var pos = $this.offset();
2746 $.data(this, "selectable-item", {
2747 element: this,
2748 $element: $this,
2749 left: pos.left,
2750 top: pos.top,
2751 right: pos.left + $this.outerWidth(),
2752 bottom: pos.top + $this.outerHeight(),
2753 startselected: false,
2754 selected: $this.hasClass('ui-selected'),
2755 selecting: $this.hasClass('ui-selecting'),
2756 unselecting: $this.hasClass('ui-unselecting')
2757 });
2758 });
2759 };
2760 this.refresh();
2761
2762 this.selectees = selectees.addClass("ui-selectee");
2763
2764 this._mouseInit();
2765
2766 this.helper = $("<div class='ui-selectable-helper'></div>");
2767 },
2768
2769 destroy: function() {
2770 this.selectees
2771 .removeClass("ui-selectee")
2772 .removeData("selectable-item");
2773 this.element
2774 .removeClass("ui-selectable ui-selectable-disabled")
2775 .removeData("selectable")
2776 .unbind(".selectable");
2777 this._mouseDestroy();
2778
2779 return this;
2780 },
2781
2782 _mouseStart: function(event) {
2783 var self = this;
2784
2785 this.opos = [event.pageX, event.pageY];
2786
2787 if (this.options.disabled)
2788 return;
2789
2790 var options = this.options;
2791
2792 this.selectees = $(options.filter, this.element[0]);
2793
2794 this._trigger("start", event);
2795
2796 $(options.appendTo).append(this.helper);
2797 // position helper (lasso)
2798 this.helper.css({
2799 "left": event.clientX,
2800 "top": event.clientY,
2801 "width": 0,
2802 "height": 0
2803 });
2804
2805 if (options.autoRefresh) {
2806 this.refresh();
2807 }
2808
2809 this.selectees.filter('.ui-selected').each(function() {
2810 var selectee = $.data(this, "selectable-item");
2811 selectee.startselected = true;
2812 if (!event.metaKey) {
2813 selectee.$element.removeClass('ui-selected');
2814 selectee.selected = false;
2815 selectee.$element.addClass('ui-unselecting');
2816 selectee.unselecting = true;
2817 // selectable UNSELECTING callback
2818 self._trigger("unselecting", event, {
2819 unselecting: selectee.element
2820 });
2821 }
2822 });
2823
2824 $(event.target).parents().andSelf().each(function() {
2825 var selectee = $.data(this, "selectable-item");
2826 if (selectee) {
2827 var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
2828 selectee.$element
2829 .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
2830 .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
2831 selectee.unselecting = !doSelect;
2832 selectee.selecting = doSelect;
2833 selectee.selected = doSelect;
2834 // selectable (UN)SELECTING callback
2835 if (doSelect) {
2836 self._trigger("selecting", event, {
2837 selecting: selectee.element
2838 });
2839 } else {
2840 self._trigger("unselecting", event, {
2841 unselecting: selectee.element
2842 });
2843 }
2844 return false;
2845 }
2846 });
2847
2848 },
2849
2850 _mouseDrag: function(event) {
2851 var self = this;
2852 this.dragged = true;
2853
2854 if (this.options.disabled)
2855 return;
2856
2857 var options = this.options;
2858
2859 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
2860 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
2861 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
2862 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
2863
2864 this.selectees.each(function() {
2865 var selectee = $.data(this, "selectable-item");
2866 //prevent helper from being selected if appendTo: selectable
2867 if (!selectee || selectee.element == self.element[0])
2868 return;
2869 var hit = false;
2870 if (options.tolerance == 'touch') {
2871 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
2872 } else if (options.tolerance == 'fit') {
2873 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
2874 }
2875
2876 if (hit) {
2877 // SELECT
2878 if (selectee.selected) {
2879 selectee.$element.removeClass('ui-selected');
2880 selectee.selected = false;
2881 }
2882 if (selectee.unselecting) {
2883 selectee.$element.removeClass('ui-unselecting');
2884 selectee.unselecting = false;
2885 }
2886 if (!selectee.selecting) {
2887 selectee.$element.addClass('ui-selecting');
2888 selectee.selecting = true;
2889 // selectable SELECTING callback
2890 self._trigger("selecting", event, {
2891 selecting: selectee.element
2892 });
2893 }
2894 } else {
2895 // UNSELECT
2896 if (selectee.selecting) {
2897 if (event.metaKey && selectee.startselected) {
2898 selectee.$element.removeClass('ui-selecting');
2899 selectee.selecting = false;
2900 selectee.$element.addClass('ui-selected');
2901 selectee.selected = true;
2902 } else {
2903 selectee.$element.removeClass('ui-selecting');
2904 selectee.selecting = false;
2905 if (selectee.startselected) {
2906 selectee.$element.addClass('ui-unselecting');
2907 selectee.unselecting = true;
2908 }
2909 // selectable UNSELECTING callback
2910 self._trigger("unselecting", event, {
2911 unselecting: selectee.element
2912 });
2913 }
2914 }
2915 if (selectee.selected) {
2916 if (!event.metaKey && !selectee.startselected) {
2917 selectee.$element.removeClass('ui-selected');
2918 selectee.selected = false;
2919
2920 selectee.$element.addClass('ui-unselecting');
2921 selectee.unselecting = true;
2922 // selectable UNSELECTING callback
2923 self._trigger("unselecting", event, {
2924 unselecting: selectee.element
2925 });
2926 }
2927 }
2928 }
2929 });
2930
2931 return false;
2932 },
2933
2934 _mouseStop: function(event) {
2935 var self = this;
2936
2937 this.dragged = false;
2938
2939 var options = this.options;
2940
2941 $('.ui-unselecting', this.element[0]).each(function() {
2942 var selectee = $.data(this, "selectable-item");
2943 selectee.$element.removeClass('ui-unselecting');
2944 selectee.unselecting = false;
2945 selectee.startselected = false;
2946 self._trigger("unselected", event, {
2947 unselected: selectee.element
2948 });
2949 });
2950 $('.ui-selecting', this.element[0]).each(function() {
2951 var selectee = $.data(this, "selectable-item");
2952 selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
2953 selectee.selecting = false;
2954 selectee.selected = true;
2955 selectee.startselected = true;
2956 self._trigger("selected", event, {
2957 selected: selectee.element
2958 });
2959 });
2960 this._trigger("stop", event);
2961
2962 this.helper.remove();
2963
2964 return false;
2965 }
2966
2967 });
2968
2969 $.extend($.ui.selectable, {
2970 version: "1.8.16"
2971 });
2972
2973 })(jQuery);
2974 /*
2975 * jQuery UI Sortable 1.8.16
2976 *
2977 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
2978 * Dual licensed under the MIT or GPL Version 2 licenses.
2979 * http://jquery.org/license
2980 *
2981 * http://docs.jquery.com/UI/Sortables
2982 *
2983 * Depends:
2984 * jquery.ui.core.js
2985 * jquery.ui.mouse.js
2986 * jquery.ui.widget.js
2987 */
2988 (function( $, undefined ) {
2989
2990 $.widget("ui.sortable", $.ui.mouse, {
2991 widgetEventPrefix: "sort",
2992 options: {
2993 appendTo: "parent",
2994 axis: false,
2995 connectWith: false,
2996 containment: false,
2997 cursor: 'auto',
2998 cursorAt: false,
2999 dropOnEmpty: true,
3000 forcePlaceholderSize: false,
3001 forceHelperSize: false,
3002 grid: false,
3003 handle: false,
3004 helper: "original",
3005 items: '> *',
3006 opacity: false,
3007 placeholder: false,
3008 revert: false,
3009 scroll: true,
3010 scrollSensitivity: 20,
3011 scrollSpeed: 20,
3012 scope: "default",
3013 tolerance: "intersect",
3014 zIndex: 1000
3015 },
3016 _create: function() {
3017
3018 var o = this.options;
3019 this.containerCache = {};
3020 this.element.addClass("ui-sortable");
3021
3022 //Get the items
3023 this.refresh();
3024
3025 //Let's determine if the items are being displayed horizontally
3026 this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
3027
3028 //Let's determine the parent's offset
3029 this.offset = this.element.offset();
3030
3031 //Initialize mouse events for interaction
3032 this._mouseInit();
3033
3034 },
3035
3036 destroy: function() {
3037 this.element
3038 .removeClass("ui-sortable ui-sortable-disabled")
3039 .removeData("sortable")
3040 .unbind(".sortable");
3041 this._mouseDestroy();
3042
3043 for ( var i = this.items.length - 1; i >= 0; i-- )
3044 this.items[i].item.removeData("sortable-item");
3045
3046 return this;
3047 },
3048
3049 _setOption: function(key, value){
3050 if ( key === "disabled" ) {
3051 this.options[ key ] = value;
3052
3053 this.widget()
3054 [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
3055 } else {
3056 // Don't call widget base _setOption for disable as it adds ui-state-disabled class
3057 $.Widget.prototype._setOption.apply(this, arguments);
3058 }
3059 },
3060
3061 _mouseCapture: function(event, overrideHandle) {
3062
3063 if (this.reverting) {
3064 return false;
3065 }
3066
3067 if(this.options.disabled || this.options.type == 'static') return false;
3068
3069 //We have to refresh the items data once first
3070 this._refreshItems(event);
3071
3072 //Find out if the clicked node (or one of its parents) is a actual item in this.items
3073 var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
3074 if($.data(this, 'sortable-item') == self) {
3075 currentItem = $(this);
3076 return false;
3077 }
3078 });
3079 if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
3080
3081 if(!currentItem) return false;
3082 if(this.options.handle && !overrideHandle) {
3083 var validHandle = false;
3084
3085 $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
3086 if(!validHandle) return false;
3087 }
3088
3089 this.currentItem = currentItem;
3090 this._removeCurrentsFromItems();
3091 return true;
3092
3093 },
3094
3095 _mouseStart: function(event, overrideHandle, noActivation) {
3096
3097 var o = this.options, self = this;
3098 this.currentContainer = this;
3099
3100 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
3101 this.refreshPositions();
3102
3103 //Create and append the visible helper
3104 this.helper = this._createHelper(event);
3105
3106 //Cache the helper size
3107 this._cacheHelperProportions();
3108
3109 /*
3110 * - Position generation -
3111 * This block generates everything position related - it's the core of draggables.
3112 */
3113
3114 //Cache the margins of the original element
3115 this._cacheMargins();
3116
3117 //Get the next scrolling parent
3118 this.scrollParent = this.helper.scrollParent();
3119
3120 //The element's absolute position on the page minus margins
3121 this.offset = this.currentItem.offset();
3122 this.offset = {
3123 top: this.offset.top - this.margins.top,
3124 left: this.offset.left - this.margins.left
3125 };
3126
3127 // Only after we got the offset, we can change the helper's position to absolute
3128 // TODO: Still need to figure out a way to make relative sorting possible
3129 this.helper.css("position", "absolute");
3130 this.cssPosition = this.helper.css("position");
3131
3132 $.extend(this.offset, {
3133 click: { //Where the click happened, relative to the element
3134 left: event.pageX - this.offset.left,
3135 top: event.pageY - this.offset.top
3136 },
3137 parent: this._getParentOffset(),
3138 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
3139 });
3140
3141 //Generate the original position
3142 this.originalPosition = this._generatePosition(event);
3143 this.originalPageX = event.pageX;
3144 this.originalPageY = event.pageY;
3145
3146 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
3147 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
3148
3149 //Cache the former DOM position
3150 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
3151
3152 //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
3153 if(this.helper[0] != this.currentItem[0]) {
3154 this.currentItem.hide();
3155 }
3156
3157 //Create the placeholder
3158 this._createPlaceholder();
3159
3160 //Set a containment if given in the options
3161 if(o.containment)
3162 this._setContainment();
3163
3164 if(o.cursor) { // cursor option
3165 if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
3166 $('body').css("cursor", o.cursor);
3167 }
3168
3169 if(o.opacity) { // opacity option
3170 if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
3171 this.helper.css("opacity", o.opacity);
3172 }
3173
3174 if(o.zIndex) { // zIndex option
3175 if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
3176 this.helper.css("zIndex", o.zIndex);
3177 }
3178
3179 //Prepare scrolling
3180 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
3181 this.overflowOffset = this.scrollParent.offset();
3182
3183 //Call callbacks
3184 this._trigger("start", event, this._uiHash());
3185
3186 //Recache the helper size
3187 if(!this._preserveHelperProportions)
3188 this._cacheHelperProportions();
3189
3190
3191 //Post 'activate' events to possible containers
3192 if(!noActivation) {
3193 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
3194 }
3195
3196 //Prepare possible droppables
3197 if($.ui.ddmanager)
3198 $.ui.ddmanager.current = this;
3199
3200 if ($.ui.ddmanager && !o.dropBehaviour)
3201 $.ui.ddmanager.prepareOffsets(this, event);
3202
3203 this.dragging = true;
3204
3205 this.helper.addClass("ui-sortable-helper");
3206 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
3207 return true;
3208
3209 },
3210
3211 _mouseDrag: function(event) {
3212
3213 //Compute the helpers position
3214 this.position = this._generatePosition(event);
3215 this.positionAbs = this._convertPositionTo("absolute");
3216
3217 if (!this.lastPositionAbs) {
3218 this.lastPositionAbs = this.positionAbs;
3219 }
3220
3221 //Do scrolling
3222 if(this.options.scroll) {
3223 var o = this.options, scrolled = false;
3224 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
3225
3226 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
3227 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
3228 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
3229 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
3230
3231 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
3232 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
3233 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
3234 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
3235
3236 } else {
3237
3238 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
3239 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
3240 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
3241 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
3242
3243 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
3244 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
3245 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
3246 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
3247
3248 }
3249
3250 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
3251 $.ui.ddmanager.prepareOffsets(this, event);
3252 }
3253
3254 //Regenerate the absolute position used for position checks
3255 this.positionAbs = this._convertPositionTo("absolute");
3256
3257 //Set the helper position
3258 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
3259 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
3260
3261 //Rearrange
3262 for (var i = this.items.length - 1; i >= 0; i--) {
3263
3264 //Cache variables and intersection, continue if no intersection
3265 var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
3266 if (!intersection) continue;
3267
3268 if(itemElement != this.currentItem[0] //cannot intersect with itself
3269 && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
3270 && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
3271 && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
3272 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
3273 ) {
3274
3275 this.direction = intersection == 1 ? "down" : "up";
3276
3277 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
3278 this._rearrange(event, item);
3279 } else {
3280 break;
3281 }
3282
3283 this._trigger("change", event, this._uiHash());
3284 break;
3285 }
3286 }
3287
3288 //Post events to containers
3289 this._contactContainers(event);
3290
3291 //Interconnect with droppables
3292 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
3293
3294 //Call callbacks
3295 this._trigger('sort', event, this._uiHash());
3296
3297 this.lastPositionAbs = this.positionAbs;
3298 return false;
3299
3300 },
3301
3302 _mouseStop: function(event, noPropagation) {
3303
3304 if(!event) return;
3305
3306 //If we are using droppables, inform the manager about the drop
3307 if ($.ui.ddmanager && !this.options.dropBehaviour)
3308 $.ui.ddmanager.drop(this, event);
3309
3310 if(this.options.revert) {
3311 var self = this;
3312 var cur = self.placeholder.offset();
3313
3314 self.reverting = true;
3315
3316 $(this.helper).animate({
3317 left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
3318 top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
3319 }, parseInt(this.options.revert, 10) || 500, function() {
3320 self._clear(event);
3321 });
3322 } else {
3323 this._clear(event, noPropagation);
3324 }
3325
3326 return false;
3327
3328 },
3329
3330 cancel: function() {
3331
3332 var self = this;
3333
3334 if(this.dragging) {
3335
3336 this._mouseUp({ target: null });
3337
3338 if(this.options.helper == "original")
3339 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3340 else
3341 this.currentItem.show();
3342
3343 //Post deactivating events to containers
3344 for (var i = this.containers.length - 1; i >= 0; i--){
3345 this.containers[i]._trigger("deactivate", null, self._uiHash(this));
3346 if(this.containers[i].containerCache.over) {
3347 this.containers[i]._trigger("out", null, self._uiHash(this));
3348 this.containers[i].containerCache.over = 0;
3349 }
3350 }
3351
3352 }
3353
3354 if (this.placeholder) {
3355 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3356 if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3357 if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
3358
3359 $.extend(this, {
3360 helper: null,
3361 dragging: false,
3362 reverting: false,
3363 _noFinalSort: null
3364 });
3365
3366 if(this.domPosition.prev) {
3367 $(this.domPosition.prev).after(this.currentItem);
3368 } else {
3369 $(this.domPosition.parent).prepend(this.currentItem);
3370 }
3371 }
3372
3373 return this;
3374
3375 },
3376
3377 serialize: function(o) {
3378
3379 var items = this._getItemsAsjQuery(o && o.connected);
3380 var str = []; o = o || {};
3381
3382 $(items).each(function() {
3383 var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
3384 if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
3385 });
3386
3387 if(!str.length && o.key) {
3388 str.push(o.key + '=');
3389 }
3390
3391 return str.join('&');
3392
3393 },
3394
3395 toArray: function(o) {
3396
3397 var items = this._getItemsAsjQuery(o && o.connected);
3398 var ret = []; o = o || {};
3399
3400 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
3401 return ret;
3402
3403 },
3404
3405 /* Be careful with the following core functions */
3406 _intersectsWith: function(item) {
3407
3408 var x1 = this.positionAbs.left,
3409 x2 = x1 + this.helperProportions.width,
3410 y1 = this.positionAbs.top,
3411 y2 = y1 + this.helperProportions.height;
3412
3413 var l = item.left,
3414 r = l + item.width,
3415 t = item.top,
3416 b = t + item.height;
3417
3418 var dyClick = this.offset.click.top,
3419 dxClick = this.offset.click.left;
3420
3421 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
3422
3423 if( this.options.tolerance == "pointer"
3424 || this.options.forcePointerForContainers
3425 || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
3426 ) {
3427 return isOverElement;
3428 } else {
3429
3430 return (l < x1 + (this.helperProportions.width / 2) // Right Half
3431 && x2 - (this.helperProportions.width / 2) < r // Left Half
3432 && t < y1 + (this.helperProportions.height / 2) // Bottom Half
3433 && y2 - (this.helperProportions.height / 2) < b ); // Top Half
3434
3435 }
3436 },
3437
3438 _intersectsWithPointer: function(item) {
3439
3440 var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
3441 isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
3442 isOverElement = isOverElementHeight && isOverElementWidth,
3443 verticalDirection = this._getDragVerticalDirection(),
3444 horizontalDirection = this._getDragHorizontalDirection();
3445
3446 if (!isOverElement)
3447 return false;
3448
3449 return this.floating ?
3450 ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
3451 : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
3452
3453 },
3454
3455 _intersectsWithSides: function(item) {
3456
3457 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
3458 isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
3459 verticalDirection = this._getDragVerticalDirection(),
3460 horizontalDirection = this._getDragHorizontalDirection();
3461
3462 if (this.floating && horizontalDirection) {
3463 return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
3464 } else {
3465 return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
3466 }
3467
3468 },
3469
3470 _getDragVerticalDirection: function() {
3471 var delta = this.positionAbs.top - this.lastPositionAbs.top;
3472 return delta != 0 && (delta > 0 ? "down" : "up");
3473 },
3474
3475 _getDragHorizontalDirection: function() {
3476 var delta = this.positionAbs.left - this.lastPositionAbs.left;
3477 return delta != 0 && (delta > 0 ? "right" : "left");
3478 },
3479
3480 refresh: function(event) {
3481 this._refreshItems(event);
3482 this.refreshPositions();
3483 return this;
3484 },
3485
3486 _connectWith: function() {
3487 var options = this.options;
3488 return options.connectWith.constructor == String
3489 ? [options.connectWith]
3490 : options.connectWith;
3491 },
3492
3493 _getItemsAsjQuery: function(connected) {
3494
3495 var self = this;
3496 var items = [];
3497 var queries = [];
3498 var connectWith = this._connectWith();
3499
3500 if(connectWith && connected) {
3501 for (var i = connectWith.length - 1; i >= 0; i--){
3502 var cur = $(connectWith[i]);
3503 for (var j = cur.length - 1; j >= 0; j--){
3504 var inst = $.data(cur[j], 'sortable');
3505 if(inst && inst != this && !inst.options.disabled) {
3506 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]);
3507 }
3508 };
3509 };
3510 }
3511
3512 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]);
3513
3514 for (var i = queries.length - 1; i >= 0; i--){
3515 queries[i][0].each(function() {
3516 items.push(this);
3517 });
3518 };
3519
3520 return $(items);
3521
3522 },
3523
3524 _removeCurrentsFromItems: function() {
3525
3526 var list = this.currentItem.find(":data(sortable-item)");
3527
3528 for (var i=0; i < this.items.length; i++) {
3529
3530 for (var j=0; j < list.length; j++) {
3531 if(list[j] == this.items[i].item[0])
3532 this.items.splice(i,1);
3533 };
3534
3535 };
3536
3537 },
3538
3539 _refreshItems: function(event) {
3540
3541 this.items = [];
3542 this.containers = [this];
3543 var items = this.items;
3544 var self = this;
3545 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
3546 var connectWith = this._connectWith();
3547
3548 if(connectWith) {
3549 for (var i = connectWith.length - 1; i >= 0; i--){
3550 var cur = $(connectWith[i]);
3551 for (var j = cur.length - 1; j >= 0; j--){
3552 var inst = $.data(cur[j], 'sortable');
3553 if(inst && inst != this && !inst.options.disabled) {
3554 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
3555 this.containers.push(inst);
3556 }
3557 };
3558 };
3559 }
3560
3561 for (var i = queries.length - 1; i >= 0; i--) {
3562 var targetData = queries[i][1];
3563 var _queries = queries[i][0];
3564
3565 for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
3566 var item = $(_queries[j]);
3567
3568 item.data('sortable-item', targetData); // Data for target checking (mouse manager)
3569
3570 items.push({
3571 item: item,
3572 instance: targetData,
3573 width: 0, height: 0,
3574 left: 0, top: 0
3575 });
3576 };
3577 };
3578
3579 },
3580
3581 refreshPositions: function(fast) {
3582
3583 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
3584 if(this.offsetParent && this.helper) {
3585 this.offset.parent = this._getParentOffset();
3586 }
3587
3588 for (var i = this.items.length - 1; i >= 0; i--){
3589 var item = this.items[i];
3590
3591 //We ignore calculating positions of all connected containers when we're not over them
3592 if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
3593 continue;
3594
3595 var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
3596
3597 if (!fast) {
3598 item.width = t.outerWidth();
3599 item.height = t.outerHeight();
3600 }
3601
3602 var p = t.offset();
3603 item.left = p.left;
3604 item.top = p.top;
3605 };
3606
3607 if(this.options.custom && this.options.custom.refreshContainers) {
3608 this.options.custom.refreshContainers.call(this);
3609 } else {
3610 for (var i = this.containers.length - 1; i >= 0; i--){
3611 var p = this.containers[i].element.offset();
3612 this.containers[i].containerCache.left = p.left;
3613 this.containers[i].containerCache.top = p.top;
3614 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
3615 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
3616 };
3617 }
3618
3619 return this;
3620 },
3621
3622 _createPlaceholder: function(that) {
3623
3624 var self = that || this, o = self.options;
3625
3626 if(!o.placeholder || o.placeholder.constructor == String) {
3627 var className = o.placeholder;
3628 o.placeholder = {
3629 element: function() {
3630
3631 var el = $(document.createElement(self.currentItem[0].nodeName))
3632 .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
3633 .removeClass("ui-sortable-helper")[0];
3634
3635 if(!className)
3636 el.style.visibility = "hidden";
3637
3638 return el;
3639 },
3640 update: function(container, p) {
3641
3642 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
3643 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
3644 if(className && !o.forcePlaceholderSize) return;
3645
3646 //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
3647 if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
3648 if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
3649 }
3650 };
3651 }
3652
3653 //Create the placeholder
3654 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
3655
3656 //Append it after the actual current item
3657 self.currentItem.after(self.placeholder);
3658
3659 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
3660 o.placeholder.update(self, self.placeholder);
3661
3662 },
3663
3664 _contactContainers: function(event) {
3665
3666 // get innermost container that intersects with item
3667 var innermostContainer = null, innermostIndex = null;
3668
3669
3670 for (var i = this.containers.length - 1; i >= 0; i--){
3671
3672 // never consider a container that's located within the item itself
3673 if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
3674 continue;
3675
3676 if(this._intersectsWith(this.containers[i].containerCache)) {
3677
3678 // if we've already found a container and it's more "inner" than this, then continue
3679 if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
3680 continue;
3681
3682 innermostContainer = this.containers[i];
3683 innermostIndex = i;
3684
3685 } else {
3686 // container doesn't intersect. trigger "out" event if necessary
3687 if(this.containers[i].containerCache.over) {
3688 this.containers[i]._trigger("out", event, this._uiHash(this));
3689 this.containers[i].containerCache.over = 0;
3690 }
3691 }
3692
3693 }
3694
3695 // if no intersecting containers found, return
3696 if(!innermostContainer) return;
3697
3698 // move the item into the container if it's not there already
3699 if(this.containers.length === 1) {
3700 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3701 this.containers[innermostIndex].containerCache.over = 1;
3702 } else if(this.currentContainer != this.containers[innermostIndex]) {
3703
3704 //When entering a new container, we will find the item with the least distance and append our item near it
3705 var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
3706 for (var j = this.items.length - 1; j >= 0; j--) {
3707 if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
3708 var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top'];
3709 if(Math.abs(cur - base) < dist) {
3710 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
3711 }
3712 }
3713
3714 if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
3715 return;
3716
3717 this.currentContainer = this.containers[innermostIndex];
3718 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
3719 this._trigger("change", event, this._uiHash());
3720 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
3721
3722 //Update the placeholder
3723 this.options.placeholder.update(this.currentContainer, this.placeholder);
3724
3725 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3726 this.containers[innermostIndex].containerCache.over = 1;
3727 }
3728
3729
3730 },
3731
3732 _createHelper: function(event) {
3733
3734 var o = this.options;
3735 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
3736
3737 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
3738 $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
3739
3740 if(helper[0] == this.currentItem[0])
3741 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") };
3742
3743 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
3744 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
3745
3746 return helper;
3747
3748 },
3749
3750 _adjustOffsetFromHelper: function(obj) {
3751 if (typeof obj == 'string') {
3752 obj = obj.split(' ');
3753 }
3754 if ($.isArray(obj)) {
3755 obj = {left: +obj[0], top: +obj[1] || 0};
3756 }
3757 if ('left' in obj) {
3758 this.offset.click.left = obj.left + this.margins.left;
3759 }
3760 if ('right' in obj) {
3761 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
3762 }
3763 if ('top' in obj) {
3764 this.offset.click.top = obj.top + this.margins.top;
3765 }
3766 if ('bottom' in obj) {
3767 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
3768 }
3769 },
3770
3771 _getParentOffset: function() {
3772
3773
3774 //Get the offsetParent and cache its position
3775 this.offsetParent = this.helper.offsetParent();
3776 var po = this.offsetParent.offset();
3777
3778 // This is a special case where we need to modify a offset calculated on start, since the following happened:
3779 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
3780 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
3781 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
3782 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
3783 po.left += this.scrollParent.scrollLeft();
3784 po.top += this.scrollParent.scrollTop();
3785 }
3786
3787 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
3788 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
3789 po = { top: 0, left: 0 };
3790
3791 return {
3792 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
3793 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
3794 };
3795
3796 },
3797
3798 _getRelativeOffset: function() {
3799
3800 if(this.cssPosition == "relative") {
3801 var p = this.currentItem.position();
3802 return {
3803 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
3804 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
3805 };
3806 } else {
3807 return { top: 0, left: 0 };
3808 }
3809
3810 },
3811
3812 _cacheMargins: function() {
3813 this.margins = {
3814 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
3815 top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
3816 };
3817 },
3818
3819 _cacheHelperProportions: function() {
3820 this.helperProportions = {
3821 width: this.helper.outerWidth(),
3822 height: this.helper.outerHeight()
3823 };
3824 },
3825
3826 _setContainment: function() {
3827
3828 var o = this.options;
3829 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
3830 if(o.containment == 'document' || o.containment == 'window') this.containment = [
3831 0 - this.offset.relative.left - this.offset.parent.left,
3832 0 - this.offset.relative.top - this.offset.parent.top,
3833 $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
3834 ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
3835 ];
3836
3837 if(!(/^(document|window|parent)$/).test(o.containment)) {
3838 var ce = $(o.containment)[0];
3839 var co = $(o.containment).offset();
3840 var over = ($(ce).css("overflow") != 'hidden');
3841
3842 this.containment = [
3843 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
3844 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
3845 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,
3846 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
3847 ];
3848 }
3849
3850 },
3851
3852 _convertPositionTo: function(d, pos) {
3853
3854 if(!pos) pos = this.position;
3855 var mod = d == "absolute" ? 1 : -1;
3856 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
3857
3858 return {
3859 top: (
3860 pos.top // The absolute mouse position
3861 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
3862 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
3863 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
3864 ),
3865 left: (
3866 pos.left // The absolute mouse position
3867 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
3868 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
3869 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
3870 )
3871 };
3872
3873 },
3874
3875 _generatePosition: function(event) {
3876
3877 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
3878
3879 // This is another very weird special case that only happens for relative elements:
3880 // 1. If the css position is relative
3881 // 2. and the scroll parent is the document or similar to the offset parent
3882 // we have to refresh the relative offset during the scroll so there are no jumps
3883 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
3884 this.offset.relative = this._getRelativeOffset();
3885 }
3886
3887 var pageX = event.pageX;
3888 var pageY = event.pageY;
3889
3890 /*
3891 * - Position constraining -
3892 * Constrain the position to a mix of grid, containment.
3893 */
3894
3895 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
3896
3897 if(this.containment) {
3898 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
3899 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
3900 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
3901 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
3902 }
3903
3904 if(o.grid) {
3905 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
3906 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;
3907
3908 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
3909 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;
3910 }
3911
3912 }
3913
3914 return {
3915 top: (
3916 pageY // The absolute mouse position
3917 - this.offset.click.top // Click offset (relative to the element)
3918 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
3919 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
3920 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
3921 ),
3922 left: (
3923 pageX // The absolute mouse position
3924 - this.offset.click.left // Click offset (relative to the element)
3925 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
3926 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
3927 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
3928 )
3929 };
3930
3931 },
3932
3933 _rearrange: function(event, i, a, hardRefresh) {
3934
3935 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));
3936
3937 //Various things done here to improve the performance:
3938 // 1. we create a setTimeout, that calls refreshPositions
3939 // 2. on the instance, we have a counter variable, that get's higher after every append
3940 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
3941 // 4. this lets only the last addition to the timeout stack through
3942 this.counter = this.counter ? ++this.counter : 1;
3943 var self = this, counter = this.counter;
3944
3945 window.setTimeout(function() {
3946 if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
3947 },0);
3948
3949 },
3950
3951 _clear: function(event, noPropagation) {
3952
3953 this.reverting = false;
3954 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
3955 // everything else normalized again
3956 var delayedTriggers = [], self = this;
3957
3958 // We first have to update the dom position of the actual currentItem
3959 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
3960 if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem);
3961 this._noFinalSort = null;
3962
3963 if(this.helper[0] == this.currentItem[0]) {
3964 for(var i in this._storedCSS) {
3965 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
3966 }
3967 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3968 } else {
3969 this.currentItem.show();
3970 }
3971
3972 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
3973 if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
3974 if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
3975 if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
3976 for (var i = this.containers.length - 1; i >= 0; i--){
3977 if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
3978 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
3979 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
3980 }
3981 };
3982 };
3983
3984 //Post events to containers
3985 for (var i = this.containers.length - 1; i >= 0; i--){
3986 if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
3987 if(this.containers[i].containerCache.over) {
3988 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
3989 this.containers[i].containerCache.over = 0;
3990 }
3991 }
3992
3993 //Do what was originally in plugins
3994 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
3995 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
3996 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
3997
3998 this.dragging = false;
3999 if(this.cancelHelperRemoval) {
4000 if(!noPropagation) {
4001 this._trigger("beforeStop", event, this._uiHash());
4002 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
4003 this._trigger("stop", event, this._uiHash());
4004 }
4005 return false;
4006 }
4007
4008 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
4009
4010 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
4011 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
4012
4013 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
4014
4015 if(!noPropagation) {
4016 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
4017 this._trigger("stop", event, this._uiHash());
4018 }
4019
4020 this.fromOutside = false;
4021 return true;
4022
4023 },
4024
4025 _trigger: function() {
4026 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
4027 this.cancel();
4028 }
4029 },
4030
4031 _uiHash: function(inst) {
4032 var self = inst || this;
4033 return {
4034 helper: self.helper,
4035 placeholder: self.placeholder || $([]),
4036 position: self.position,
4037 originalPosition: self.originalPosition,
4038 offset: self.positionAbs,
4039 item: self.currentItem,
4040 sender: inst ? inst.element : null
4041 };
4042 }
4043
4044 });
4045
4046 $.extend($.ui.sortable, {
4047 version: "1.8.16"
4048 });
4049
4050 })(jQuery);
4051 /*
4052 * jQuery UI Effects 1.8.16
4053 *
4054 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4055 * Dual licensed under the MIT or GPL Version 2 licenses.
4056 * http://jquery.org/license
4057 *
4058 * http://docs.jquery.com/UI/Effects/
4059 */
4060 ;jQuery.effects || (function($, undefined) {
4061
4062 $.effects = {};
4063
4064
4065
4066 /******************************************************************************/
4067 /****************************** COLOR ANIMATIONS ******************************/
4068 /******************************************************************************/
4069
4070 // override the animation for color styles
4071 $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
4072 'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
4073 function(i, attr) {
4074 $.fx.step[attr] = function(fx) {
4075 if (!fx.colorInit) {
4076 fx.start = getColor(fx.elem, attr);
4077 fx.end = getRGB(fx.end);
4078 fx.colorInit = true;
4079 }
4080
4081 fx.elem.style[attr] = 'rgb(' +
4082 Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
4083 Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
4084 Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
4085 };
4086 });
4087
4088 // Color Conversion functions from highlightFade
4089 // By Blair Mitchelmore
4090 // http://jquery.offput.ca/highlightFade/
4091
4092 // Parse strings looking for color tuples [255,255,255]
4093 function getRGB(color) {
4094 var result;
4095
4096 // Check if we're already dealing with an array of colors
4097 if ( color && color.constructor == Array && color.length == 3 )
4098 return color;
4099
4100 // Look for rgb(num,num,num)
4101 if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
4102 return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
4103
4104 // Look for rgb(num%,num%,num%)
4105 if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
4106 return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
4107
4108 // Look for #a0b1c2
4109 if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
4110 return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
4111
4112 // Look for #fff
4113 if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
4114 return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
4115
4116 // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
4117 if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
4118 return colors['transparent'];
4119
4120 // Otherwise, we're most likely dealing with a named color
4121 return colors[$.trim(color).toLowerCase()];
4122 }
4123
4124 function getColor(elem, attr) {
4125 var color;
4126
4127 do {
4128 color = $.curCSS(elem, attr);
4129
4130 // Keep going until we find an element that has color, or we hit the body
4131 if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
4132 break;
4133
4134 attr = "backgroundColor";
4135 } while ( elem = elem.parentNode );
4136
4137 return getRGB(color);
4138 };
4139
4140 // Some named colors to work with
4141 // From Interface by Stefan Petre
4142 // http://interface.eyecon.ro/
4143
4144 var colors = {
4145 aqua:[0,255,255],
4146 azure:[240,255,255],
4147 beige:[245,245,220],
4148 black:[0,0,0],
4149 blue:[0,0,255],
4150 brown:[165,42,42],
4151 cyan:[0,255,255],
4152 darkblue:[0,0,139],
4153 darkcyan:[0,139,139],
4154 darkgrey:[169,169,169],
4155 darkgreen:[0,100,0],
4156 darkkhaki:[189,183,107],
4157 darkmagenta:[139,0,139],
4158 darkolivegreen:[85,107,47],
4159 darkorange:[255,140,0],
4160 darkorchid:[153,50,204],
4161 darkred:[139,0,0],
4162 darksalmon:[233,150,122],
4163 darkviolet:[148,0,211],
4164 fuchsia:[255,0,255],
4165 gold:[255,215,0],
4166 green:[0,128,0],
4167 indigo:[75,0,130],
4168 khaki:[240,230,140],
4169 lightblue:[173,216,230],
4170 lightcyan:[224,255,255],
4171 lightgreen:[144,238,144],
4172 lightgrey:[211,211,211],
4173 lightpink:[255,182,193],
4174 lightyellow:[255,255,224],
4175 lime:[0,255,0],
4176 magenta:[255,0,255],
4177 maroon:[128,0,0],
4178 navy:[0,0,128],
4179 olive:[128,128,0],
4180 orange:[255,165,0],
4181 pink:[255,192,203],
4182 purple:[128,0,128],
4183 violet:[128,0,128],
4184 red:[255,0,0],
4185 silver:[192,192,192],
4186 white:[255,255,255],
4187 yellow:[255,255,0],
4188 transparent: [255,255,255]
4189 };
4190
4191
4192
4193 /******************************************************************************/
4194 /****************************** CLASS ANIMATIONS ******************************/
4195 /******************************************************************************/
4196
4197 var classAnimationActions = ['add', 'remove', 'toggle'],
4198 shorthandStyles = {
4199 border: 1,
4200 borderBottom: 1,
4201 borderColor: 1,
4202 borderLeft: 1,
4203 borderRight: 1,
4204 borderTop: 1,
4205 borderWidth: 1,
4206 margin: 1,
4207 padding: 1
4208 };
4209
4210 function getElementStyles() {
4211 var style = document.defaultView
4212 ? document.defaultView.getComputedStyle(this, null)
4213 : this.currentStyle,
4214 newStyle = {},
4215 key,
4216 camelCase;
4217
4218 // webkit enumerates style porperties
4219 if (style && style.length && style[0] && style[style[0]]) {
4220 var len = style.length;
4221 while (len--) {
4222 key = style[len];
4223 if (typeof style[key] == 'string') {
4224 camelCase = key.replace(/\-(\w)/g, function(all, letter){
4225 return letter.toUpperCase();
4226 });
4227 newStyle[camelCase] = style[key];
4228 }
4229 }
4230 } else {
4231 for (key in style) {
4232 if (typeof style[key] === 'string') {
4233 newStyle[key] = style[key];
4234 }
4235 }
4236 }
4237
4238 return newStyle;
4239 }
4240
4241 function filterStyles(styles) {
4242 var name, value;
4243 for (name in styles) {
4244 value = styles[name];
4245 if (
4246 // ignore null and undefined values
4247 value == null ||
4248 // ignore functions (when does this occur?)
4249 $.isFunction(value) ||
4250 // shorthand styles that need to be expanded
4251 name in shorthandStyles ||
4252 // ignore scrollbars (break in IE)
4253 (/scrollbar/).test(name) ||
4254
4255 // only colors or values that can be converted to numbers
4256 (!(/color/i).test(name) && isNaN(parseFloat(value)))
4257 ) {
4258 delete styles[name];
4259 }
4260 }
4261
4262 return styles;
4263 }
4264
4265 function styleDifference(oldStyle, newStyle) {
4266 var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
4267 name;
4268
4269 for (name in newStyle) {
4270 if (oldStyle[name] != newStyle[name]) {
4271 diff[name] = newStyle[name];
4272 }
4273 }
4274
4275 return diff;
4276 }
4277
4278 $.effects.animateClass = function(value, duration, easing, callback) {
4279 if ($.isFunction(easing)) {
4280 callback = easing;
4281 easing = null;
4282 }
4283
4284 return this.queue(function() {
4285 var that = $(this),
4286 originalStyleAttr = that.attr('style') || ' ',
4287 originalStyle = filterStyles(getElementStyles.call(this)),
4288 newStyle,
4289 className = that.attr('class');
4290
4291 $.each(classAnimationActions, function(i, action) {
4292 if (value[action]) {
4293 that[action + 'Class'](value[action]);
4294 }
4295 });
4296 newStyle = filterStyles(getElementStyles.call(this));
4297 that.attr('class', className);
4298
4299 that.animate(styleDifference(originalStyle, newStyle), {
4300 queue: false,
4301 duration: duration,
4302 easing: easing,
4303 complete: function() {
4304 $.each(classAnimationActions, function(i, action) {
4305 if (value[action]) { that[action + 'Class'](value[action]); }
4306 });
4307 // work around bug in IE by clearing the cssText before setting it
4308 if (typeof that.attr('style') == 'object') {
4309 that.attr('style').cssText = '';
4310 that.attr('style').cssText = originalStyleAttr;
4311 } else {
4312 that.attr('style', originalStyleAttr);
4313 }
4314 if (callback) { callback.apply(this, arguments); }
4315 $.dequeue( this );
4316 }
4317 });
4318 });
4319 };
4320
4321 $.fn.extend({
4322 _addClass: $.fn.addClass,
4323 addClass: function(classNames, speed, easing, callback) {
4324 return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
4325 },
4326
4327 _removeClass: $.fn.removeClass,
4328 removeClass: function(classNames,speed,easing,callback) {
4329 return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
4330 },
4331
4332 _toggleClass: $.fn.toggleClass,
4333 toggleClass: function(classNames, force, speed, easing, callback) {
4334 if ( typeof force == "boolean" || force === undefined ) {
4335 if ( !speed ) {
4336 // without speed parameter;
4337 return this._toggleClass(classNames, force);
4338 } else {
4339 return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
4340 }
4341 } else {
4342 // without switch parameter;
4343 return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
4344 }
4345 },
4346
4347 switchClass: function(remove,add,speed,easing,callback) {
4348 return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
4349 }
4350 });
4351
4352
4353
4354 /******************************************************************************/
4355 /*********************************** EFFECTS **********************************/
4356 /******************************************************************************/
4357
4358 $.extend($.effects, {
4359 version: "1.8.16",
4360
4361 // Saves a set of properties in a data storage
4362 save: function(element, set) {
4363 for(var i=0; i < set.length; i++) {
4364 if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
4365 }
4366 },
4367
4368 // Restores a set of previously saved properties from a data storage
4369 restore: function(element, set) {
4370 for(var i=0; i < set.length; i++) {
4371 if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
4372 }
4373 },
4374
4375 setMode: function(el, mode) {
4376 if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
4377 return mode;
4378 },
4379
4380 getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
4381 // this should be a little more flexible in the future to handle a string & hash
4382 var y, x;
4383 switch (origin[0]) {
4384 case 'top': y = 0; break;
4385 case 'middle': y = 0.5; break;
4386 case 'bottom': y = 1; break;
4387 default: y = origin[0] / original.height;
4388 };
4389 switch (origin[1]) {
4390 case 'left': x = 0; break;
4391 case 'center': x = 0.5; break;
4392 case 'right': x = 1; break;
4393 default: x = origin[1] / original.width;
4394 };
4395 return {x: x, y: y};
4396 },
4397
4398 // Wraps the element around a wrapper that copies position properties
4399 createWrapper: function(element) {
4400
4401 // if the element is already wrapped, return it
4402 if (element.parent().is('.ui-effects-wrapper')) {
4403 return element.parent();
4404 }
4405
4406 // wrap the element
4407 var props = {
4408 width: element.outerWidth(true),
4409 height: element.outerHeight(true),
4410 'float': element.css('float')
4411 },
4412 wrapper = $('<div></div>')
4413 .addClass('ui-effects-wrapper')
4414 .css({
4415 fontSize: '100%',
4416 background: 'transparent',
4417 border: 'none',
4418 margin: 0,
4419 padding: 0
4420 }),
4421 active = document.activeElement;
4422
4423 element.wrap(wrapper);
4424
4425 // Fixes #7595 - Elements lose focus when wrapped.
4426 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
4427 $( active ).focus();
4428 }
4429
4430 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
4431
4432 // transfer positioning properties to the wrapper
4433 if (element.css('position') == 'static') {
4434 wrapper.css({ position: 'relative' });
4435 element.css({ position: 'relative' });
4436 } else {
4437 $.extend(props, {
4438 position: element.css('position'),
4439 zIndex: element.css('z-index')
4440 });
4441 $.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
4442 props[pos] = element.css(pos);
4443 if (isNaN(parseInt(props[pos], 10))) {
4444 props[pos] = 'auto';
4445 }
4446 });
4447 element.css({position: 'relative', top: 0, left: 0, right: 'auto', bottom: 'auto' });
4448 }
4449
4450 return wrapper.css(props).show();
4451 },
4452
4453 removeWrapper: function(element) {
4454 var parent,
4455 active = document.activeElement;
4456
4457 if (element.parent().is('.ui-effects-wrapper')) {
4458 parent = element.parent().replaceWith(element);
4459 // Fixes #7595 - Elements lose focus when wrapped.
4460 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
4461 $( active ).focus();
4462 }
4463 return parent;
4464 }
4465
4466 return element;
4467 },
4468
4469 setTransition: function(element, list, factor, value) {
4470 value = value || {};
4471 $.each(list, function(i, x){
4472 unit = element.cssUnit(x);
4473 if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
4474 });
4475 return value;
4476 }
4477 });
4478
4479
4480 function _normalizeArguments(effect, options, speed, callback) {
4481 // shift params for method overloading
4482 if (typeof effect == 'object') {
4483 callback = options;
4484 speed = null;
4485 options = effect;
4486 effect = options.effect;
4487 }
4488 if ($.isFunction(options)) {
4489 callback = options;
4490 speed = null;
4491 options = {};
4492 }
4493 if (typeof options == 'number' || $.fx.speeds[options]) {
4494 callback = speed;
4495 speed = options;
4496 options = {};
4497 }
4498 if ($.isFunction(speed)) {
4499 callback = speed;
4500 speed = null;
4501 }
4502
4503 options = options || {};
4504
4505 speed = speed || options.duration;
4506 speed = $.fx.off ? 0 : typeof speed == 'number'
4507 ? speed : speed in $.fx.speeds ? $.fx.speeds[speed] : $.fx.speeds._default;
4508
4509 callback = callback || options.complete;
4510
4511 return [effect, options, speed, callback];
4512 }
4513
4514 function standardSpeed( speed ) {
4515 // valid standard speeds
4516 if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
4517 return true;
4518 }
4519
4520 // invalid strings - treat as "normal" speed
4521 if ( typeof speed === "string" && !$.effects[ speed ] ) {
4522 return true;
4523 }
4524
4525 return false;
4526 }
4527
4528 $.fn.extend({
4529 effect: function(effect, options, speed, callback) {
4530 var args = _normalizeArguments.apply(this, arguments),
4531 // TODO: make effects take actual parameters instead of a hash
4532 args2 = {
4533 options: args[1],
4534 duration: args[2],
4535 callback: args[3]
4536 },
4537 mode = args2.options.mode,
4538 effectMethod = $.effects[effect];
4539
4540 if ( $.fx.off || !effectMethod ) {
4541 // delegate to the original method (e.g., .show()) if possible
4542 if ( mode ) {
4543 return this[ mode ]( args2.duration, args2.callback );
4544 } else {
4545 return this.each(function() {
4546 if ( args2.callback ) {
4547 args2.callback.call( this );
4548 }
4549 });
4550 }
4551 }
4552
4553 return effectMethod.call(this, args2);
4554 },
4555
4556 _show: $.fn.show,
4557 show: function(speed) {
4558 if ( standardSpeed( speed ) ) {
4559 return this._show.apply(this, arguments);
4560 } else {
4561 var args = _normalizeArguments.apply(this, arguments);
4562 args[1].mode = 'show';
4563 return this.effect.apply(this, args);
4564 }
4565 },
4566
4567 _hide: $.fn.hide,
4568 hide: function(speed) {
4569 if ( standardSpeed( speed ) ) {
4570 return this._hide.apply(this, arguments);
4571 } else {
4572 var args = _normalizeArguments.apply(this, arguments);
4573 args[1].mode = 'hide';
4574 return this.effect.apply(this, args);
4575 }
4576 },
4577
4578 // jQuery core overloads toggle and creates _toggle
4579 __toggle: $.fn.toggle,
4580 toggle: function(speed) {
4581 if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
4582 return this.__toggle.apply(this, arguments);
4583 } else {
4584 var args = _normalizeArguments.apply(this, arguments);
4585 args[1].mode = 'toggle';
4586 return this.effect.apply(this, args);
4587 }
4588 },
4589
4590 // helper functions
4591 cssUnit: function(key) {
4592 var style = this.css(key), val = [];
4593 $.each( ['em','px','%','pt'], function(i, unit){
4594 if(style.indexOf(unit) > 0)
4595 val = [parseFloat(style), unit];
4596 });
4597 return val;
4598 }
4599 });
4600
4601
4602
4603 /******************************************************************************/
4604 /*********************************** EASING ***********************************/
4605 /******************************************************************************/
4606
4607 /*
4608 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
4609 *
4610 * Uses the built in easing capabilities added In jQuery 1.1
4611 * to offer multiple easing options
4612 *
4613 * TERMS OF USE - jQuery Easing
4614 *
4615 * Open source under the BSD License.
4616 *
4617 * Copyright 2008 George McGinley Smith
4618 * All rights reserved.
4619 *
4620 * Redistribution and use in source and binary forms, with or without modification,
4621 * are permitted provided that the following conditions are met:
4622 *
4623 * Redistributions of source code must retain the above copyright notice, this list of
4624 * conditions and the following disclaimer.
4625 * Redistributions in binary form must reproduce the above copyright notice, this list
4626 * of conditions and the following disclaimer in the documentation and/or other materials
4627 * provided with the distribution.
4628 *
4629 * Neither the name of the author nor the names of contributors may be used to endorse
4630 * or promote products derived from this software without specific prior written permission.
4631 *
4632 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
4633 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
4634 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
4635 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4636 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
4637 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
4638 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4639 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
4640 * OF THE POSSIBILITY OF SUCH DAMAGE.
4641 *
4642 */
4643
4644 // t: current time, b: begInnIng value, c: change In value, d: duration
4645 $.easing.jswing = $.easing.swing;
4646
4647 $.extend($.easing,
4648 {
4649 def: 'easeOutQuad',
4650 swing: function (x, t, b, c, d) {
4651 //alert($.easing.default);
4652 return $.easing[$.easing.def](x, t, b, c, d);
4653 },
4654 easeInQuad: function (x, t, b, c, d) {
4655 return c*(t/=d)*t + b;
4656 },
4657 easeOutQuad: function (x, t, b, c, d) {
4658 return -c *(t/=d)*(t-2) + b;
4659 },
4660 easeInOutQuad: function (x, t, b, c, d) {
4661 if ((t/=d/2) < 1) return c/2*t*t + b;
4662 return -c/2 * ((--t)*(t-2) - 1) + b;
4663 },
4664 easeInCubic: function (x, t, b, c, d) {
4665 return c*(t/=d)*t*t + b;
4666 },
4667 easeOutCubic: function (x, t, b, c, d) {
4668 return c*((t=t/d-1)*t*t + 1) + b;
4669 },
4670 easeInOutCubic: function (x, t, b, c, d) {
4671 if ((t/=d/2) < 1) return c/2*t*t*t + b;
4672 return c/2*((t-=2)*t*t + 2) + b;
4673 },
4674 easeInQuart: function (x, t, b, c, d) {
4675 return c*(t/=d)*t*t*t + b;
4676 },
4677 easeOutQuart: function (x, t, b, c, d) {
4678 return -c * ((t=t/d-1)*t*t*t - 1) + b;
4679 },
4680 easeInOutQuart: function (x, t, b, c, d) {
4681 if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
4682 return -c/2 * ((t-=2)*t*t*t - 2) + b;
4683 },
4684 easeInQuint: function (x, t, b, c, d) {
4685 return c*(t/=d)*t*t*t*t + b;
4686 },
4687 easeOutQuint: function (x, t, b, c, d) {
4688 return c*((t=t/d-1)*t*t*t*t + 1) + b;
4689 },
4690 easeInOutQuint: function (x, t, b, c, d) {
4691 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
4692 return c/2*((t-=2)*t*t*t*t + 2) + b;
4693 },
4694 easeInSine: function (x, t, b, c, d) {
4695 return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
4696 },
4697 easeOutSine: function (x, t, b, c, d) {
4698 return c * Math.sin(t/d * (Math.PI/2)) + b;
4699 },
4700 easeInOutSine: function (x, t, b, c, d) {
4701 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
4702 },
4703 easeInExpo: function (x, t, b, c, d) {
4704 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
4705 },
4706 easeOutExpo: function (x, t, b, c, d) {
4707 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
4708 },
4709 easeInOutExpo: function (x, t, b, c, d) {
4710 if (t==0) return b;
4711 if (t==d) return b+c;
4712 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
4713 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
4714 },
4715 easeInCirc: function (x, t, b, c, d) {
4716 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
4717 },
4718 easeOutCirc: function (x, t, b, c, d) {
4719 return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
4720 },
4721 easeInOutCirc: function (x, t, b, c, d) {
4722 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
4723 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
4724 },
4725 easeInElastic: function (x, t, b, c, d) {
4726 var s=1.70158;var p=0;var a=c;
4727 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
4728 if (a < Math.abs(c)) { a=c; var s=p/4; }
4729 else var s = p/(2*Math.PI) * Math.asin (c/a);
4730 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
4731 },
4732 easeOutElastic: function (x, t, b, c, d) {
4733 var s=1.70158;var p=0;var a=c;
4734 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
4735 if (a < Math.abs(c)) { a=c; var s=p/4; }
4736 else var s = p/(2*Math.PI) * Math.asin (c/a);
4737 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
4738 },
4739 easeInOutElastic: function (x, t, b, c, d) {
4740 var s=1.70158;var p=0;var a=c;
4741 if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
4742 if (a < Math.abs(c)) { a=c; var s=p/4; }
4743 else var s = p/(2*Math.PI) * Math.asin (c/a);
4744 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
4745 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
4746 },
4747 easeInBack: function (x, t, b, c, d, s) {
4748 if (s == undefined) s = 1.70158;
4749 return c*(t/=d)*t*((s+1)*t - s) + b;
4750 },
4751 easeOutBack: function (x, t, b, c, d, s) {
4752 if (s == undefined) s = 1.70158;
4753 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
4754 },
4755 easeInOutBack: function (x, t, b, c, d, s) {
4756 if (s == undefined) s = 1.70158;
4757 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
4758 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
4759 },
4760 easeInBounce: function (x, t, b, c, d) {
4761 return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
4762 },
4763 easeOutBounce: function (x, t, b, c, d) {
4764 if ((t/=d) < (1/2.75)) {
4765 return c*(7.5625*t*t) + b;
4766 } else if (t < (2/2.75)) {
4767 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
4768 } else if (t < (2.5/2.75)) {
4769 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
4770 } else {
4771 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
4772 }
4773 },
4774 easeInOutBounce: function (x, t, b, c, d) {
4775 if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
4776 return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
4777 }
4778 });
4779
4780 /*
4781 *
4782 * TERMS OF USE - EASING EQUATIONS
4783 *
4784 * Open source under the BSD License.
4785 *
4786 * Copyright 2001 Robert Penner
4787 * All rights reserved.
4788 *
4789 * Redistribution and use in source and binary forms, with or without modification,
4790 * are permitted provided that the following conditions are met:
4791 *
4792 * Redistributions of source code must retain the above copyright notice, this list of
4793 * conditions and the following disclaimer.
4794 * Redistributions in binary form must reproduce the above copyright notice, this list
4795 * of conditions and the following disclaimer in the documentation and/or other materials
4796 * provided with the distribution.
4797 *
4798 * Neither the name of the author nor the names of contributors may be used to endorse
4799 * or promote products derived from this software without specific prior written permission.
4800 *
4801 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
4802 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
4803 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
4804 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4805 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
4806 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
4807 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4808 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
4809 * OF THE POSSIBILITY OF SUCH DAMAGE.
4810 *
4811 */
4812
4813 })(jQuery);
4814 /*
4815 * jQuery UI Effects Blind 1.8.16
4816 *
4817 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4818 * Dual licensed under the MIT or GPL Version 2 licenses.
4819 * http://jquery.org/license
4820 *
4821 * http://docs.jquery.com/UI/Effects/Blind
4822 *
4823 * Depends:
4824 * jquery.effects.core.js
4825 */
4826 (function( $, undefined ) {
4827
4828 $.effects.blind = function(o) {
4829
4830 return this.queue(function() {
4831
4832 // Create element
4833 var el = $(this), props = ['position','top','bottom','left','right'];
4834
4835 // Set options
4836 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
4837 var direction = o.options.direction || 'vertical'; // Default direction
4838
4839 // Adjust
4840 $.effects.save(el, props); el.show(); // Save & Show
4841 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
4842 var ref = (direction == 'vertical') ? 'height' : 'width';
4843 var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
4844 if(mode == 'show') wrapper.css(ref, 0); // Shift
4845
4846 // Animation
4847 var animation = {};
4848 animation[ref] = mode == 'show' ? distance : 0;
4849
4850 // Animate
4851 wrapper.animate(animation, o.duration, o.options.easing, function() {
4852 if(mode == 'hide') el.hide(); // Hide
4853 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
4854 if(o.callback) o.callback.apply(el[0], arguments); // Callback
4855 el.dequeue();
4856 });
4857
4858 });
4859
4860 };
4861
4862 })(jQuery);
4863 /*
4864 * jQuery UI Effects Bounce 1.8.16
4865 *
4866 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4867 * Dual licensed under the MIT or GPL Version 2 licenses.
4868 * http://jquery.org/license
4869 *
4870 * http://docs.jquery.com/UI/Effects/Bounce
4871 *
4872 * Depends:
4873 * jquery.effects.core.js
4874 */
4875 (function( $, undefined ) {
4876
4877 $.effects.bounce = function(o) {
4878
4879 return this.queue(function() {
4880
4881 // Create element
4882 var el = $(this), props = ['position','top','bottom','left','right'];
4883
4884 // Set options
4885 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
4886 var direction = o.options.direction || 'up'; // Default direction
4887 var distance = o.options.distance || 20; // Default distance
4888 var times = o.options.times || 5; // Default # of times
4889 var speed = o.duration || 250; // Default speed per bounce
4890 if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
4891
4892 // Adjust
4893 $.effects.save(el, props); el.show(); // Save & Show
4894 $.effects.createWrapper(el); // Create Wrapper
4895 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
4896 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
4897 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
4898 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
4899 if (mode == 'hide') distance = distance / (times * 2);
4900 if (mode != 'hide') times--;
4901
4902 // Animate
4903 if (mode == 'show') { // Show Bounce
4904 var animation = {opacity: 1};
4905 animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
4906 el.animate(animation, speed / 2, o.options.easing);
4907 distance = distance / 2;
4908 times--;
4909 };
4910 for (var i = 0; i < times; i++) { // Bounces
4911 var animation1 = {}, animation2 = {};
4912 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
4913 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
4914 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
4915 distance = (mode == 'hide') ? distance * 2 : distance / 2;
4916 };
4917 if (mode == 'hide') { // Last Bounce
4918 var animation = {opacity: 0};
4919 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
4920 el.animate(animation, speed / 2, o.options.easing, function(){
4921 el.hide(); // Hide
4922 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
4923 if(o.callback) o.callback.apply(this, arguments); // Callback
4924 });
4925 } else {
4926 var animation1 = {}, animation2 = {};
4927 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
4928 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
4929 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
4930 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
4931 if(o.callback) o.callback.apply(this, arguments); // Callback
4932 });
4933 };
4934 el.queue('fx', function() { el.dequeue(); });
4935 el.dequeue();
4936 });
4937
4938 };
4939
4940 })(jQuery);
4941 /*
4942 * jQuery UI Effects Clip 1.8.16
4943 *
4944 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4945 * Dual licensed under the MIT or GPL Version 2 licenses.
4946 * http://jquery.org/license
4947 *
4948 * http://docs.jquery.com/UI/Effects/Clip
4949 *
4950 * Depends:
4951 * jquery.effects.core.js
4952 */
4953 (function( $, undefined ) {
4954
4955 $.effects.clip = function(o) {
4956
4957 return this.queue(function() {
4958
4959 // Create element
4960 var el = $(this), props = ['position','top','bottom','left','right','height','width'];
4961
4962 // Set options
4963 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
4964 var direction = o.options.direction || 'vertical'; // Default direction
4965
4966 // Adjust
4967 $.effects.save(el, props); el.show(); // Save & Show
4968 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
4969 var animate = el[0].tagName == 'IMG' ? wrapper : el;
4970 var ref = {
4971 size: (direction == 'vertical') ? 'height' : 'width',
4972 position: (direction == 'vertical') ? 'top' : 'left'
4973 };
4974 var distance = (direction == 'vertical') ? animate.height() : animate.width();
4975 if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
4976
4977 // Animation
4978 var animation = {};
4979 animation[ref.size] = mode == 'show' ? distance : 0;
4980 animation[ref.position] = mode == 'show' ? 0 : distance / 2;
4981
4982 // Animate
4983 animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
4984 if(mode == 'hide') el.hide(); // Hide
4985 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
4986 if(o.callback) o.callback.apply(el[0], arguments); // Callback
4987 el.dequeue();
4988 }});
4989
4990 });
4991
4992 };
4993
4994 })(jQuery);
4995 /*
4996 * jQuery UI Effects Drop 1.8.16
4997 *
4998 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4999 * Dual licensed under the MIT or GPL Version 2 licenses.
5000 * http://jquery.org/license
5001 *
5002 * http://docs.jquery.com/UI/Effects/Drop
5003 *
5004 * Depends:
5005 * jquery.effects.core.js
5006 */
5007 (function( $, undefined ) {
5008
5009 $.effects.drop = function(o) {
5010
5011 return this.queue(function() {
5012
5013 // Create element
5014 var el = $(this), props = ['position','top','bottom','left','right','opacity'];
5015
5016 // Set options
5017 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
5018 var direction = o.options.direction || 'left'; // Default Direction
5019
5020 // Adjust
5021 $.effects.save(el, props); el.show(); // Save & Show
5022 $.effects.createWrapper(el); // Create Wrapper
5023 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
5024 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
5025 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
5026 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
5027
5028 // Animation
5029 var animation = {opacity: mode == 'show' ? 1 : 0};
5030 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
5031
5032 // Animate
5033 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
5034 if(mode == 'hide') el.hide(); // Hide
5035 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
5036 if(o.callback) o.callback.apply(this, arguments); // Callback
5037 el.dequeue();
5038 }});
5039
5040 });
5041
5042 };
5043
5044 })(jQuery);
5045 /*
5046 * jQuery UI Effects Explode 1.8.16
5047 *
5048 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5049 * Dual licensed under the MIT or GPL Version 2 licenses.
5050 * http://jquery.org/license
5051 *
5052 * http://docs.jquery.com/UI/Effects/Explode
5053 *
5054 * Depends:
5055 * jquery.effects.core.js
5056 */
5057 (function( $, undefined ) {
5058
5059 $.effects.explode = function(o) {
5060
5061 return this.queue(function() {
5062
5063 var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
5064 var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
5065
5066 o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
5067 var el = $(this).show().css('visibility', 'hidden');
5068 var offset = el.offset();
5069
5070 //Substract the margins - not fixing the problem yet.
5071 offset.top -= parseInt(el.css("marginTop"),10) || 0;
5072 offset.left -= parseInt(el.css("marginLeft"),10) || 0;
5073
5074 var width = el.outerWidth(true);
5075 var height = el.outerHeight(true);
5076
5077 for(var i=0;i<rows;i++) { // =
5078 for(var j=0;j<cells;j++) { // ||
5079 el
5080 .clone()
5081 .appendTo('body')
5082 .wrap('<div></div>')
5083 .css({
5084 position: 'absolute',
5085 visibility: 'visible',
5086 left: -j*(width/cells),
5087 top: -i*(height/rows)
5088 })
5089 .parent()
5090 .addClass('ui-effects-explode')
5091 .css({
5092 position: 'absolute',
5093 overflow: 'hidden',
5094 width: width/cells,
5095 height: height/rows,
5096 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
5097 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
5098 opacity: o.options.mode == 'show' ? 0 : 1
5099 }).animate({
5100 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
5101 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
5102 opacity: o.options.mode == 'show' ? 1 : 0
5103 }, o.duration || 500);
5104 }
5105 }
5106
5107 // Set a timeout, to call the callback approx. when the other animations have finished
5108 setTimeout(function() {
5109
5110 o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
5111 if(o.callback) o.callback.apply(el[0]); // Callback
5112 el.dequeue();
5113
5114 $('div.ui-effects-explode').remove();
5115
5116 }, o.duration || 500);
5117
5118
5119 });
5120
5121 };
5122
5123 })(jQuery);
5124 /*
5125 * jQuery UI Effects Fade 1.8.16
5126 *
5127 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5128 * Dual licensed under the MIT or GPL Version 2 licenses.
5129 * http://jquery.org/license
5130 *
5131 * http://docs.jquery.com/UI/Effects/Fade
5132 *
5133 * Depends:
5134 * jquery.effects.core.js
5135 */
5136 (function( $, undefined ) {
5137
5138 $.effects.fade = function(o) {
5139 return this.queue(function() {
5140 var elem = $(this),
5141 mode = $.effects.setMode(elem, o.options.mode || 'hide');
5142
5143 elem.animate({ opacity: mode }, {
5144 queue: false,
5145 duration: o.duration,
5146 easing: o.options.easing,
5147 complete: function() {
5148 (o.callback && o.callback.apply(this, arguments));
5149 elem.dequeue();
5150 }
5151 });
5152 });
5153 };
5154
5155 })(jQuery);
5156 /*
5157 * jQuery UI Effects Fold 1.8.16
5158 *
5159 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5160 * Dual licensed under the MIT or GPL Version 2 licenses.
5161 * http://jquery.org/license
5162 *
5163 * http://docs.jquery.com/UI/Effects/Fold
5164 *
5165 * Depends:
5166 * jquery.effects.core.js
5167 */
5168 (function( $, undefined ) {
5169
5170 $.effects.fold = function(o) {
5171
5172 return this.queue(function() {
5173
5174 // Create element
5175 var el = $(this), props = ['position','top','bottom','left','right'];
5176
5177 // Set options
5178 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
5179 var size = o.options.size || 15; // Default fold size
5180 var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
5181 var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
5182
5183 // Adjust
5184 $.effects.save(el, props); el.show(); // Save & Show
5185 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
5186 var widthFirst = ((mode == 'show') != horizFirst);
5187 var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
5188 var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
5189 var percent = /([0-9]+)%/.exec(size);
5190 if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
5191 if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
5192
5193 // Animation
5194 var animation1 = {}, animation2 = {};
5195 animation1[ref[0]] = mode == 'show' ? distance[0] : size;
5196 animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
5197
5198 // Animate
5199 wrapper.animate(animation1, duration, o.options.easing)
5200 .animate(animation2, duration, o.options.easing, function() {
5201 if(mode == 'hide') el.hide(); // Hide
5202 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
5203 if(o.callback) o.callback.apply(el[0], arguments); // Callback
5204 el.dequeue();
5205 });
5206
5207 });
5208
5209 };
5210
5211 })(jQuery);
5212 /*
5213 * jQuery UI Effects Highlight 1.8.16
5214 *
5215 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5216 * Dual licensed under the MIT or GPL Version 2 licenses.
5217 * http://jquery.org/license
5218 *
5219 * http://docs.jquery.com/UI/Effects/Highlight
5220 *
5221 * Depends:
5222 * jquery.effects.core.js
5223 */
5224 (function( $, undefined ) {
5225
5226 $.effects.highlight = function(o) {
5227 return this.queue(function() {
5228 var elem = $(this),
5229 props = ['backgroundImage', 'backgroundColor', 'opacity'],
5230 mode = $.effects.setMode(elem, o.options.mode || 'show'),
5231 animation = {
5232 backgroundColor: elem.css('backgroundColor')
5233 };
5234
5235 if (mode == 'hide') {
5236 animation.opacity = 0;
5237 }
5238
5239 $.effects.save(elem, props);
5240 elem
5241 .show()
5242 .css({
5243 backgroundImage: 'none',
5244 backgroundColor: o.options.color || '#ffff99'
5245 })
5246 .animate(animation, {
5247 queue: false,
5248 duration: o.duration,
5249 easing: o.options.easing,
5250 complete: function() {
5251 (mode == 'hide' && elem.hide());
5252 $.effects.restore(elem, props);
5253 (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
5254 (o.callback && o.callback.apply(this, arguments));
5255 elem.dequeue();
5256 }
5257 });
5258 });
5259 };
5260
5261 })(jQuery);
5262 /*
5263 * jQuery UI Effects Pulsate 1.8.16
5264 *
5265 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5266 * Dual licensed under the MIT or GPL Version 2 licenses.
5267 * http://jquery.org/license
5268 *
5269 * http://docs.jquery.com/UI/Effects/Pulsate
5270 *
5271 * Depends:
5272 * jquery.effects.core.js
5273 */
5274 (function( $, undefined ) {
5275
5276 $.effects.pulsate = function(o) {
5277 return this.queue(function() {
5278 var elem = $(this),
5279 mode = $.effects.setMode(elem, o.options.mode || 'show');
5280 times = ((o.options.times || 5) * 2) - 1;
5281 duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
5282 isVisible = elem.is(':visible'),
5283 animateTo = 0;
5284
5285 if (!isVisible) {
5286 elem.css('opacity', 0).show();
5287 animateTo = 1;
5288 }
5289
5290 if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
5291 times--;
5292 }
5293
5294 for (var i = 0; i < times; i++) {
5295 elem.animate({ opacity: animateTo }, duration, o.options.easing);
5296 animateTo = (animateTo + 1) % 2;
5297 }
5298
5299 elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
5300 if (animateTo == 0) {
5301 elem.hide();
5302 }
5303 (o.callback && o.callback.apply(this, arguments));
5304 });
5305
5306 elem
5307 .queue('fx', function() { elem.dequeue(); })
5308 .dequeue();
5309 });
5310 };
5311
5312 })(jQuery);
5313 /*
5314 * jQuery UI Effects Scale 1.8.16
5315 *
5316 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5317 * Dual licensed under the MIT or GPL Version 2 licenses.
5318 * http://jquery.org/license
5319 *
5320 * http://docs.jquery.com/UI/Effects/Scale
5321 *
5322 * Depends:
5323 * jquery.effects.core.js
5324 */
5325 (function( $, undefined ) {
5326
5327 $.effects.puff = function(o) {
5328 return this.queue(function() {
5329 var elem = $(this),
5330 mode = $.effects.setMode(elem, o.options.mode || 'hide'),
5331 percent = parseInt(o.options.percent, 10) || 150,
5332 factor = percent / 100,
5333 original = { height: elem.height(), width: elem.width() };
5334
5335 $.extend(o.options, {
5336 fade: true,
5337 mode: mode,
5338 percent: mode == 'hide' ? percent : 100,
5339 from: mode == 'hide'
5340 ? original
5341 : {
5342 height: original.height * factor,
5343 width: original.width * factor
5344 }
5345 });
5346
5347 elem.effect('scale', o.options, o.duration, o.callback);
5348 elem.dequeue();
5349 });
5350 };
5351
5352 $.effects.scale = function(o) {
5353
5354 return this.queue(function() {
5355
5356 // Create element
5357 var el = $(this);
5358
5359 // Set options
5360 var options = $.extend(true, {}, o.options);
5361 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
5362 var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
5363 var direction = o.options.direction || 'both'; // Set default axis
5364 var origin = o.options.origin; // The origin of the scaling
5365 if (mode != 'effect') { // Set default origin and restore for show/hide
5366 options.origin = origin || ['middle','center'];
5367 options.restore = true;
5368 }
5369 var original = {height: el.height(), width: el.width()}; // Save original
5370 el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
5371
5372 // Adjust
5373 var factor = { // Set scaling factor
5374 y: direction != 'horizontal' ? (percent / 100) : 1,
5375 x: direction != 'vertical' ? (percent / 100) : 1
5376 };
5377 el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
5378
5379 if (o.options.fade) { // Fade option to support puff
5380 if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
5381 if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
5382 };
5383
5384 // Animation
5385 options.from = el.from; options.to = el.to; options.mode = mode;
5386
5387 // Animate
5388 el.effect('size', options, o.duration, o.callback);
5389 el.dequeue();
5390 });
5391
5392 };
5393
5394 $.effects.size = function(o) {
5395
5396 return this.queue(function() {
5397
5398 // Create element
5399 var el = $(this), props = ['position','top','bottom','left','right','width','height','overflow','opacity'];
5400 var props1 = ['position','top','bottom','left','right','overflow','opacity']; // Always restore
5401 var props2 = ['width','height','overflow']; // Copy for children
5402 var cProps = ['fontSize'];
5403 var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
5404 var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
5405
5406 // Set options
5407 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
5408 var restore = o.options.restore || false; // Default restore
5409 var scale = o.options.scale || 'both'; // Default scale mode
5410 var origin = o.options.origin; // The origin of the sizing
5411 var original = {height: el.height(), width: el.width()}; // Save original
5412 el.from = o.options.from || original; // Default from state
5413 el.to = o.options.to || original; // Default to state
5414 // Adjust
5415 if (origin) { // Calculate baseline shifts
5416 var baseline = $.effects.getBaseline(origin, original);
5417 el.from.top = (original.height - el.from.height) * baseline.y;
5418 el.from.left = (original.width - el.from.width) * baseline.x;
5419 el.to.top = (original.height - el.to.height) * baseline.y;
5420 el.to.left = (original.width - el.to.width) * baseline.x;
5421 };
5422 var factor = { // Set scaling factor
5423 from: {y: el.from.height / original.height, x: el.from.width / original.width},
5424 to: {y: el.to.height / original.height, x: el.to.width / original.width}
5425 };
5426 if (scale == 'box' || scale == 'both') { // Scale the css box
5427 if (factor.from.y != factor.to.y) { // Vertical props scaling
5428 props = props.concat(vProps);
5429 el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
5430 el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
5431 };
5432 if (factor.from.x != factor.to.x) { // Horizontal props scaling
5433 props = props.concat(hProps);
5434 el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
5435 el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
5436 };
5437 };
5438 if (scale == 'content' || scale == 'both') { // Scale the content
5439 if (factor.from.y != factor.to.y) { // Vertical props scaling
5440 props = props.concat(cProps);
5441 el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
5442 el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
5443 };
5444 };
5445 $.effects.save(el, restore ? props : props1); el.show(); // Save & Show
5446 $.effects.createWrapper(el); // Create Wrapper
5447 el.css('overflow','hidden').css(el.from); // Shift
5448
5449 // Animate
5450 if (scale == 'content' || scale == 'both') { // Scale the children
5451 vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
5452 hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
5453 props2 = props.concat(vProps).concat(hProps); // Concat
5454 el.find("*[width]").each(function(){
5455 child = $(this);
5456 if (restore) $.effects.save(child, props2);
5457 var c_original = {height: child.height(), width: child.width()}; // Save original
5458 child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
5459 child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
5460 if (factor.from.y != factor.to.y) { // Vertical props scaling
5461 child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
5462 child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
5463 };
5464 if (factor.from.x != factor.to.x) { // Horizontal props scaling
5465 child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
5466 child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
5467 };
5468 child.css(child.from); // Shift children
5469 child.animate(child.to, o.duration, o.options.easing, function(){
5470 if (restore) $.effects.restore(child, props2); // Restore children
5471 }); // Animate children
5472 });
5473 };
5474
5475 // Animate
5476 el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
5477 if (el.to.opacity === 0) {
5478 el.css('opacity', el.from.opacity);
5479 }
5480 if(mode == 'hide') el.hide(); // Hide
5481 $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
5482 if(o.callback) o.callback.apply(this, arguments); // Callback
5483 el.dequeue();
5484 }});
5485
5486 });
5487
5488 };
5489
5490 })(jQuery);
5491 /*
5492 * jQuery UI Effects Shake 1.8.16
5493 *
5494 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5495 * Dual licensed under the MIT or GPL Version 2 licenses.
5496 * http://jquery.org/license
5497 *
5498 * http://docs.jquery.com/UI/Effects/Shake
5499 *
5500 * Depends:
5501 * jquery.effects.core.js
5502 */
5503 (function( $, undefined ) {
5504
5505 $.effects.shake = function(o) {
5506
5507 return this.queue(function() {
5508
5509 // Create element
5510 var el = $(this), props = ['position','top','bottom','left','right'];
5511
5512 // Set options
5513 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
5514 var direction = o.options.direction || 'left'; // Default direction
5515 var distance = o.options.distance || 20; // Default distance
5516 var times = o.options.times || 3; // Default # of times
5517 var speed = o.duration || o.options.duration || 140; // Default speed per shake
5518
5519 // Adjust
5520 $.effects.save(el, props); el.show(); // Save & Show
5521 $.effects.createWrapper(el); // Create Wrapper
5522 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
5523 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
5524
5525 // Animation
5526 var animation = {}, animation1 = {}, animation2 = {};
5527 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
5528 animation1[ref] = (motion == 'pos' ? '+=' : '-=') + distance * 2;
5529 animation2[ref] = (motion == 'pos' ? '-=' : '+=') + distance * 2;
5530
5531 // Animate
5532 el.animate(animation, speed, o.options.easing);
5533 for (var i = 1; i < times; i++) { // Shakes
5534 el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
5535 };
5536 el.animate(animation1, speed, o.options.easing).
5537 animate(animation, speed / 2, o.options.easing, function(){ // Last shake
5538 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
5539 if(o.callback) o.callback.apply(this, arguments); // Callback
5540 });
5541 el.queue('fx', function() { el.dequeue(); });
5542 el.dequeue();
5543 });
5544
5545 };
5546
5547 })(jQuery);
5548 /*
5549 * jQuery UI Effects Slide 1.8.16
5550 *
5551 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5552 * Dual licensed under the MIT or GPL Version 2 licenses.
5553 * http://jquery.org/license
5554 *
5555 * http://docs.jquery.com/UI/Effects/Slide
5556 *
5557 * Depends:
5558 * jquery.effects.core.js
5559 */
5560 (function( $, undefined ) {
5561
5562 $.effects.slide = function(o) {
5563
5564 return this.queue(function() {
5565
5566 // Create element
5567 var el = $(this), props = ['position','top','bottom','left','right'];
5568
5569 // Set options
5570 var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
5571 var direction = o.options.direction || 'left'; // Default Direction
5572
5573 // Adjust
5574 $.effects.save(el, props); el.show(); // Save & Show
5575 $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
5576 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
5577 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
5578 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
5579 if (mode == 'show') el.css(ref, motion == 'pos' ? (isNaN(distance) ? "-" + distance : -distance) : distance); // Shift
5580
5581 // Animation
5582 var animation = {};
5583 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
5584
5585 // Animate
5586 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
5587 if(mode == 'hide') el.hide(); // Hide
5588 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
5589 if(o.callback) o.callback.apply(this, arguments); // Callback
5590 el.dequeue();
5591 }});
5592
5593 });
5594
5595 };
5596
5597 })(jQuery);
5598 /*
5599 * jQuery UI Effects Transfer 1.8.16
5600 *
5601 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5602 * Dual licensed under the MIT or GPL Version 2 licenses.
5603 * http://jquery.org/license
5604 *
5605 * http://docs.jquery.com/UI/Effects/Transfer
5606 *
5607 * Depends:
5608 * jquery.effects.core.js
5609 */
5610 (function( $, undefined ) {
5611
5612 $.effects.transfer = function(o) {
5613 return this.queue(function() {
5614 var elem = $(this),
5615 target = $(o.options.to),
5616 endPosition = target.offset(),
5617 animation = {
5618 top: endPosition.top,
5619 left: endPosition.left,
5620 height: target.innerHeight(),
5621 width: target.innerWidth()
5622 },
5623 startPosition = elem.offset(),
5624 transfer = $('<div class="ui-effects-transfer"></div>')
5625 .appendTo(document.body)
5626 .addClass(o.options.className)
5627 .css({
5628 top: startPosition.top,
5629 left: startPosition.left,
5630 height: elem.innerHeight(),
5631 width: elem.innerWidth(),
5632 position: 'absolute'
5633 })
5634 .animate(animation, o.duration, o.options.easing, function() {
5635 transfer.remove();
5636 (o.callback && o.callback.apply(elem[0], arguments));
5637 elem.dequeue();
5638 });
5639 });
5640 };
5641
5642 })(jQuery);
5643 /*
5644 * jQuery UI Accordion 1.8.16
5645 *
5646 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5647 * Dual licensed under the MIT or GPL Version 2 licenses.
5648 * http://jquery.org/license
5649 *
5650 * http://docs.jquery.com/UI/Accordion
5651 *
5652 * Depends:
5653 * jquery.ui.core.js
5654 * jquery.ui.widget.js
5655 */
5656 (function( $, undefined ) {
5657
5658 $.widget( "ui.accordion", {
5659 options: {
5660 active: 0,
5661 animated: "slide",
5662 autoHeight: true,
5663 clearStyle: false,
5664 collapsible: false,
5665 event: "click",
5666 fillSpace: false,
5667 header: "> li > :first-child,> :not(li):even",
5668 icons: {
5669 header: "ui-icon-triangle-1-e",
5670 headerSelected: "ui-icon-triangle-1-s"
5671 },
5672 navigation: false,
5673 navigationFilter: function() {
5674 return this.href.toLowerCase() === location.href.toLowerCase();
5675 }
5676 },
5677
5678 _create: function() {
5679 var self = this,
5680 options = self.options;
5681
5682 self.running = 0;
5683
5684 self.element
5685 .addClass( "ui-accordion ui-widget ui-helper-reset" )
5686 // in lack of child-selectors in CSS
5687 // we need to mark top-LIs in a UL-accordion for some IE-fix
5688 .children( "li" )
5689 .addClass( "ui-accordion-li-fix" );
5690
5691 self.headers = self.element.find( options.header )
5692 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
5693 .bind( "mouseenter.accordion", function() {
5694 if ( options.disabled ) {
5695 return;
5696 }
5697 $( this ).addClass( "ui-state-hover" );
5698 })
5699 .bind( "mouseleave.accordion", function() {
5700 if ( options.disabled ) {
5701 return;
5702 }
5703 $( this ).removeClass( "ui-state-hover" );
5704 })
5705 .bind( "focus.accordion", function() {
5706 if ( options.disabled ) {
5707 return;
5708 }
5709 $( this ).addClass( "ui-state-focus" );
5710 })
5711 .bind( "blur.accordion", function() {
5712 if ( options.disabled ) {
5713 return;
5714 }
5715 $( this ).removeClass( "ui-state-focus" );
5716 });
5717
5718 self.headers.next()
5719 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
5720
5721 if ( options.navigation ) {
5722 var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
5723 if ( current.length ) {
5724 var header = current.closest( ".ui-accordion-header" );
5725 if ( header.length ) {
5726 // anchor within header
5727 self.active = header;
5728 } else {
5729 // anchor within content
5730 self.active = current.closest( ".ui-accordion-content" ).prev();
5731 }
5732 }
5733 }
5734
5735 self.active = self._findActive( self.active || options.active )
5736 .addClass( "ui-state-default ui-state-active" )
5737 .toggleClass( "ui-corner-all" )
5738 .toggleClass( "ui-corner-top" );
5739 self.active.next().addClass( "ui-accordion-content-active" );
5740
5741 self._createIcons();
5742 self.resize();
5743
5744 // ARIA
5745 self.element.attr( "role", "tablist" );
5746
5747 self.headers
5748 .attr( "role", "tab" )
5749 .bind( "keydown.accordion", function( event ) {
5750 return self._keydown( event );
5751 })
5752 .next()
5753 .attr( "role", "tabpanel" );
5754
5755 self.headers
5756 .not( self.active || "" )
5757 .attr({
5758 "aria-expanded": "false",
5759 "aria-selected": "false",
5760 tabIndex: -1
5761 })
5762 .next()
5763 .hide();
5764
5765 // make sure at least one header is in the tab order
5766 if ( !self.active.length ) {
5767 self.headers.eq( 0 ).attr( "tabIndex", 0 );
5768 } else {
5769 self.active
5770 .attr({
5771 "aria-expanded": "true",
5772 "aria-selected": "true",
5773 tabIndex: 0
5774 });
5775 }
5776
5777 // only need links in tab order for Safari
5778 if ( !$.browser.safari ) {
5779 self.headers.find( "a" ).attr( "tabIndex", -1 );
5780 }
5781
5782 if ( options.event ) {
5783 self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
5784 self._clickHandler.call( self, event, this );
5785 event.preventDefault();
5786 });
5787 }
5788 },
5789
5790 _createIcons: function() {
5791 var options = this.options;
5792 if ( options.icons ) {
5793 $( "<span></span>" )
5794 .addClass( "ui-icon " + options.icons.header )
5795 .prependTo( this.headers );
5796 this.active.children( ".ui-icon" )
5797 .toggleClass(options.icons.header)
5798 .toggleClass(options.icons.headerSelected);
5799 this.element.addClass( "ui-accordion-icons" );
5800 }
5801 },
5802
5803 _destroyIcons: function() {
5804 this.headers.children( ".ui-icon" ).remove();
5805 this.element.removeClass( "ui-accordion-icons" );
5806 },
5807
5808 destroy: function() {
5809 var options = this.options;
5810
5811 this.element
5812 .removeClass( "ui-accordion ui-widget ui-helper-reset" )
5813 .removeAttr( "role" );
5814
5815 this.headers
5816 .unbind( ".accordion" )
5817 .removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
5818 .removeAttr( "role" )
5819 .removeAttr( "aria-expanded" )
5820 .removeAttr( "aria-selected" )
5821 .removeAttr( "tabIndex" );
5822
5823 this.headers.find( "a" ).removeAttr( "tabIndex" );
5824 this._destroyIcons();
5825 var contents = this.headers.next()
5826 .css( "display", "" )
5827 .removeAttr( "role" )
5828 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
5829 if ( options.autoHeight || options.fillHeight ) {
5830 contents.css( "height", "" );
5831 }
5832
5833 return $.Widget.prototype.destroy.call( this );
5834 },
5835
5836 _setOption: function( key, value ) {
5837 $.Widget.prototype._setOption.apply( this, arguments );
5838
5839 if ( key == "active" ) {
5840 this.activate( value );
5841 }
5842 if ( key == "icons" ) {
5843 this._destroyIcons();
5844 if ( value ) {
5845 this._createIcons();
5846 }
5847 }
5848 // #5332 - opacity doesn't cascade to positioned elements in IE
5849 // so we need to add the disabled class to the headers and panels
5850 if ( key == "disabled" ) {
5851 this.headers.add(this.headers.next())
5852 [ value ? "addClass" : "removeClass" ](
5853 "ui-accordion-disabled ui-state-disabled" );
5854 }
5855 },
5856
5857 _keydown: function( event ) {
5858 if ( this.options.disabled || event.altKey || event.ctrlKey ) {
5859 return;
5860 }
5861
5862 var keyCode = $.ui.keyCode,
5863 length = this.headers.length,
5864 currentIndex = this.headers.index( event.target ),
5865 toFocus = false;
5866
5867 switch ( event.keyCode ) {
5868 case keyCode.RIGHT:
5869 case keyCode.DOWN:
5870 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
5871 break;
5872 case keyCode.LEFT:
5873 case keyCode.UP:
5874 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
5875 break;
5876 case keyCode.SPACE:
5877 case keyCode.ENTER:
5878 this._clickHandler( { target: event.target }, event.target );
5879 event.preventDefault();
5880 }
5881
5882 if ( toFocus ) {
5883 $( event.target ).attr( "tabIndex", -1 );
5884 $( toFocus ).attr( "tabIndex", 0 );
5885 toFocus.focus();
5886 return false;
5887 }
5888
5889 return true;
5890 },
5891
5892 resize: function() {
5893 var options = this.options,
5894 maxHeight;
5895
5896 if ( options.fillSpace ) {
5897 if ( $.browser.msie ) {
5898 var defOverflow = this.element.parent().css( "overflow" );
5899 this.element.parent().css( "overflow", "hidden");
5900 }
5901 maxHeight = this.element.parent().height();
5902 if ($.browser.msie) {
5903 this.element.parent().css( "overflow", defOverflow );
5904 }
5905
5906 this.headers.each(function() {
5907 maxHeight -= $( this ).outerHeight( true );
5908 });
5909
5910 this.headers.next()
5911 .each(function() {
5912 $( this ).height( Math.max( 0, maxHeight -
5913 $( this ).innerHeight() + $( this ).height() ) );
5914 })
5915 .css( "overflow", "auto" );
5916 } else if ( options.autoHeight ) {
5917 maxHeight = 0;
5918 this.headers.next()
5919 .each(function() {
5920 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
5921 })
5922 .height( maxHeight );
5923 }
5924
5925 return this;
5926 },
5927
5928 activate: function( index ) {
5929 // TODO this gets called on init, changing the option without an explicit call for that
5930 this.options.active = index;
5931 // call clickHandler with custom event
5932 var active = this._findActive( index )[ 0 ];
5933 this._clickHandler( { target: active }, active );
5934
5935 return this;
5936 },
5937
5938 _findActive: function( selector ) {
5939 return selector
5940 ? typeof selector === "number"
5941 ? this.headers.filter( ":eq(" + selector + ")" )
5942 : this.headers.not( this.headers.not( selector ) )
5943 : selector === false
5944 ? $( [] )
5945 : this.headers.filter( ":eq(0)" );
5946 },
5947
5948 // TODO isn't event.target enough? why the separate target argument?
5949 _clickHandler: function( event, target ) {
5950 var options = this.options;
5951 if ( options.disabled ) {
5952 return;
5953 }
5954
5955 // called only when using activate(false) to close all parts programmatically
5956 if ( !event.target ) {
5957 if ( !options.collapsible ) {
5958 return;
5959 }
5960 this.active
5961 .removeClass( "ui-state-active ui-corner-top" )
5962 .addClass( "ui-state-default ui-corner-all" )
5963 .children( ".ui-icon" )
5964 .removeClass( options.icons.headerSelected )
5965 .addClass( options.icons.header );
5966 this.active.next().addClass( "ui-accordion-content-active" );
5967 var toHide = this.active.next(),
5968 data = {
5969 options: options,
5970 newHeader: $( [] ),
5971 oldHeader: options.active,
5972 newContent: $( [] ),
5973 oldContent: toHide
5974 },
5975 toShow = ( this.active = $( [] ) );
5976 this._toggle( toShow, toHide, data );
5977 return;
5978 }
5979
5980 // get the click target
5981 var clicked = $( event.currentTarget || target ),
5982 clickedIsActive = clicked[0] === this.active[0];
5983
5984 // TODO the option is changed, is that correct?
5985 // TODO if it is correct, shouldn't that happen after determining that the click is valid?
5986 options.active = options.collapsible && clickedIsActive ?
5987 false :
5988 this.headers.index( clicked );
5989
5990 // if animations are still active, or the active header is the target, ignore click
5991 if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
5992 return;
5993 }
5994
5995 // find elements to show and hide
5996 var active = this.active,
5997 toShow = clicked.next(),
5998 toHide = this.active.next(),
5999 data = {
6000 options: options,
6001 newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
6002 oldHeader: this.active,
6003 newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
6004 oldContent: toHide
6005 },
6006 down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
6007
6008 // when the call to ._toggle() comes after the class changes
6009 // it causes a very odd bug in IE 8 (see #6720)
6010 this.active = clickedIsActive ? $([]) : clicked;
6011 this._toggle( toShow, toHide, data, clickedIsActive, down );
6012
6013 // switch classes
6014 active
6015 .removeClass( "ui-state-active ui-corner-top" )
6016 .addClass( "ui-state-default ui-corner-all" )
6017 .children( ".ui-icon" )
6018 .removeClass( options.icons.headerSelected )
6019 .addClass( options.icons.header );
6020 if ( !clickedIsActive ) {
6021 clicked
6022 .removeClass( "ui-state-default ui-corner-all" )
6023 .addClass( "ui-state-active ui-corner-top" )
6024 .children( ".ui-icon" )
6025 .removeClass( options.icons.header )
6026 .addClass( options.icons.headerSelected );
6027 clicked
6028 .next()
6029 .addClass( "ui-accordion-content-active" );
6030 }
6031
6032 return;
6033 },
6034
6035 _toggle: function( toShow, toHide, data, clickedIsActive, down ) {
6036 var self = this,
6037 options = self.options;
6038
6039 self.toShow = toShow;
6040 self.toHide = toHide;
6041 self.data = data;
6042
6043 var complete = function() {
6044 if ( !self ) {
6045 return;
6046 }
6047 return self._completed.apply( self, arguments );
6048 };
6049
6050 // trigger changestart event
6051 self._trigger( "changestart", null, self.data );
6052
6053 // count elements to animate
6054 self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
6055
6056 if ( options.animated ) {
6057 var animOptions = {};
6058
6059 if ( options.collapsible && clickedIsActive ) {
6060 animOptions = {
6061 toShow: $( [] ),
6062 toHide: toHide,
6063 complete: complete,
6064 down: down,
6065 autoHeight: options.autoHeight || options.fillSpace
6066 };
6067 } else {
6068 animOptions = {
6069 toShow: toShow,
6070 toHide: toHide,
6071 complete: complete,
6072 down: down,
6073 autoHeight: options.autoHeight || options.fillSpace
6074 };
6075 }
6076
6077 if ( !options.proxied ) {
6078 options.proxied = options.animated;
6079 }
6080
6081 if ( !options.proxiedDuration ) {
6082 options.proxiedDuration = options.duration;
6083 }
6084
6085 options.animated = $.isFunction( options.proxied ) ?
6086 options.proxied( animOptions ) :
6087 options.proxied;
6088
6089 options.duration = $.isFunction( options.proxiedDuration ) ?
6090 options.proxiedDuration( animOptions ) :
6091 options.proxiedDuration;
6092
6093 var animations = $.ui.accordion.animations,
6094 duration = options.duration,
6095 easing = options.animated;
6096
6097 if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
6098 easing = "slide";
6099 }
6100 if ( !animations[ easing ] ) {
6101 animations[ easing ] = function( options ) {
6102 this.slide( options, {
6103 easing: easing,
6104 duration: duration || 700
6105 });
6106 };
6107 }
6108
6109 animations[ easing ]( animOptions );
6110 } else {
6111 if ( options.collapsible && clickedIsActive ) {
6112 toShow.toggle();
6113 } else {
6114 toHide.hide();
6115 toShow.show();
6116 }
6117
6118 complete( true );
6119 }
6120
6121 // TODO assert that the blur and focus triggers are really necessary, remove otherwise
6122 toHide.prev()
6123 .attr({
6124 "aria-expanded": "false",
6125 "aria-selected": "false",
6126 tabIndex: -1
6127 })
6128 .blur();
6129 toShow.prev()
6130 .attr({
6131 "aria-expanded": "true",
6132 "aria-selected": "true",
6133 tabIndex: 0
6134 })
6135 .focus();
6136 },
6137
6138 _completed: function( cancel ) {
6139 this.running = cancel ? 0 : --this.running;
6140 if ( this.running ) {
6141 return;
6142 }
6143
6144 if ( this.options.clearStyle ) {
6145 this.toShow.add( this.toHide ).css({
6146 height: "",
6147 overflow: ""
6148 });
6149 }
6150
6151 // other classes are removed before the animation; this one needs to stay until completed
6152 this.toHide.removeClass( "ui-accordion-content-active" );
6153 // Work around for rendering bug in IE (#5421)
6154 if ( this.toHide.length ) {
6155 this.toHide.parent()[0].className = this.toHide.parent()[0].className;
6156 }
6157
6158 this._trigger( "change", null, this.data );
6159 }
6160 });
6161
6162 $.extend( $.ui.accordion, {
6163 version: "1.8.16",
6164 animations: {
6165 slide: function( options, additions ) {
6166 options = $.extend({
6167 easing: "swing",
6168 duration: 300
6169 }, options, additions );
6170 if ( !options.toHide.size() ) {
6171 options.toShow.animate({
6172 height: "show",
6173 paddingTop: "show",
6174 paddingBottom: "show"
6175 }, options );
6176 return;
6177 }
6178 if ( !options.toShow.size() ) {
6179 options.toHide.animate({
6180 height: "hide",
6181 paddingTop: "hide",
6182 paddingBottom: "hide"
6183 }, options );
6184 return;
6185 }
6186 var overflow = options.toShow.css( "overflow" ),
6187 percentDone = 0,
6188 showProps = {},
6189 hideProps = {},
6190 fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
6191 originalWidth;
6192 // fix width before calculating height of hidden element
6193 var s = options.toShow;
6194 originalWidth = s[0].style.width;
6195 s.width( parseInt( s.parent().width(), 10 )
6196 - parseInt( s.css( "paddingLeft" ), 10 )
6197 - parseInt( s.css( "paddingRight" ), 10 )
6198 - ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
6199 - ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
6200
6201 $.each( fxAttrs, function( i, prop ) {
6202 hideProps[ prop ] = "hide";
6203
6204 var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
6205 showProps[ prop ] = {
6206 value: parts[ 1 ],
6207 unit: parts[ 2 ] || "px"
6208 };
6209 });
6210 options.toShow.css({ height: 0, overflow: "hidden" }).show();
6211 options.toHide
6212 .filter( ":hidden" )
6213 .each( options.complete )
6214 .end()
6215 .filter( ":visible" )
6216 .animate( hideProps, {
6217 step: function( now, settings ) {
6218 // only calculate the percent when animating height
6219 // IE gets very inconsistent results when animating elements
6220 // with small values, which is common for padding
6221 if ( settings.prop == "height" ) {
6222 percentDone = ( settings.end - settings.start === 0 ) ? 0 :
6223 ( settings.now - settings.start ) / ( settings.end - settings.start );
6224 }
6225
6226 options.toShow[ 0 ].style[ settings.prop ] =
6227 ( percentDone * showProps[ settings.prop ].value )
6228 + showProps[ settings.prop ].unit;
6229 },
6230 duration: options.duration,
6231 easing: options.easing,
6232 complete: function() {
6233 if ( !options.autoHeight ) {
6234 options.toShow.css( "height", "" );
6235 }
6236 options.toShow.css({
6237 width: originalWidth,
6238 overflow: overflow
6239 });
6240 options.complete();
6241 }
6242 });
6243 },
6244 bounceslide: function( options ) {
6245 this.slide( options, {
6246 easing: options.down ? "easeOutBounce" : "swing",
6247 duration: options.down ? 1000 : 200
6248 });
6249 }
6250 }
6251 });
6252
6253 })( jQuery );
6254 /*
6255 * jQuery UI Autocomplete 1.8.16
6256 *
6257 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
6258 * Dual licensed under the MIT or GPL Version 2 licenses.
6259 * http://jquery.org/license
6260 *
6261 * http://docs.jquery.com/UI/Autocomplete
6262 *
6263 * Depends:
6264 * jquery.ui.core.js
6265 * jquery.ui.widget.js
6266 * jquery.ui.position.js
6267 */
6268 (function( $, undefined ) {
6269
6270 // used to prevent race conditions with remote data sources
6271 var requestIndex = 0;
6272
6273 $.widget( "ui.autocomplete", {
6274 options: {
6275 appendTo: "body",
6276 autoFocus: false,
6277 delay: 300,
6278 minLength: 1,
6279 position: {
6280 my: "left top",
6281 at: "left bottom",
6282 collision: "none"
6283 },
6284 source: null
6285 },
6286
6287 pending: 0,
6288
6289 _create: function() {
6290 var self = this,
6291 doc = this.element[ 0 ].ownerDocument,
6292 suppressKeyPress;
6293
6294 this.element
6295 .addClass( "ui-autocomplete-input" )
6296 .attr( "autocomplete", "off" )
6297 // TODO verify these actually work as intended
6298 .attr({
6299 role: "textbox",
6300 "aria-autocomplete": "list",
6301 "aria-haspopup": "true"
6302 })
6303 .bind( "keydown.autocomplete", function( event ) {
6304 if ( self.options.disabled || self.element.propAttr( "readOnly" ) ) {
6305 return;
6306 }
6307
6308 suppressKeyPress = false;
6309 var keyCode = $.ui.keyCode;
6310 switch( event.keyCode ) {
6311 case keyCode.PAGE_UP:
6312 self._move( "previousPage", event );
6313 break;
6314 case keyCode.PAGE_DOWN:
6315 self._move( "nextPage", event );
6316 break;
6317 case keyCode.UP:
6318 self._move( "previous", event );
6319 // prevent moving cursor to beginning of text field in some browsers
6320 event.preventDefault();
6321 break;
6322 case keyCode.DOWN:
6323 self._move( "next", event );
6324 // prevent moving cursor to end of text field in some browsers
6325 event.preventDefault();
6326 break;
6327 case keyCode.ENTER:
6328 case keyCode.NUMPAD_ENTER:
6329 // when menu is open and has focus
6330 if ( self.menu.active ) {
6331 // #6055 - Opera still allows the keypress to occur
6332 // which causes forms to submit
6333 suppressKeyPress = true;
6334 event.preventDefault();
6335 }
6336 //passthrough - ENTER and TAB both select the current element
6337 case keyCode.TAB:
6338 if ( !self.menu.active ) {
6339 return;
6340 }
6341 self.menu.select( event );
6342 break;
6343 case keyCode.ESCAPE:
6344 self.element.val( self.term );
6345 self.close( event );
6346 break;
6347 default:
6348 // keypress is triggered before the input value is changed
6349 clearTimeout( self.searching );
6350 self.searching = setTimeout(function() {
6351 // only search if the value has changed
6352 if ( self.term != self.element.val() ) {
6353 self.selectedItem = null;
6354 self.search( null, event );
6355 }
6356 }, self.options.delay );
6357 break;
6358 }
6359 })
6360 .bind( "keypress.autocomplete", function( event ) {
6361 if ( suppressKeyPress ) {
6362 suppressKeyPress = false;
6363 event.preventDefault();
6364 }
6365 })
6366 .bind( "focus.autocomplete", function() {
6367 if ( self.options.disabled ) {
6368 return;
6369 }
6370
6371 self.selectedItem = null;
6372 self.previous = self.element.val();
6373 })
6374 .bind( "blur.autocomplete", function( event ) {
6375 if ( self.options.disabled ) {
6376 return;
6377 }
6378
6379 clearTimeout( self.searching );
6380 // clicks on the menu (or a button to trigger a search) will cause a blur event
6381 self.closing = setTimeout(function() {
6382 self.close( event );
6383 self._change( event );
6384 }, 150 );
6385 });
6386 this._initSource();
6387 this.response = function() {
6388 return self._response.apply( self, arguments );
6389 };
6390 this.menu = $( "<ul></ul>" )
6391 .addClass( "ui-autocomplete" )
6392 .appendTo( $( this.options.appendTo || "body", doc )[0] )
6393 // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
6394 .mousedown(function( event ) {
6395 // clicking on the scrollbar causes focus to shift to the body
6396 // but we can't detect a mouseup or a click immediately afterward
6397 // so we have to track the next mousedown and close the menu if
6398 // the user clicks somewhere outside of the autocomplete
6399 var menuElement = self.menu.element[ 0 ];
6400 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
6401 setTimeout(function() {
6402 $( document ).one( 'mousedown', function( event ) {
6403 if ( event.target !== self.element[ 0 ] &&
6404 event.target !== menuElement &&
6405 !$.ui.contains( menuElement, event.target ) ) {
6406 self.close();
6407 }
6408 });
6409 }, 1 );
6410 }
6411
6412 // use another timeout to make sure the blur-event-handler on the input was already triggered
6413 setTimeout(function() {
6414 clearTimeout( self.closing );
6415 }, 13);
6416 })
6417 .menu({
6418 focus: function( event, ui ) {
6419 var item = ui.item.data( "item.autocomplete" );
6420 if ( false !== self._trigger( "focus", event, { item: item } ) ) {
6421 // use value to match what will end up in the input, if it was a key event
6422 if ( /^key/.test(event.originalEvent.type) ) {
6423 self.element.val( item.value );
6424 }
6425 }
6426 },
6427 selected: function( event, ui ) {
6428 var item = ui.item.data( "item.autocomplete" ),
6429 previous = self.previous;
6430
6431 // only trigger when focus was lost (click on menu)
6432 if ( self.element[0] !== doc.activeElement ) {
6433 self.element.focus();
6434 self.previous = previous;
6435 // #6109 - IE triggers two focus events and the second
6436 // is asynchronous, so we need to reset the previous
6437 // term synchronously and asynchronously :-(
6438 setTimeout(function() {
6439 self.previous = previous;
6440 self.selectedItem = item;
6441 }, 1);
6442 }
6443
6444 if ( false !== self._trigger( "select", event, { item: item } ) ) {
6445 self.element.val( item.value );
6446 }
6447 // reset the term after the select event
6448 // this allows custom select handling to work properly
6449 self.term = self.element.val();
6450
6451 self.close( event );
6452 self.selectedItem = item;
6453 },
6454 blur: function( event, ui ) {
6455 // don't set the value of the text field if it's already correct
6456 // this prevents moving the cursor unnecessarily
6457 if ( self.menu.element.is(":visible") &&
6458 ( self.element.val() !== self.term ) ) {
6459 self.element.val( self.term );
6460 }
6461 }
6462 })
6463 .zIndex( this.element.zIndex() + 1 )
6464 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
6465 .css({ top: 0, left: 0 })
6466 .hide()
6467 .data( "menu" );
6468 if ( $.fn.bgiframe ) {
6469 this.menu.element.bgiframe();
6470 }
6471 },
6472
6473 destroy: function() {
6474 this.element
6475 .removeClass( "ui-autocomplete-input" )
6476 .removeAttr( "autocomplete" )
6477 .removeAttr( "role" )
6478 .removeAttr( "aria-autocomplete" )
6479 .removeAttr( "aria-haspopup" );
6480 this.menu.element.remove();
6481 $.Widget.prototype.destroy.call( this );
6482 },
6483
6484 _setOption: function( key, value ) {
6485 $.Widget.prototype._setOption.apply( this, arguments );
6486 if ( key === "source" ) {
6487 this._initSource();
6488 }
6489 if ( key === "appendTo" ) {
6490 this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
6491 }
6492 if ( key === "disabled" && value && this.xhr ) {
6493 this.xhr.abort();
6494 }
6495 },
6496
6497 _initSource: function() {
6498 var self = this,
6499 array,
6500 url;
6501 if ( $.isArray(this.options.source) ) {
6502 array = this.options.source;
6503 this.source = function( request, response ) {
6504 response( $.ui.autocomplete.filter(array, request.term) );
6505 };
6506 } else if ( typeof this.options.source === "string" ) {
6507 url = this.options.source;
6508 this.source = function( request, response ) {
6509 if ( self.xhr ) {
6510 self.xhr.abort();
6511 }
6512 self.xhr = $.ajax({
6513 url: url,
6514 data: request,
6515 dataType: "json",
6516 autocompleteRequest: ++requestIndex,
6517 success: function( data, status ) {
6518 if ( this.autocompleteRequest === requestIndex ) {
6519 response( data );
6520 }
6521 },
6522 error: function() {
6523 if ( this.autocompleteRequest === requestIndex ) {
6524 response( [] );
6525 }
6526 }
6527 });
6528 };
6529 } else {
6530 this.source = this.options.source;
6531 }
6532 },
6533
6534 search: function( value, event ) {
6535 value = value != null ? value : this.element.val();
6536
6537 // always save the actual value, not the one passed as an argument
6538 this.term = this.element.val();
6539
6540 if ( value.length < this.options.minLength ) {
6541 return this.close( event );
6542 }
6543
6544 clearTimeout( this.closing );
6545 if ( this._trigger( "search", event ) === false ) {
6546 return;
6547 }
6548
6549 return this._search( value );
6550 },
6551
6552 _search: function( value ) {
6553 this.pending++;
6554 this.element.addClass( "ui-autocomplete-loading" );
6555
6556 this.source( { term: value }, this.response );
6557 },
6558
6559 _response: function( content ) {
6560 if ( !this.options.disabled && content && content.length ) {
6561 content = this._normalize( content );
6562 this._suggest( content );
6563 this._trigger( "open" );
6564 } else {
6565 this.close();
6566 }
6567 this.pending--;
6568 if ( !this.pending ) {
6569 this.element.removeClass( "ui-autocomplete-loading" );
6570 }
6571 },
6572
6573 close: function( event ) {
6574 clearTimeout( this.closing );
6575 if ( this.menu.element.is(":visible") ) {
6576 this.menu.element.hide();
6577 this.menu.deactivate();
6578 this._trigger( "close", event );
6579 }
6580 },
6581
6582 _change: function( event ) {
6583 if ( this.previous !== this.element.val() ) {
6584 this._trigger( "change", event, { item: this.selectedItem } );
6585 }
6586 },
6587
6588 _normalize: function( items ) {
6589 // assume all items have the right format when the first item is complete
6590 if ( items.length && items[0].label && items[0].value ) {
6591 return items;
6592 }
6593 return $.map( items, function(item) {
6594 if ( typeof item === "string" ) {
6595 return {
6596 label: item,
6597 value: item
6598 };
6599 }
6600 return $.extend({
6601 label: item.label || item.value,
6602 value: item.value || item.label
6603 }, item );
6604 });
6605 },
6606
6607 _suggest: function( items ) {
6608 var ul = this.menu.element
6609 .empty()
6610 .zIndex( this.element.zIndex() + 1 );
6611 this._renderMenu( ul, items );
6612 // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
6613 this.menu.deactivate();
6614 this.menu.refresh();
6615
6616 // size and position menu
6617 ul.show();
6618 this._resizeMenu();
6619 ul.position( $.extend({
6620 of: this.element
6621 }, this.options.position ));
6622
6623 if ( this.options.autoFocus ) {
6624 this.menu.next( new $.Event("mouseover") );
6625 }
6626 },
6627
6628 _resizeMenu: function() {
6629 var ul = this.menu.element;
6630 ul.outerWidth( Math.max(
6631 ul.width( "" ).outerWidth(),
6632 this.element.outerWidth()
6633 ) );
6634 },
6635
6636 _renderMenu: function( ul, items ) {
6637 var self = this;
6638 $.each( items, function( index, item ) {
6639 self._renderItem( ul, item );
6640 });
6641 },
6642
6643 _renderItem: function( ul, item) {
6644 return $( "<li></li>" )
6645 .data( "item.autocomplete", item )
6646 .append( $( "<a></a>" ).text( item.label ) )
6647 .appendTo( ul );
6648 },
6649
6650 _move: function( direction, event ) {
6651 if ( !this.menu.element.is(":visible") ) {
6652 this.search( null, event );
6653 return;
6654 }
6655 if ( this.menu.first() && /^previous/.test(direction) ||
6656 this.menu.last() && /^next/.test(direction) ) {
6657 this.element.val( this.term );
6658 this.menu.deactivate();
6659 return;
6660 }
6661 this.menu[ direction ]( event );
6662 },
6663
6664 widget: function() {
6665 return this.menu.element;
6666 }
6667 });
6668
6669 $.extend( $.ui.autocomplete, {
6670 escapeRegex: function( value ) {
6671 return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
6672 },
6673 filter: function(array, term) {
6674 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
6675 return $.grep( array, function(value) {
6676 return matcher.test( value.label || value.value || value );
6677 });
6678 }
6679 });
6680
6681 }( jQuery ));
6682
6683 /*
6684 * jQuery UI Menu (not officially released)
6685 *
6686 * This widget isn't yet finished and the API is subject to change. We plan to finish
6687 * it for the next release. You're welcome to give it a try anyway and give us feedback,
6688 * as long as you're okay with migrating your code later on. We can help with that, too.
6689 *
6690 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
6691 * Dual licensed under the MIT or GPL Version 2 licenses.
6692 * http://jquery.org/license
6693 *
6694 * http://docs.jquery.com/UI/Menu
6695 *
6696 * Depends:
6697 * jquery.ui.core.js
6698 * jquery.ui.widget.js
6699 */
6700 (function($) {
6701
6702 $.widget("ui.menu", {
6703 _create: function() {
6704 var self = this;
6705 this.element
6706 .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
6707 .attr({
6708 role: "listbox",
6709 "aria-activedescendant": "ui-active-menuitem"
6710 })
6711 .click(function( event ) {
6712 if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
6713 return;
6714 }
6715 // temporary
6716 event.preventDefault();
6717 self.select( event );
6718 });
6719 this.refresh();
6720 },
6721
6722 refresh: function() {
6723 var self = this;
6724
6725 // don't refresh list items that are already adapted
6726 var items = this.element.children("li:not(.ui-menu-item):has(a)")
6727 .addClass("ui-menu-item")
6728 .attr("role", "menuitem");
6729
6730 items.children("a")
6731 .addClass("ui-corner-all")
6732 .attr("tabindex", -1)
6733 // mouseenter doesn't work with event delegation
6734 .mouseenter(function( event ) {
6735 self.activate( event, $(this).parent() );
6736 })
6737 .mouseleave(function() {
6738 self.deactivate();
6739 });
6740 },
6741
6742 activate: function( event, item ) {
6743 this.deactivate();
6744 if (this.hasScroll()) {
6745 var offset = item.offset().top - this.element.offset().top,
6746 scroll = this.element.scrollTop(),
6747 elementHeight = this.element.height();
6748 if (offset < 0) {
6749 this.element.scrollTop( scroll + offset);
6750 } else if (offset >= elementHeight) {
6751 this.element.scrollTop( scroll + offset - elementHeight + item.height());
6752 }
6753 }
6754 this.active = item.eq(0)
6755 .children("a")
6756 .addClass("ui-state-hover")
6757 .attr("id", "ui-active-menuitem")
6758 .end();
6759 this._trigger("focus", event, { item: item });
6760 },
6761
6762 deactivate: function() {
6763 if (!this.active) { return; }
6764
6765 this.active.children("a")
6766 .removeClass("ui-state-hover")
6767 .removeAttr("id");
6768 this._trigger("blur");
6769 this.active = null;
6770 },
6771
6772 next: function(event) {
6773 this.move("next", ".ui-menu-item:first", event);
6774 },
6775
6776 previous: function(event) {
6777 this.move("prev", ".ui-menu-item:last", event);
6778 },
6779
6780 first: function() {
6781 return this.active && !this.active.prevAll(".ui-menu-item").length;
6782 },
6783
6784 last: function() {
6785 return this.active && !this.active.nextAll(".ui-menu-item").length;
6786 },
6787
6788 move: function(direction, edge, event) {
6789 if (!this.active) {
6790 this.activate(event, this.element.children(edge));
6791 return;
6792 }
6793 var next = this.active[direction + "All"](".ui-menu-item").eq(0);
6794 if (next.length) {
6795 this.activate(event, next);
6796 } else {
6797 this.activate(event, this.element.children(edge));
6798 }
6799 },
6800
6801 // TODO merge with previousPage
6802 nextPage: function(event) {
6803 if (this.hasScroll()) {
6804 // TODO merge with no-scroll-else
6805 if (!this.active || this.last()) {
6806 this.activate(event, this.element.children(".ui-menu-item:first"));
6807 return;
6808 }
6809 var base = this.active.offset().top,
6810 height = this.element.height(),
6811 result = this.element.children(".ui-menu-item").filter(function() {
6812 var close = $(this).offset().top - base - height + $(this).height();
6813 // TODO improve approximation
6814 return close < 10 && close > -10;
6815 });
6816
6817 // TODO try to catch this earlier when scrollTop indicates the last page anyway
6818 if (!result.length) {
6819 result = this.element.children(".ui-menu-item:last");
6820 }
6821 this.activate(event, result);
6822 } else {
6823 this.activate(event, this.element.children(".ui-menu-item")
6824 .filter(!this.active || this.last() ? ":first" : ":last"));
6825 }
6826 },
6827
6828 // TODO merge with nextPage
6829 previousPage: function(event) {
6830 if (this.hasScroll()) {
6831 // TODO merge with no-scroll-else
6832 if (!this.active || this.first()) {
6833 this.activate(event, this.element.children(".ui-menu-item:last"));
6834 return;
6835 }
6836
6837 var base = this.active.offset().top,
6838 height = this.element.height();
6839 result = this.element.children(".ui-menu-item").filter(function() {
6840 var close = $(this).offset().top - base + height - $(this).height();
6841 // TODO improve approximation
6842 return close < 10 && close > -10;
6843 });
6844
6845 // TODO try to catch this earlier when scrollTop indicates the last page anyway
6846 if (!result.length) {
6847 result = this.element.children(".ui-menu-item:first");
6848 }
6849 this.activate(event, result);
6850 } else {
6851 this.activate(event, this.element.children(".ui-menu-item")
6852 .filter(!this.active || this.first() ? ":last" : ":first"));
6853 }
6854 },
6855
6856 hasScroll: function() {
6857 return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight");
6858 },
6859
6860 select: function( event ) {
6861 this._trigger("selected", event, { item: this.active });
6862 }
6863 });
6864
6865 }(jQuery));
6866 /*
6867 * jQuery UI Button 1.8.16
6868 *
6869 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
6870 * Dual licensed under the MIT or GPL Version 2 licenses.
6871 * http://jquery.org/license
6872 *
6873 * http://docs.jquery.com/UI/Button
6874 *
6875 * Depends:
6876 * jquery.ui.core.js
6877 * jquery.ui.widget.js
6878 */
6879 (function( $, undefined ) {
6880
6881 var lastActive, startXPos, startYPos, clickDragged,
6882 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
6883 stateClasses = "ui-state-hover ui-state-active ",
6884 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",
6885 formResetHandler = function() {
6886 var buttons = $( this ).find( ":ui-button" );
6887 setTimeout(function() {
6888 buttons.button( "refresh" );
6889 }, 1 );
6890 },
6891 radioGroup = function( radio ) {
6892 var name = radio.name,
6893 form = radio.form,
6894 radios = $( [] );
6895 if ( name ) {
6896 if ( form ) {
6897 radios = $( form ).find( "[name='" + name + "']" );
6898 } else {
6899 radios = $( "[name='" + name + "']", radio.ownerDocument )
6900 .filter(function() {
6901 return !this.form;
6902 });
6903 }
6904 }
6905 return radios;
6906 };
6907
6908 $.widget( "ui.button", {
6909 options: {
6910 disabled: null,
6911 text: true,
6912 label: null,
6913 icons: {
6914 primary: null,
6915 secondary: null
6916 }
6917 },
6918 _create: function() {
6919 this.element.closest( "form" )
6920 .unbind( "reset.button" )
6921 .bind( "reset.button", formResetHandler );
6922
6923 if ( typeof this.options.disabled !== "boolean" ) {
6924 this.options.disabled = this.element.propAttr( "disabled" );
6925 }
6926
6927 this._determineButtonType();
6928 this.hasTitle = !!this.buttonElement.attr( "title" );
6929
6930 var self = this,
6931 options = this.options,
6932 toggleButton = this.type === "checkbox" || this.type === "radio",
6933 hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
6934 focusClass = "ui-state-focus";
6935
6936 if ( options.label === null ) {
6937 options.label = this.buttonElement.html();
6938 }
6939
6940 if ( this.element.is( ":disabled" ) ) {
6941 options.disabled = true;
6942 }
6943
6944 this.buttonElement
6945 .addClass( baseClasses )
6946 .attr( "role", "button" )
6947 .bind( "mouseenter.button", function() {
6948 if ( options.disabled ) {
6949 return;
6950 }
6951 $( this ).addClass( "ui-state-hover" );
6952 if ( this === lastActive ) {
6953 $( this ).addClass( "ui-state-active" );
6954 }
6955 })
6956 .bind( "mouseleave.button", function() {
6957 if ( options.disabled ) {
6958 return;
6959 }
6960 $( this ).removeClass( hoverClass );
6961 })
6962 .bind( "click.button", function( event ) {
6963 if ( options.disabled ) {
6964 event.preventDefault();
6965 event.stopImmediatePropagation();
6966 }
6967 });
6968
6969 this.element
6970 .bind( "focus.button", function() {
6971 // no need to check disabled, focus won't be triggered anyway
6972 self.buttonElement.addClass( focusClass );
6973 })
6974 .bind( "blur.button", function() {
6975 self.buttonElement.removeClass( focusClass );
6976 });
6977
6978 if ( toggleButton ) {
6979 this.element.bind( "change.button", function() {
6980 if ( clickDragged ) {
6981 return;
6982 }
6983 self.refresh();
6984 });
6985 // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
6986 // prevents issue where button state changes but checkbox/radio checked state
6987 // does not in Firefox (see ticket #6970)
6988 this.buttonElement
6989 .bind( "mousedown.button", function( event ) {
6990 if ( options.disabled ) {
6991 return;
6992 }
6993 clickDragged = false;
6994 startXPos = event.pageX;
6995 startYPos = event.pageY;
6996 })
6997 .bind( "mouseup.button", function( event ) {
6998 if ( options.disabled ) {
6999 return;
7000 }
7001 if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
7002 clickDragged = true;
7003 }
7004 });
7005 }
7006
7007 if ( this.type === "checkbox" ) {
7008 this.buttonElement.bind( "click.button", function() {
7009 if ( options.disabled || clickDragged ) {
7010 return false;
7011 }
7012 $( this ).toggleClass( "ui-state-active" );
7013 self.buttonElement.attr( "aria-pressed", self.element[0].checked );
7014 });
7015 } else if ( this.type === "radio" ) {
7016 this.buttonElement.bind( "click.button", function() {
7017 if ( options.disabled || clickDragged ) {
7018 return false;
7019 }
7020 $( this ).addClass( "ui-state-active" );
7021 self.buttonElement.attr( "aria-pressed", "true" );
7022
7023 var radio = self.element[ 0 ];
7024 radioGroup( radio )
7025 .not( radio )
7026 .map(function() {
7027 return $( this ).button( "widget" )[ 0 ];
7028 })
7029 .removeClass( "ui-state-active" )
7030 .attr( "aria-pressed", "false" );
7031 });
7032 } else {
7033 this.buttonElement
7034 .bind( "mousedown.button", function() {
7035 if ( options.disabled ) {
7036 return false;
7037 }
7038 $( this ).addClass( "ui-state-active" );
7039 lastActive = this;
7040 $( document ).one( "mouseup", function() {
7041 lastActive = null;
7042 });
7043 })
7044 .bind( "mouseup.button", function() {
7045 if ( options.disabled ) {
7046 return false;
7047 }
7048 $( this ).removeClass( "ui-state-active" );
7049 })
7050 .bind( "keydown.button", function(event) {
7051 if ( options.disabled ) {
7052 return false;
7053 }
7054 if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
7055 $( this ).addClass( "ui-state-active" );
7056 }
7057 })
7058 .bind( "keyup.button", function() {
7059 $( this ).removeClass( "ui-state-active" );
7060 });
7061
7062 if ( this.buttonElement.is("a") ) {
7063 this.buttonElement.keyup(function(event) {
7064 if ( event.keyCode === $.ui.keyCode.SPACE ) {
7065 // TODO pass through original event correctly (just as 2nd argument doesn't work)
7066 $( this ).click();
7067 }
7068 });
7069 }
7070 }
7071
7072 // TODO: pull out $.Widget's handling for the disabled option into
7073 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
7074 // be overridden by individual plugins
7075 this._setOption( "disabled", options.disabled );
7076 this._resetButton();
7077 },
7078
7079 _determineButtonType: function() {
7080
7081 if ( this.element.is(":checkbox") ) {
7082 this.type = "checkbox";
7083 } else if ( this.element.is(":radio") ) {
7084 this.type = "radio";
7085 } else if ( this.element.is("input") ) {
7086 this.type = "input";
7087 } else {
7088 this.type = "button";
7089 }
7090
7091 if ( this.type === "checkbox" || this.type === "radio" ) {
7092 // we don't search against the document in case the element
7093 // is disconnected from the DOM
7094 var ancestor = this.element.parents().filter(":last"),
7095 labelSelector = "label[for='" + this.element.attr("id") + "']";
7096 this.buttonElement = ancestor.find( labelSelector );
7097 if ( !this.buttonElement.length ) {
7098 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
7099 this.buttonElement = ancestor.filter( labelSelector );
7100 if ( !this.buttonElement.length ) {
7101 this.buttonElement = ancestor.find( labelSelector );
7102 }
7103 }
7104 this.element.addClass( "ui-helper-hidden-accessible" );
7105
7106 var checked = this.element.is( ":checked" );
7107 if ( checked ) {
7108 this.buttonElement.addClass( "ui-state-active" );
7109 }
7110 this.buttonElement.attr( "aria-pressed", checked );
7111 } else {
7112 this.buttonElement = this.element;
7113 }
7114 },
7115
7116 widget: function() {
7117 return this.buttonElement;
7118 },
7119
7120 destroy: function() {
7121 this.element
7122 .removeClass( "ui-helper-hidden-accessible" );
7123 this.buttonElement
7124 .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
7125 .removeAttr( "role" )
7126 .removeAttr( "aria-pressed" )
7127 .html( this.buttonElement.find(".ui-button-text").html() );
7128
7129 if ( !this.hasTitle ) {
7130 this.buttonElement.removeAttr( "title" );
7131 }
7132
7133 $.Widget.prototype.destroy.call( this );
7134 },
7135
7136 _setOption: function( key, value ) {
7137 $.Widget.prototype._setOption.apply( this, arguments );
7138 if ( key === "disabled" ) {
7139 if ( value ) {
7140 this.element.propAttr( "disabled", true );
7141 } else {
7142 this.element.propAttr( "disabled", false );
7143 }
7144 return;
7145 }
7146 this._resetButton();
7147 },
7148
7149 refresh: function() {
7150 var isDisabled = this.element.is( ":disabled" );
7151 if ( isDisabled !== this.options.disabled ) {
7152 this._setOption( "disabled", isDisabled );
7153 }
7154 if ( this.type === "radio" ) {
7155 radioGroup( this.element[0] ).each(function() {
7156 if ( $( this ).is( ":checked" ) ) {
7157 $( this ).button( "widget" )
7158 .addClass( "ui-state-active" )
7159 .attr( "aria-pressed", "true" );
7160 } else {
7161 $( this ).button( "widget" )
7162 .removeClass( "ui-state-active" )
7163 .attr( "aria-pressed", "false" );
7164 }
7165 });
7166 } else if ( this.type === "checkbox" ) {
7167 if ( this.element.is( ":checked" ) ) {
7168 this.buttonElement
7169 .addClass( "ui-state-active" )
7170 .attr( "aria-pressed", "true" );
7171 } else {
7172 this.buttonElement
7173 .removeClass( "ui-state-active" )
7174 .attr( "aria-pressed", "false" );
7175 }
7176 }
7177 },
7178
7179 _resetButton: function() {
7180 if ( this.type === "input" ) {
7181 if ( this.options.label ) {
7182 this.element.val( this.options.label );
7183 }
7184 return;
7185 }
7186 var buttonElement = this.buttonElement.removeClass( typeClasses ),
7187 buttonText = $( "<span></span>" )
7188 .addClass( "ui-button-text" )
7189 .html( this.options.label )
7190 .appendTo( buttonElement.empty() )
7191 .text(),
7192 icons = this.options.icons,
7193 multipleIcons = icons.primary && icons.secondary,
7194 buttonClasses = [];
7195
7196 if ( icons.primary || icons.secondary ) {
7197 if ( this.options.text ) {
7198 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
7199 }
7200
7201 if ( icons.primary ) {
7202 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
7203 }
7204
7205 if ( icons.secondary ) {
7206 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
7207 }
7208
7209 if ( !this.options.text ) {
7210 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
7211
7212 if ( !this.hasTitle ) {
7213 buttonElement.attr( "title", buttonText );
7214 }
7215 }
7216 } else {
7217 buttonClasses.push( "ui-button-text-only" );
7218 }
7219 buttonElement.addClass( buttonClasses.join( " " ) );
7220 }
7221 });
7222
7223 $.widget( "ui.buttonset", {
7224 options: {
7225 items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
7226 },
7227
7228 _create: function() {
7229 this.element.addClass( "ui-buttonset" );
7230 },
7231
7232 _init: function() {
7233 this.refresh();
7234 },
7235
7236 _setOption: function( key, value ) {
7237 if ( key === "disabled" ) {
7238 this.buttons.button( "option", key, value );
7239 }
7240
7241 $.Widget.prototype._setOption.apply( this, arguments );
7242 },
7243
7244 refresh: function() {
7245 var ltr = this.element.css( "direction" ) === "ltr";
7246
7247 this.buttons = this.element.find( this.options.items )
7248 .filter( ":ui-button" )
7249 .button( "refresh" )
7250 .end()
7251 .not( ":ui-button" )
7252 .button()
7253 .end()
7254 .map(function() {
7255 return $( this ).button( "widget" )[ 0 ];
7256 })
7257 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
7258 .filter( ":first" )
7259 .addClass( ltr ? "ui-corner-left" : "ui-corner-right" )
7260 .end()
7261 .filter( ":last" )
7262 .addClass( ltr ? "ui-corner-right" : "ui-corner-left" )
7263 .end()
7264 .end();
7265 },
7266
7267 destroy: function() {
7268 this.element.removeClass( "ui-buttonset" );
7269 this.buttons
7270 .map(function() {
7271 return $( this ).button( "widget" )[ 0 ];
7272 })
7273 .removeClass( "ui-corner-left ui-corner-right" )
7274 .end()
7275 .button( "destroy" );
7276
7277 $.Widget.prototype.destroy.call( this );
7278 }
7279 });
7280
7281 }( jQuery ) );
7282 /*
7283 * jQuery UI Datepicker 1.8.16
7284 *
7285 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
7286 * Dual licensed under the MIT or GPL Version 2 licenses.
7287 * http://jquery.org/license
7288 *
7289 * http://docs.jquery.com/UI/Datepicker
7290 *
7291 * Depends:
7292 * jquery.ui.core.js
7293 */
7294 (function( $, undefined ) {
7295
7296 $.extend($.ui, { datepicker: { version: "1.8.16" } });
7297
7298 var PROP_NAME = 'datepicker';
7299 var dpuuid = new Date().getTime();
7300 var instActive;
7301
7302 /* Date picker manager.
7303 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7304 Settings for (groups of) date pickers are maintained in an instance object,
7305 allowing multiple different settings on the same page. */
7306
7307 function Datepicker() {
7308 this.debug = false; // Change this to true to start debugging
7309 this._curInst = null; // The current instance in use
7310 this._keyEvent = false; // If the last event was a key event
7311 this._disabledInputs = []; // List of date picker inputs that have been disabled
7312 this._datepickerShowing = false; // True if the popup picker is showing , false if not
7313 this._inDialog = false; // True if showing within a "dialog", false if not
7314 this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
7315 this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
7316 this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
7317 this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
7318 this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
7319 this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
7320 this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
7321 this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
7322 this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
7323 this.regional = []; // Available regional settings, indexed by language code
7324 this.regional[''] = { // Default regional settings
7325 closeText: 'Done', // Display text for close link
7326 prevText: 'Prev', // Display text for previous month link
7327 nextText: 'Next', // Display text for next month link
7328 currentText: 'Today', // Display text for current month link
7329 monthNames: ['January','February','March','April','May','June',
7330 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
7331 monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
7332 dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
7333 dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
7334 dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
7335 weekHeader: 'Wk', // Column header for week of the year
7336 dateFormat: 'mm/dd/yy', // See format options on parseDate
7337 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7338 isRTL: false, // True if right-to-left language, false if left-to-right
7339 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7340 yearSuffix: '' // Additional text to append to the year in the month headers
7341 };
7342 this._defaults = { // Global defaults for all the date picker instances
7343 showOn: 'focus', // 'focus' for popup on focus,
7344 // 'button' for trigger button, or 'both' for either
7345 showAnim: 'fadeIn', // Name of jQuery animation for popup
7346 showOptions: {}, // Options for enhanced animations
7347 defaultDate: null, // Used when field is blank: actual date,
7348 // +/-number for offset from today, null for today
7349 appendText: '', // Display text following the input box, e.g. showing the format
7350 buttonText: '...', // Text for trigger button
7351 buttonImage: '', // URL for trigger button image
7352 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7353 hideIfNoPrevNext: false, // True to hide next/previous month links
7354 // if not applicable, false to just disable them
7355 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7356 gotoCurrent: false, // True if today link goes back to current selection instead
7357 changeMonth: false, // True if month can be selected directly, false if only prev/next
7358 changeYear: false, // True if year can be selected directly, false if only prev/next
7359 yearRange: 'c-10:c+10', // Range of years to display in drop-down,
7360 // either relative to today's year (-nn:+nn), relative to currently displayed year
7361 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7362 showOtherMonths: false, // True to show dates in other months, false to leave blank
7363 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7364 showWeek: false, // True to show week of the year, false to not show it
7365 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7366 // takes a Date and returns the number of the week for it
7367 shortYearCutoff: '+10', // Short year values < this are in the current century,
7368 // > this are in the previous century,
7369 // string value starting with '+' for current year + value
7370 minDate: null, // The earliest selectable date, or null for no limit
7371 maxDate: null, // The latest selectable date, or null for no limit
7372 duration: 'fast', // Duration of display/closure
7373 beforeShowDay: null, // Function that takes a date and returns an array with
7374 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
7375 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
7376 beforeShow: null, // Function that takes an input field and
7377 // returns a set of custom settings for the date picker
7378 onSelect: null, // Define a callback function when a date is selected
7379 onChangeMonthYear: null, // Define a callback function when the month or year is changed
7380 onClose: null, // Define a callback function when the datepicker is closed
7381 numberOfMonths: 1, // Number of months to show at a time
7382 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7383 stepMonths: 1, // Number of months to step back/forward
7384 stepBigMonths: 12, // Number of months to step back/forward for the big links
7385 altField: '', // Selector for an alternate field to store selected dates into
7386 altFormat: '', // The date format to use for the alternate field
7387 constrainInput: true, // The input is constrained by the current date format
7388 showButtonPanel: false, // True to show button panel, false to not show it
7389 autoSize: false, // True to size the input for the date format, false to leave as is
7390 disabled: false // The initial disabled state
7391 };
7392 $.extend(this._defaults, this.regional['']);
7393 this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'));
7394 }
7395
7396 $.extend(Datepicker.prototype, {
7397 /* Class name added to elements to indicate already configured with a date picker. */
7398 markerClassName: 'hasDatepicker',
7399
7400 //Keep track of the maximum number of rows displayed (see #7043)
7401 maxRows: 4,
7402
7403 /* Debug logging (if enabled). */
7404 log: function () {
7405 if (this.debug)
7406 console.log.apply('', arguments);
7407 },
7408
7409 // TODO rename to "widget" when switching to widget factory
7410 _widgetDatepicker: function() {
7411 return this.dpDiv;
7412 },
7413
7414 /* Override the default settings for all instances of the date picker.
7415 @param settings object - the new settings to use as defaults (anonymous object)
7416 @return the manager object */
7417 setDefaults: function(settings) {
7418 extendRemove(this._defaults, settings || {});
7419 return this;
7420 },
7421
7422 /* Attach the date picker to a jQuery selection.
7423 @param target element - the target input field or division or span
7424 @param settings object - the new settings to use for this date picker instance (anonymous) */
7425 _attachDatepicker: function(target, settings) {
7426 // check for settings on the control itself - in namespace 'date:'
7427 var inlineSettings = null;
7428 for (var attrName in this._defaults) {
7429 var attrValue = target.getAttribute('date:' + attrName);
7430 if (attrValue) {
7431 inlineSettings = inlineSettings || {};
7432 try {
7433 inlineSettings[attrName] = eval(attrValue);
7434 } catch (err) {
7435 inlineSettings[attrName] = attrValue;
7436 }
7437 }
7438 }
7439 var nodeName = target.nodeName.toLowerCase();
7440 var inline = (nodeName == 'div' || nodeName == 'span');
7441 if (!target.id) {
7442 this.uuid += 1;
7443 target.id = 'dp' + this.uuid;
7444 }
7445 var inst = this._newInst($(target), inline);
7446 inst.settings = $.extend({}, settings || {}, inlineSettings || {});
7447 if (nodeName == 'input') {
7448 this._connectDatepicker(target, inst);
7449 } else if (inline) {
7450 this._inlineDatepicker(target, inst);
7451 }
7452 },
7453
7454 /* Create a new instance object. */
7455 _newInst: function(target, inline) {
7456 var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
7457 return {id: id, input: target, // associated target
7458 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7459 drawMonth: 0, drawYear: 0, // month being drawn
7460 inline: inline, // is datepicker inline or not
7461 dpDiv: (!inline ? this.dpDiv : // presentation div
7462 bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))};
7463 },
7464
7465 /* Attach the date picker to an input field. */
7466 _connectDatepicker: function(target, inst) {
7467 var input = $(target);
7468 inst.append = $([]);
7469 inst.trigger = $([]);
7470 if (input.hasClass(this.markerClassName))
7471 return;
7472 this._attachments(input, inst);
7473 input.addClass(this.markerClassName).keydown(this._doKeyDown).
7474 keypress(this._doKeyPress).keyup(this._doKeyUp).
7475 bind("setData.datepicker", function(event, key, value) {
7476 inst.settings[key] = value;
7477 }).bind("getData.datepicker", function(event, key) {
7478 return this._get(inst, key);
7479 });
7480 this._autoSize(inst);
7481 $.data(target, PROP_NAME, inst);
7482 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7483 if( inst.settings.disabled ) {
7484 this._disableDatepicker( target );
7485 }
7486 },
7487
7488 /* Make attachments based on settings. */
7489 _attachments: function(input, inst) {
7490 var appendText = this._get(inst, 'appendText');
7491 var isRTL = this._get(inst, 'isRTL');
7492 if (inst.append)
7493 inst.append.remove();
7494 if (appendText) {
7495 inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
7496 input[isRTL ? 'before' : 'after'](inst.append);
7497 }
7498 input.unbind('focus', this._showDatepicker);
7499 if (inst.trigger)
7500 inst.trigger.remove();
7501 var showOn = this._get(inst, 'showOn');
7502 if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
7503 input.focus(this._showDatepicker);
7504 if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
7505 var buttonText = this._get(inst, 'buttonText');
7506 var buttonImage = this._get(inst, 'buttonImage');
7507 inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
7508 $('<img/>').addClass(this._triggerClass).
7509 attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
7510 $('<button type="button"></button>').addClass(this._triggerClass).
7511 html(buttonImage == '' ? buttonText : $('<img/>').attr(
7512 { src:buttonImage, alt:buttonText, title:buttonText })));
7513 input[isRTL ? 'before' : 'after'](inst.trigger);
7514 inst.trigger.click(function() {
7515 if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
7516 $.datepicker._hideDatepicker();
7517 else
7518 $.datepicker._showDatepicker(input[0]);
7519 return false;
7520 });
7521 }
7522 },
7523
7524 /* Apply the maximum length for the date format. */
7525 _autoSize: function(inst) {
7526 if (this._get(inst, 'autoSize') && !inst.inline) {
7527 var date = new Date(2009, 12 - 1, 20); // Ensure double digits
7528 var dateFormat = this._get(inst, 'dateFormat');
7529 if (dateFormat.match(/[DM]/)) {
7530 var findMax = function(names) {
7531 var max = 0;
7532 var maxI = 0;
7533 for (var i = 0; i < names.length; i++) {
7534 if (names[i].length > max) {
7535 max = names[i].length;
7536 maxI = i;
7537 }
7538 }
7539 return maxI;
7540 };
7541 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
7542 'monthNames' : 'monthNamesShort'))));
7543 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
7544 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
7545 }
7546 inst.input.attr('size', this._formatDate(inst, date).length);
7547 }
7548 },
7549
7550 /* Attach an inline date picker to a div. */
7551 _inlineDatepicker: function(target, inst) {
7552 var divSpan = $(target);
7553 if (divSpan.hasClass(this.markerClassName))
7554 return;
7555 divSpan.addClass(this.markerClassName).append(inst.dpDiv).
7556 bind("setData.datepicker", function(event, key, value){
7557 inst.settings[key] = value;
7558 }).bind("getData.datepicker", function(event, key){
7559 return this._get(inst, key);
7560 });
7561 $.data(target, PROP_NAME, inst);
7562 this._setDate(inst, this._getDefaultDate(inst), true);
7563 this._updateDatepicker(inst);
7564 this._updateAlternate(inst);
7565 //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7566 if( inst.settings.disabled ) {
7567 this._disableDatepicker( target );
7568 }
7569 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7570 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7571 inst.dpDiv.css( "display", "block" );
7572 },
7573
7574 /* Pop-up the date picker in a "dialog" box.
7575 @param input element - ignored
7576 @param date string or Date - the initial date to display
7577 @param onSelect function - the function to call when a date is selected
7578 @param settings object - update the dialog date picker instance's settings (anonymous object)
7579 @param pos int[2] - coordinates for the dialog's position within the screen or
7580 event - with x/y coordinates or
7581 leave empty for default (screen centre)
7582 @return the manager object */
7583 _dialogDatepicker: function(input, date, onSelect, settings, pos) {
7584 var inst = this._dialogInst; // internal instance
7585 if (!inst) {
7586 this.uuid += 1;
7587 var id = 'dp' + this.uuid;
7588 this._dialogInput = $('<input type="text" id="' + id +
7589 '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
7590 this._dialogInput.keydown(this._doKeyDown);
7591 $('body').append(this._dialogInput);
7592 inst = this._dialogInst = this._newInst(this._dialogInput, false);
7593 inst.settings = {};
7594 $.data(this._dialogInput[0], PROP_NAME, inst);
7595 }
7596 extendRemove(inst.settings, settings || {});
7597 date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
7598 this._dialogInput.val(date);
7599
7600 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
7601 if (!this._pos) {
7602 var browserWidth = document.documentElement.clientWidth;
7603 var browserHeight = document.documentElement.clientHeight;
7604 var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7605 var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7606 this._pos = // should use actual width/height below
7607 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
7608 }
7609
7610 // move input on screen for focus, but hidden behind dialog
7611 this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
7612 inst.settings.onSelect = onSelect;
7613 this._inDialog = true;
7614 this.dpDiv.addClass(this._dialogClass);
7615 this._showDatepicker(this._dialogInput[0]);
7616 if ($.blockUI)
7617 $.blockUI(this.dpDiv);
7618 $.data(this._dialogInput[0], PROP_NAME, inst);
7619 return this;
7620 },
7621
7622 /* Detach a datepicker from its control.
7623 @param target element - the target input field or division or span */
7624 _destroyDatepicker: function(target) {
7625 var $target = $(target);
7626 var inst = $.data(target, PROP_NAME);
7627 if (!$target.hasClass(this.markerClassName)) {
7628 return;
7629 }
7630 var nodeName = target.nodeName.toLowerCase();
7631 $.removeData(target, PROP_NAME);
7632 if (nodeName == 'input') {
7633 inst.append.remove();
7634 inst.trigger.remove();
7635 $target.removeClass(this.markerClassName).
7636 unbind('focus', this._showDatepicker).
7637 unbind('keydown', this._doKeyDown).
7638 unbind('keypress', this._doKeyPress).
7639 unbind('keyup', this._doKeyUp);
7640 } else if (nodeName == 'div' || nodeName == 'span')
7641 $target.removeClass(this.markerClassName).empty();
7642 },
7643
7644 /* Enable the date picker to a jQuery selection.
7645 @param target element - the target input field or division or span */
7646 _enableDatepicker: function(target) {
7647 var $target = $(target);
7648 var inst = $.data(target, PROP_NAME);
7649 if (!$target.hasClass(this.markerClassName)) {
7650 return;
7651 }
7652 var nodeName = target.nodeName.toLowerCase();
7653 if (nodeName == 'input') {
7654 target.disabled = false;
7655 inst.trigger.filter('button').
7656 each(function() { this.disabled = false; }).end().
7657 filter('img').css({opacity: '1.0', cursor: ''});
7658 }
7659 else if (nodeName == 'div' || nodeName == 'span') {
7660 var inline = $target.children('.' + this._inlineClass);
7661 inline.children().removeClass('ui-state-disabled');
7662 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
7663 removeAttr("disabled");
7664 }
7665 this._disabledInputs = $.map(this._disabledInputs,
7666 function(value) { return (value == target ? null : value); }); // delete entry
7667 },
7668
7669 /* Disable the date picker to a jQuery selection.
7670 @param target element - the target input field or division or span */
7671 _disableDatepicker: function(target) {
7672 var $target = $(target);
7673 var inst = $.data(target, PROP_NAME);
7674 if (!$target.hasClass(this.markerClassName)) {
7675 return;
7676 }
7677 var nodeName = target.nodeName.toLowerCase();
7678 if (nodeName == 'input') {
7679 target.disabled = true;
7680 inst.trigger.filter('button').
7681 each(function() { this.disabled = true; }).end().
7682 filter('img').css({opacity: '0.5', cursor: 'default'});
7683 }
7684 else if (nodeName == 'div' || nodeName == 'span') {
7685 var inline = $target.children('.' + this._inlineClass);
7686 inline.children().addClass('ui-state-disabled');
7687 inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
7688 attr("disabled", "disabled");
7689 }
7690 this._disabledInputs = $.map(this._disabledInputs,
7691 function(value) { return (value == target ? null : value); }); // delete entry
7692 this._disabledInputs[this._disabledInputs.length] = target;
7693 },
7694
7695 /* Is the first field in a jQuery collection disabled as a datepicker?
7696 @param target element - the target input field or division or span
7697 @return boolean - true if disabled, false if enabled */
7698 _isDisabledDatepicker: function(target) {
7699 if (!target) {
7700 return false;
7701 }
7702 for (var i = 0; i < this._disabledInputs.length; i++) {
7703 if (this._disabledInputs[i] == target)
7704 return true;
7705 }
7706 return false;
7707 },
7708
7709 /* Retrieve the instance data for the target control.
7710 @param target element - the target input field or division or span
7711 @return object - the associated instance data
7712 @throws error if a jQuery problem getting data */
7713 _getInst: function(target) {
7714 try {
7715 return $.data(target, PROP_NAME);
7716 }
7717 catch (err) {
7718 throw 'Missing instance data for this datepicker';
7719 }
7720 },
7721
7722 /* Update or retrieve the settings for a date picker attached to an input field or division.
7723 @param target element - the target input field or division or span
7724 @param name object - the new settings to update or
7725 string - the name of the setting to change or retrieve,
7726 when retrieving also 'all' for all instance settings or
7727 'defaults' for all global defaults
7728 @param value any - the new value for the setting
7729 (omit if above is an object or to retrieve a value) */
7730 _optionDatepicker: function(target, name, value) {
7731 var inst = this._getInst(target);
7732 if (arguments.length == 2 && typeof name == 'string') {
7733 return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
7734 (inst ? (name == 'all' ? $.extend({}, inst.settings) :
7735 this._get(inst, name)) : null));
7736 }
7737 var settings = name || {};
7738 if (typeof name == 'string') {
7739 settings = {};
7740 settings[name] = value;
7741 }
7742 if (inst) {
7743 if (this._curInst == inst) {
7744 this._hideDatepicker();
7745 }
7746 var date = this._getDateDatepicker(target, true);
7747 var minDate = this._getMinMaxDate(inst, 'min');
7748 var maxDate = this._getMinMaxDate(inst, 'max');
7749 extendRemove(inst.settings, settings);
7750 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
7751 if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
7752 inst.settings.minDate = this._formatDate(inst, minDate);
7753 if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
7754 inst.settings.maxDate = this._formatDate(inst, maxDate);
7755 this._attachments($(target), inst);
7756 this._autoSize(inst);
7757 this._setDate(inst, date);
7758 this._updateAlternate(inst);
7759 this._updateDatepicker(inst);
7760 }
7761 },
7762
7763 // change method deprecated
7764 _changeDatepicker: function(target, name, value) {
7765 this._optionDatepicker(target, name, value);
7766 },
7767
7768 /* Redraw the date picker attached to an input field or division.
7769 @param target element - the target input field or division or span */
7770 _refreshDatepicker: function(target) {
7771 var inst = this._getInst(target);
7772 if (inst) {
7773 this._updateDatepicker(inst);
7774 }
7775 },
7776
7777 /* Set the dates for a jQuery selection.
7778 @param target element - the target input field or division or span
7779 @param date Date - the new date */
7780 _setDateDatepicker: function(target, date) {
7781 var inst = this._getInst(target);
7782 if (inst) {
7783 this._setDate(inst, date);
7784 this._updateDatepicker(inst);
7785 this._updateAlternate(inst);
7786 }
7787 },
7788
7789 /* Get the date(s) for the first entry in a jQuery selection.
7790 @param target element - the target input field or division or span
7791 @param noDefault boolean - true if no default date is to be used
7792 @return Date - the current date */
7793 _getDateDatepicker: function(target, noDefault) {
7794 var inst = this._getInst(target);
7795 if (inst && !inst.inline)
7796 this._setDateFromField(inst, noDefault);
7797 return (inst ? this._getDate(inst) : null);
7798 },
7799
7800 /* Handle keystrokes. */
7801 _doKeyDown: function(event) {
7802 var inst = $.datepicker._getInst(event.target);
7803 var handled = true;
7804 var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
7805 inst._keyEvent = true;
7806 if ($.datepicker._datepickerShowing)
7807 switch (event.keyCode) {
7808 case 9: $.datepicker._hideDatepicker();
7809 handled = false;
7810 break; // hide on tab out
7811 case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' +
7812 $.datepicker._currentClass + ')', inst.dpDiv);
7813 if (sel[0])
7814 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
7815 var onSelect = $.datepicker._get(inst, 'onSelect');
7816 if (onSelect) {
7817 var dateStr = $.datepicker._formatDate(inst);
7818
7819 // trigger custom callback
7820 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
7821 }
7822 else
7823 $.datepicker._hideDatepicker();
7824 return false; // don't submit the form
7825 break; // select the value on enter
7826 case 27: $.datepicker._hideDatepicker();
7827 break; // hide on escape
7828 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7829 -$.datepicker._get(inst, 'stepBigMonths') :
7830 -$.datepicker._get(inst, 'stepMonths')), 'M');
7831 break; // previous month/year on page up/+ ctrl
7832 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7833 +$.datepicker._get(inst, 'stepBigMonths') :
7834 +$.datepicker._get(inst, 'stepMonths')), 'M');
7835 break; // next month/year on page down/+ ctrl
7836 case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
7837 handled = event.ctrlKey || event.metaKey;
7838 break; // clear on ctrl or command +end
7839 case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
7840 handled = event.ctrlKey || event.metaKey;
7841 break; // current on ctrl or command +home
7842 case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
7843 handled = event.ctrlKey || event.metaKey;
7844 // -1 day on ctrl or command +left
7845 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7846 -$.datepicker._get(inst, 'stepBigMonths') :
7847 -$.datepicker._get(inst, 'stepMonths')), 'M');
7848 // next month/year on alt +left on Mac
7849 break;
7850 case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
7851 handled = event.ctrlKey || event.metaKey;
7852 break; // -1 week on ctrl or command +up
7853 case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
7854 handled = event.ctrlKey || event.metaKey;
7855 // +1 day on ctrl or command +right
7856 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7857 +$.datepicker._get(inst, 'stepBigMonths') :
7858 +$.datepicker._get(inst, 'stepMonths')), 'M');
7859 // next month/year on alt +right
7860 break;
7861 case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
7862 handled = event.ctrlKey || event.metaKey;
7863 break; // +1 week on ctrl or command +down
7864 default: handled = false;
7865 }
7866 else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
7867 $.datepicker._showDatepicker(this);
7868 else {
7869 handled = false;
7870 }
7871 if (handled) {
7872 event.preventDefault();
7873 event.stopPropagation();
7874 }
7875 },
7876
7877 /* Filter entered characters - based on date format. */
7878 _doKeyPress: function(event) {
7879 var inst = $.datepicker._getInst(event.target);
7880 if ($.datepicker._get(inst, 'constrainInput')) {
7881 var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
7882 var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
7883 return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
7884 }
7885 },
7886
7887 /* Synchronise manual entry and field/alternate field. */
7888 _doKeyUp: function(event) {
7889 var inst = $.datepicker._getInst(event.target);
7890 if (inst.input.val() != inst.lastVal) {
7891 try {
7892 var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
7893 (inst.input ? inst.input.val() : null),
7894 $.datepicker._getFormatConfig(inst));
7895 if (date) { // only if valid
7896 $.datepicker._setDateFromField(inst);
7897 $.datepicker._updateAlternate(inst);
7898 $.datepicker._updateDatepicker(inst);
7899 }
7900 }
7901 catch (event) {
7902 $.datepicker.log(event);
7903 }
7904 }
7905 return true;
7906 },
7907
7908 /* Pop-up the date picker for a given input field.
7909 If false returned from beforeShow event handler do not show.
7910 @param input element - the input field attached to the date picker or
7911 event - if triggered by focus */
7912 _showDatepicker: function(input) {
7913 input = input.target || input;
7914 if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
7915 input = $('input', input.parentNode)[0];
7916 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
7917 return;
7918 var inst = $.datepicker._getInst(input);
7919 if ($.datepicker._curInst && $.datepicker._curInst != inst) {
7920 if ( $.datepicker._datepickerShowing ) {
7921 $.datepicker._triggerOnClose($.datepicker._curInst);
7922 }
7923 $.datepicker._curInst.dpDiv.stop(true, true);
7924 }
7925 var beforeShow = $.datepicker._get(inst, 'beforeShow');
7926 var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
7927 if(beforeShowSettings === false){
7928 //false
7929 return;
7930 }
7931 extendRemove(inst.settings, beforeShowSettings);
7932 inst.lastVal = null;
7933 $.datepicker._lastInput = input;
7934 $.datepicker._setDateFromField(inst);
7935 if ($.datepicker._inDialog) // hide cursor
7936 input.value = '';
7937 if (!$.datepicker._pos) { // position below input
7938 $.datepicker._pos = $.datepicker._findPos(input);
7939 $.datepicker._pos[1] += input.offsetHeight; // add the height
7940 }
7941 var isFixed = false;
7942 $(input).parents().each(function() {
7943 isFixed |= $(this).css('position') == 'fixed';
7944 return !isFixed;
7945 });
7946 if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
7947 $.datepicker._pos[0] -= document.documentElement.scrollLeft;
7948 $.datepicker._pos[1] -= document.documentElement.scrollTop;
7949 }
7950 var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
7951 $.datepicker._pos = null;
7952 //to avoid flashes on Firefox
7953 inst.dpDiv.empty();
7954 // determine sizing offscreen
7955 inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
7956 $.datepicker._updateDatepicker(inst);
7957 // fix width for dynamic number of date pickers
7958 // and adjust position before showing
7959 offset = $.datepicker._checkOffset(inst, offset, isFixed);
7960 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
7961 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
7962 left: offset.left + 'px', top: offset.top + 'px'});
7963 if (!inst.inline) {
7964 var showAnim = $.datepicker._get(inst, 'showAnim');
7965 var duration = $.datepicker._get(inst, 'duration');
7966 var postProcess = function() {
7967 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
7968 if( !! cover.length ){
7969 var borders = $.datepicker._getBorders(inst.dpDiv);
7970 cover.css({left: -borders[0], top: -borders[1],
7971 width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
7972 }
7973 };
7974 inst.dpDiv.zIndex($(input).zIndex()+1);
7975 $.datepicker._datepickerShowing = true;
7976 if ($.effects && $.effects[showAnim])
7977 inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
7978 else
7979 inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
7980 if (!showAnim || !duration)
7981 postProcess();
7982 if (inst.input.is(':visible') && !inst.input.is(':disabled'))
7983 inst.input.focus();
7984 $.datepicker._curInst = inst;
7985 }
7986 },
7987
7988 /* Generate the date picker content. */
7989 _updateDatepicker: function(inst) {
7990 var self = this;
7991 self.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
7992 var borders = $.datepicker._getBorders(inst.dpDiv);
7993 instActive = inst; // for delegate hover events
7994 inst.dpDiv.empty().append(this._generateHTML(inst));
7995 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
7996 if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
7997 cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
7998 }
7999 inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();
8000 var numMonths = this._getNumberOfMonths(inst);
8001 var cols = numMonths[1];
8002 var width = 17;
8003 inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
8004 if (cols > 1)
8005 inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
8006 inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
8007 'Class']('ui-datepicker-multi');
8008 inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
8009 'Class']('ui-datepicker-rtl');
8010 if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
8011 // #6694 - don't focus the input if it's already focused
8012 // this breaks the change event in IE
8013 inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
8014 inst.input.focus();
8015 // deffered render of the years select (to avoid flashes on Firefox)
8016 if( inst.yearshtml ){
8017 var origyearshtml = inst.yearshtml;
8018 setTimeout(function(){
8019 //assure that inst.yearshtml didn't change.
8020 if( origyearshtml === inst.yearshtml && inst.yearshtml ){
8021 inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
8022 }
8023 origyearshtml = inst.yearshtml = null;
8024 }, 0);
8025 }
8026 },
8027
8028 /* Retrieve the size of left and top borders for an element.
8029 @param elem (jQuery object) the element of interest
8030 @return (number[2]) the left and top borders */
8031 _getBorders: function(elem) {
8032 var convert = function(value) {
8033 return {thin: 1, medium: 2, thick: 3}[value] || value;
8034 };
8035 return [parseFloat(convert(elem.css('border-left-width'))),
8036 parseFloat(convert(elem.css('border-top-width')))];
8037 },
8038
8039 /* Check positioning to remain on screen. */
8040 _checkOffset: function(inst, offset, isFixed) {
8041 var dpWidth = inst.dpDiv.outerWidth();
8042 var dpHeight = inst.dpDiv.outerHeight();
8043 var inputWidth = inst.input ? inst.input.outerWidth() : 0;
8044 var inputHeight = inst.input ? inst.input.outerHeight() : 0;
8045 var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
8046 var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
8047
8048 offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
8049 offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
8050 offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
8051
8052 // now check if datepicker is showing outside window viewport - move to a better place if so.
8053 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
8054 Math.abs(offset.left + dpWidth - viewWidth) : 0);
8055 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
8056 Math.abs(dpHeight + inputHeight) : 0);
8057
8058 return offset;
8059 },
8060
8061 /* Find an object's position on the screen. */
8062 _findPos: function(obj) {
8063 var inst = this._getInst(obj);
8064 var isRTL = this._get(inst, 'isRTL');
8065 while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
8066 obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
8067 }
8068 var position = $(obj).offset();
8069 return [position.left, position.top];
8070 },
8071
8072 /* Trigger custom callback of onClose. */
8073 _triggerOnClose: function(inst) {
8074 var onClose = this._get(inst, 'onClose');
8075 if (onClose)
8076 onClose.apply((inst.input ? inst.input[0] : null),
8077 [(inst.input ? inst.input.val() : ''), inst]);
8078 },
8079
8080 /* Hide the date picker from view.
8081 @param input element - the input field attached to the date picker */
8082 _hideDatepicker: function(input) {
8083 var inst = this._curInst;
8084 if (!inst || (input && inst != $.data(input, PROP_NAME)))
8085 return;
8086 if (this._datepickerShowing) {
8087 var showAnim = this._get(inst, 'showAnim');
8088 var duration = this._get(inst, 'duration');
8089 var postProcess = function() {
8090 $.datepicker._tidyDialog(inst);
8091 this._curInst = null;
8092 };
8093 if ($.effects && $.effects[showAnim])
8094 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
8095 else
8096 inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
8097 (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
8098 if (!showAnim)
8099 postProcess();
8100 $.datepicker._triggerOnClose(inst);
8101 this._datepickerShowing = false;
8102 this._lastInput = null;
8103 if (this._inDialog) {
8104 this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
8105 if ($.blockUI) {
8106 $.unblockUI();
8107 $('body').append(this.dpDiv);
8108 }
8109 }
8110 this._inDialog = false;
8111 }
8112 },
8113
8114 /* Tidy up after a dialog display. */
8115 _tidyDialog: function(inst) {
8116 inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
8117 },
8118
8119 /* Close date picker if clicked elsewhere. */
8120 _checkExternalClick: function(event) {
8121 if (!$.datepicker._curInst)
8122 return;
8123 var $target = $(event.target);
8124 if ($target[0].id != $.datepicker._mainDivId &&
8125 $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
8126 !$target.hasClass($.datepicker.markerClassName) &&
8127 !$target.hasClass($.datepicker._triggerClass) &&
8128 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
8129 $.datepicker._hideDatepicker();
8130 },
8131
8132 /* Adjust one of the date sub-fields. */
8133 _adjustDate: function(id, offset, period) {
8134 var target = $(id);
8135 var inst = this._getInst(target[0]);
8136 if (this._isDisabledDatepicker(target[0])) {
8137 return;
8138 }
8139 this._adjustInstDate(inst, offset +
8140 (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
8141 period);
8142 this._updateDatepicker(inst);
8143 },
8144
8145 /* Action for current link. */
8146 _gotoToday: function(id) {
8147 var target = $(id);
8148 var inst = this._getInst(target[0]);
8149 if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
8150 inst.selectedDay = inst.currentDay;
8151 inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8152 inst.drawYear = inst.selectedYear = inst.currentYear;
8153 }
8154 else {
8155 var date = new Date();
8156 inst.selectedDay = date.getDate();
8157 inst.drawMonth = inst.selectedMonth = date.getMonth();
8158 inst.drawYear = inst.selectedYear = date.getFullYear();
8159 }
8160 this._notifyChange(inst);
8161 this._adjustDate(target);
8162 },
8163
8164 /* Action for selecting a new month/year. */
8165 _selectMonthYear: function(id, select, period) {
8166 var target = $(id);
8167 var inst = this._getInst(target[0]);
8168 inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
8169 inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
8170 parseInt(select.options[select.selectedIndex].value,10);
8171 this._notifyChange(inst);
8172 this._adjustDate(target);
8173 },
8174
8175 /* Action for selecting a day. */
8176 _selectDay: function(id, month, year, td) {
8177 var target = $(id);
8178 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
8179 return;
8180 }
8181 var inst = this._getInst(target[0]);
8182 inst.selectedDay = inst.currentDay = $('a', td).html();
8183 inst.selectedMonth = inst.currentMonth = month;
8184 inst.selectedYear = inst.currentYear = year;
8185 this._selectDate(id, this._formatDate(inst,
8186 inst.currentDay, inst.currentMonth, inst.currentYear));
8187 },
8188
8189 /* Erase the input field and hide the date picker. */
8190 _clearDate: function(id) {
8191 var target = $(id);
8192 var inst = this._getInst(target[0]);
8193 this._selectDate(target, '');
8194 },
8195
8196 /* Update the input field with the selected date. */
8197 _selectDate: function(id, dateStr) {
8198 var target = $(id);
8199 var inst = this._getInst(target[0]);
8200 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
8201 if (inst.input)
8202 inst.input.val(dateStr);
8203 this._updateAlternate(inst);
8204 var onSelect = this._get(inst, 'onSelect');
8205 if (onSelect)
8206 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
8207 else if (inst.input)
8208 inst.input.trigger('change'); // fire the change event
8209 if (inst.inline)
8210 this._updateDatepicker(inst);
8211 else {
8212 this._hideDatepicker();
8213 this._lastInput = inst.input[0];
8214 if (typeof(inst.input[0]) != 'object')
8215 inst.input.focus(); // restore focus
8216 this._lastInput = null;
8217 }
8218 },
8219
8220 /* Update any alternate field to synchronise with the main field. */
8221 _updateAlternate: function(inst) {
8222 var altField = this._get(inst, 'altField');
8223 if (altField) { // update alternate field too
8224 var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
8225 var date = this._getDate(inst);
8226 var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
8227 $(altField).each(function() { $(this).val(dateStr); });
8228 }
8229 },
8230
8231 /* Set as beforeShowDay function to prevent selection of weekends.
8232 @param date Date - the date to customise
8233 @return [boolean, string] - is this date selectable?, what is its CSS class? */
8234 noWeekends: function(date) {
8235 var day = date.getDay();
8236 return [(day > 0 && day < 6), ''];
8237 },
8238
8239 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8240 @param date Date - the date to get the week for
8241 @return number - the number of the week within the year that contains this date */
8242 iso8601Week: function(date) {
8243 var checkDate = new Date(date.getTime());
8244 // Find Thursday of this week starting on Monday
8245 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
8246 var time = checkDate.getTime();
8247 checkDate.setMonth(0); // Compare with Jan 1
8248 checkDate.setDate(1);
8249 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
8250 },
8251
8252 /* Parse a string value into a date object.
8253 See formatDate below for the possible formats.
8254
8255 @param format string - the expected format of the date
8256 @param value string - the date in the above format
8257 @param settings Object - attributes include:
8258 shortYearCutoff number - the cutoff year for determining the century (optional)
8259 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8260 dayNames string[7] - names of the days from Sunday (optional)
8261 monthNamesShort string[12] - abbreviated names of the months (optional)
8262 monthNames string[12] - names of the months (optional)
8263 @return Date - the extracted date value or null if value is blank */
8264 parseDate: function (format, value, settings) {
8265 if (format == null || value == null)
8266 throw 'Invalid arguments';
8267 value = (typeof value == 'object' ? value.toString() : value + '');
8268 if (value == '')
8269 return null;
8270 var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
8271 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
8272 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
8273 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
8274 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
8275 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
8276 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
8277 var year = -1;
8278 var month = -1;
8279 var day = -1;
8280 var doy = -1;
8281 var literal = false;
8282 // Check whether a format character is doubled
8283 var lookAhead = function(match) {
8284 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
8285 if (matches)
8286 iFormat++;
8287 return matches;
8288 };
8289 // Extract a number from the string value
8290 var getNumber = function(match) {
8291 var isDoubled = lookAhead(match);
8292 var size = (match == '@' ? 14 : (match == '!' ? 20 :
8293 (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
8294 var digits = new RegExp('^\\d{1,' + size + '}');
8295 var num = value.substring(iValue).match(digits);
8296 if (!num)
8297 throw 'Missing number at position ' + iValue;
8298 iValue += num[0].length;
8299 return parseInt(num[0], 10);
8300 };
8301 // Extract a name from the string value and convert to an index
8302 var getName = function(match, shortNames, longNames) {
8303 var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
8304 return [ [k, v] ];
8305 }).sort(function (a, b) {
8306 return -(a[1].length - b[1].length);
8307 });
8308 var index = -1;
8309 $.each(names, function (i, pair) {
8310 var name = pair[1];
8311 if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {
8312 index = pair[0];
8313 iValue += name.length;
8314 return false;
8315 }
8316 });
8317 if (index != -1)
8318 return index + 1;
8319 else
8320 throw 'Unknown name at position ' + iValue;
8321 };
8322 // Confirm that a literal character matches the string value
8323 var checkLiteral = function() {
8324 if (value.charAt(iValue) != format.charAt(iFormat))
8325 throw 'Unexpected literal at position ' + iValue;
8326 iValue++;
8327 };
8328 var iValue = 0;
8329 for (var iFormat = 0; iFormat < format.length; iFormat++) {
8330 if (literal)
8331 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
8332 literal = false;
8333 else
8334 checkLiteral();
8335 else
8336 switch (format.charAt(iFormat)) {
8337 case 'd':
8338 day = getNumber('d');
8339 break;
8340 case 'D':
8341 getName('D', dayNamesShort, dayNames);
8342 break;
8343 case 'o':
8344 doy = getNumber('o');
8345 break;
8346 case 'm':
8347 month = getNumber('m');
8348 break;
8349 case 'M':
8350 month = getName('M', monthNamesShort, monthNames);
8351 break;
8352 case 'y':
8353 year = getNumber('y');
8354 break;
8355 case '@':
8356 var date = new Date(getNumber('@'));
8357 year = date.getFullYear();
8358 month = date.getMonth() + 1;
8359 day = date.getDate();
8360 break;
8361 case '!':
8362 var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
8363 year = date.getFullYear();
8364 month = date.getMonth() + 1;
8365 day = date.getDate();
8366 break;
8367 case "'":
8368 if (lookAhead("'"))
8369 checkLiteral();
8370 else
8371 literal = true;
8372 break;
8373 default:
8374 checkLiteral();
8375 }
8376 }
8377 if (iValue < value.length){
8378 throw "Extra/unparsed characters found in date: " + value.substring(iValue);
8379 }
8380 if (year == -1)
8381 year = new Date().getFullYear();
8382 else if (year < 100)
8383 year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8384 (year <= shortYearCutoff ? 0 : -100);
8385 if (doy > -1) {
8386 month = 1;
8387 day = doy;
8388 do {
8389 var dim = this._getDaysInMonth(year, month - 1);
8390 if (day <= dim)
8391 break;
8392 month++;
8393 day -= dim;
8394 } while (true);
8395 }
8396 var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
8397 if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
8398 throw 'Invalid date'; // E.g. 31/02/00
8399 return date;
8400 },
8401
8402 /* Standard date formats. */
8403 ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
8404 COOKIE: 'D, dd M yy',
8405 ISO_8601: 'yy-mm-dd',
8406 RFC_822: 'D, d M y',
8407 RFC_850: 'DD, dd-M-y',
8408 RFC_1036: 'D, d M y',
8409 RFC_1123: 'D, d M yy',
8410 RFC_2822: 'D, d M yy',
8411 RSS: 'D, d M y', // RFC 822
8412 TICKS: '!',
8413 TIMESTAMP: '@',
8414 W3C: 'yy-mm-dd', // ISO 8601
8415
8416 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
8417 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
8418
8419 /* Format a date object into a string value.
8420 The format can be combinations of the following:
8421 d - day of month (no leading zero)
8422 dd - day of month (two digit)
8423 o - day of year (no leading zeros)
8424 oo - day of year (three digit)
8425 D - day name short
8426 DD - day name long
8427 m - month of year (no leading zero)
8428 mm - month of year (two digit)
8429 M - month name short
8430 MM - month name long
8431 y - year (two digit)
8432 yy - year (four digit)
8433 @ - Unix timestamp (ms since 01/01/1970)
8434 ! - Windows ticks (100ns since 01/01/0001)
8435 '...' - literal text
8436 '' - single quote
8437
8438 @param format string - the desired format of the date
8439 @param date Date - the date value to format
8440 @param settings Object - attributes include:
8441 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8442 dayNames string[7] - names of the days from Sunday (optional)
8443 monthNamesShort string[12] - abbreviated names of the months (optional)
8444 monthNames string[12] - names of the months (optional)
8445 @return string - the date in the above format */
8446 formatDate: function (format, date, settings) {
8447 if (!date)
8448 return '';
8449 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
8450 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
8451 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
8452 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
8453 // Check whether a format character is doubled
8454 var lookAhead = function(match) {
8455 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
8456 if (matches)
8457 iFormat++;
8458 return matches;
8459 };
8460 // Format a number, with leading zero if necessary
8461 var formatNumber = function(match, value, len) {
8462 var num = '' + value;
8463 if (lookAhead(match))
8464 while (num.length < len)
8465 num = '0' + num;
8466 return num;
8467 };
8468 // Format a name, short or long as requested
8469 var formatName = function(match, value, shortNames, longNames) {
8470 return (lookAhead(match) ? longNames[value] : shortNames[value]);
8471 };
8472 var output = '';
8473 var literal = false;
8474 if (date)
8475 for (var iFormat = 0; iFormat < format.length; iFormat++) {
8476 if (literal)
8477 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
8478 literal = false;
8479 else
8480 output += format.charAt(iFormat);
8481 else
8482 switch (format.charAt(iFormat)) {
8483 case 'd':
8484 output += formatNumber('d', date.getDate(), 2);
8485 break;
8486 case 'D':
8487 output += formatName('D', date.getDay(), dayNamesShort, dayNames);
8488 break;
8489 case 'o':
8490 output += formatNumber('o',
8491 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
8492 break;
8493 case 'm':
8494 output += formatNumber('m', date.getMonth() + 1, 2);
8495 break;
8496 case 'M':
8497 output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
8498 break;
8499 case 'y':
8500 output += (lookAhead('y') ? date.getFullYear() :
8501 (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
8502 break;
8503 case '@':
8504 output += date.getTime();
8505 break;
8506 case '!':
8507 output += date.getTime() * 10000 + this._ticksTo1970;
8508 break;
8509 case "'":
8510 if (lookAhead("'"))
8511 output += "'";
8512 else
8513 literal = true;
8514 break;
8515 default:
8516 output += format.charAt(iFormat);
8517 }
8518 }
8519 return output;
8520 },
8521
8522 /* Extract all possible characters from the date format. */
8523 _possibleChars: function (format) {
8524 var chars = '';
8525 var literal = false;
8526 // Check whether a format character is doubled
8527 var lookAhead = function(match) {
8528 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
8529 if (matches)
8530 iFormat++;
8531 return matches;
8532 };
8533 for (var iFormat = 0; iFormat < format.length; iFormat++)
8534 if (literal)
8535 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
8536 literal = false;
8537 else
8538 chars += format.charAt(iFormat);
8539 else
8540 switch (format.charAt(iFormat)) {
8541 case 'd': case 'm': case 'y': case '@':
8542 chars += '0123456789';
8543 break;
8544 case 'D': case 'M':
8545 return null; // Accept anything
8546 case "'":
8547 if (lookAhead("'"))
8548 chars += "'";
8549 else
8550 literal = true;
8551 break;
8552 default:
8553 chars += format.charAt(iFormat);
8554 }
8555 return chars;
8556 },
8557
8558 /* Get a setting value, defaulting if necessary. */
8559 _get: function(inst, name) {
8560 return inst.settings[name] !== undefined ?
8561 inst.settings[name] : this._defaults[name];
8562 },
8563
8564 /* Parse existing date and initialise date picker. */
8565 _setDateFromField: function(inst, noDefault) {
8566 if (inst.input.val() == inst.lastVal) {
8567 return;
8568 }
8569 var dateFormat = this._get(inst, 'dateFormat');
8570 var dates = inst.lastVal = inst.input ? inst.input.val() : null;
8571 var date, defaultDate;
8572 date = defaultDate = this._getDefaultDate(inst);
8573 var settings = this._getFormatConfig(inst);
8574 try {
8575 date = this.parseDate(dateFormat, dates, settings) || defaultDate;
8576 } catch (event) {
8577 this.log(event);
8578 dates = (noDefault ? '' : dates);
8579 }
8580 inst.selectedDay = date.getDate();
8581 inst.drawMonth = inst.selectedMonth = date.getMonth();
8582 inst.drawYear = inst.selectedYear = date.getFullYear();
8583 inst.currentDay = (dates ? date.getDate() : 0);
8584 inst.currentMonth = (dates ? date.getMonth() : 0);
8585 inst.currentYear = (dates ? date.getFullYear() : 0);
8586 this._adjustInstDate(inst);
8587 },
8588
8589 /* Retrieve the default date shown on opening. */
8590 _getDefaultDate: function(inst) {
8591 return this._restrictMinMax(inst,
8592 this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
8593 },
8594
8595 /* A date may be specified as an exact value or a relative one. */
8596 _determineDate: function(inst, date, defaultDate) {
8597 var offsetNumeric = function(offset) {
8598 var date = new Date();
8599 date.setDate(date.getDate() + offset);
8600 return date;
8601 };
8602 var offsetString = function(offset) {
8603 try {
8604 return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
8605 offset, $.datepicker._getFormatConfig(inst));
8606 }
8607 catch (e) {
8608 // Ignore
8609 }
8610 var date = (offset.toLowerCase().match(/^c/) ?
8611 $.datepicker._getDate(inst) : null) || new Date();
8612 var year = date.getFullYear();
8613 var month = date.getMonth();
8614 var day = date.getDate();
8615 var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
8616 var matches = pattern.exec(offset);
8617 while (matches) {
8618 switch (matches[2] || 'd') {
8619 case 'd' : case 'D' :
8620 day += parseInt(matches[1],10); break;
8621 case 'w' : case 'W' :
8622 day += parseInt(matches[1],10) * 7; break;
8623 case 'm' : case 'M' :
8624 month += parseInt(matches[1],10);
8625 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
8626 break;
8627 case 'y': case 'Y' :
8628 year += parseInt(matches[1],10);
8629 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
8630 break;
8631 }
8632 matches = pattern.exec(offset);
8633 }
8634 return new Date(year, month, day);
8635 };
8636 var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
8637 (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
8638 newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
8639 if (newDate) {
8640 newDate.setHours(0);
8641 newDate.setMinutes(0);
8642 newDate.setSeconds(0);
8643 newDate.setMilliseconds(0);
8644 }
8645 return this._daylightSavingAdjust(newDate);
8646 },
8647
8648 /* Handle switch to/from daylight saving.
8649 Hours may be non-zero on daylight saving cut-over:
8650 > 12 when midnight changeover, but then cannot generate
8651 midnight datetime, so jump to 1AM, otherwise reset.
8652 @param date (Date) the date to check
8653 @return (Date) the corrected date */
8654 _daylightSavingAdjust: function(date) {
8655 if (!date) return null;
8656 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
8657 return date;
8658 },
8659
8660 /* Set the date(s) directly. */
8661 _setDate: function(inst, date, noChange) {
8662 var clear = !date;
8663 var origMonth = inst.selectedMonth;
8664 var origYear = inst.selectedYear;
8665 var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
8666 inst.selectedDay = inst.currentDay = newDate.getDate();
8667 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
8668 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
8669 if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
8670 this._notifyChange(inst);
8671 this._adjustInstDate(inst);
8672 if (inst.input) {
8673 inst.input.val(clear ? '' : this._formatDate(inst));
8674 }
8675 },
8676
8677 /* Retrieve the date(s) directly. */
8678 _getDate: function(inst) {
8679 var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
8680 this._daylightSavingAdjust(new Date(
8681 inst.currentYear, inst.currentMonth, inst.currentDay)));
8682 return startDate;
8683 },
8684
8685 /* Generate the HTML for the current state of the date picker. */
8686 _generateHTML: function(inst) {
8687 var today = new Date();
8688 today = this._daylightSavingAdjust(
8689 new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
8690 var isRTL = this._get(inst, 'isRTL');
8691 var showButtonPanel = this._get(inst, 'showButtonPanel');
8692 var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
8693 var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
8694 var numMonths = this._getNumberOfMonths(inst);
8695 var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
8696 var stepMonths = this._get(inst, 'stepMonths');
8697 var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
8698 var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
8699 new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
8700 var minDate = this._getMinMaxDate(inst, 'min');
8701 var maxDate = this._getMinMaxDate(inst, 'max');
8702 var drawMonth = inst.drawMonth - showCurrentAtPos;
8703 var drawYear = inst.drawYear;
8704 if (drawMonth < 0) {
8705 drawMonth += 12;
8706 drawYear--;
8707 }
8708 if (maxDate) {
8709 var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
8710 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
8711 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
8712 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
8713 drawMonth--;
8714 if (drawMonth < 0) {
8715 drawMonth = 11;
8716 drawYear--;
8717 }
8718 }
8719 }
8720 inst.drawMonth = drawMonth;
8721 inst.drawYear = drawYear;
8722 var prevText = this._get(inst, 'prevText');
8723 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
8724 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
8725 this._getFormatConfig(inst)));
8726 var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
8727 '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
8728 '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
8729 ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
8730 (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>'));
8731 var nextText = this._get(inst, 'nextText');
8732 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
8733 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
8734 this._getFormatConfig(inst)));
8735 var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
8736 '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
8737 '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
8738 ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
8739 (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>'));
8740 var currentText = this._get(inst, 'currentText');
8741 var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
8742 currentText = (!navigationAsDateFormat ? currentText :
8743 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
8744 var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
8745 '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
8746 var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
8747 (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
8748 '.datepicker._gotoToday(\'#' + inst.id + '\');"' +
8749 '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
8750 var firstDay = parseInt(this._get(inst, 'firstDay'),10);
8751 firstDay = (isNaN(firstDay) ? 0 : firstDay);
8752 var showWeek = this._get(inst, 'showWeek');
8753 var dayNames = this._get(inst, 'dayNames');
8754 var dayNamesShort = this._get(inst, 'dayNamesShort');
8755 var dayNamesMin = this._get(inst, 'dayNamesMin');
8756 var monthNames = this._get(inst, 'monthNames');
8757 var monthNamesShort = this._get(inst, 'monthNamesShort');
8758 var beforeShowDay = this._get(inst, 'beforeShowDay');
8759 var showOtherMonths = this._get(inst, 'showOtherMonths');
8760 var selectOtherMonths = this._get(inst, 'selectOtherMonths');
8761 var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
8762 var defaultDate = this._getDefaultDate(inst);
8763 var html = '';
8764 for (var row = 0; row < numMonths[0]; row++) {
8765 var group = '';
8766 this.maxRows = 4;
8767 for (var col = 0; col < numMonths[1]; col++) {
8768 var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
8769 var cornerClass = ' ui-corner-all';
8770 var calender = '';
8771 if (isMultiMonth) {
8772 calender += '<div class="ui-datepicker-group';
8773 if (numMonths[1] > 1)
8774 switch (col) {
8775 case 0: calender += ' ui-datepicker-group-first';
8776 cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
8777 case numMonths[1]-1: calender += ' ui-datepicker-group-last';
8778 cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
8779 default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
8780 }
8781 calender += '">';
8782 }
8783 calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
8784 (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
8785 (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
8786 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
8787 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
8788 '</div><table class="ui-datepicker-calendar"><thead>' +
8789 '<tr>';
8790 var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
8791 for (var dow = 0; dow < 7; dow++) { // days of the week
8792 var day = (dow + firstDay) % 7;
8793 thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
8794 '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
8795 }
8796 calender += thead + '</tr></thead><tbody>';
8797 var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
8798 if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
8799 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
8800 var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
8801 var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
8802 var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
8803 this.maxRows = numRows;
8804 var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
8805 for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
8806 calender += '<tr>';
8807 var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
8808 this._get(inst, 'calculateWeek')(printDate) + '</td>');
8809 for (var dow = 0; dow < 7; dow++) { // create date picker days
8810 var daySettings = (beforeShowDay ?
8811 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
8812 var otherMonth = (printDate.getMonth() != drawMonth);
8813 var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
8814 (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
8815 tbody += '<td class="' +
8816 ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
8817 (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
8818 ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
8819 (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
8820 // or defaultDate is current printedDate and defaultDate is selectedDate
8821 ' ' + this._dayOverClass : '') + // highlight selected day
8822 (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
8823 (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
8824 (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
8825 (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
8826 ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
8827 (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
8828 inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
8829 (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
8830 (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
8831 (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
8832 (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
8833 (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
8834 '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
8835 printDate.setDate(printDate.getDate() + 1);
8836 printDate = this._daylightSavingAdjust(printDate);
8837 }
8838 calender += tbody + '</tr>';
8839 }
8840 drawMonth++;
8841 if (drawMonth > 11) {
8842 drawMonth = 0;
8843 drawYear++;
8844 }
8845 calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
8846 ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
8847 group += calender;
8848 }
8849 html += group;
8850 }
8851 html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
8852 '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
8853 inst._keyEvent = false;
8854 return html;
8855 },
8856
8857 /* Generate the month and year header. */
8858 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
8859 secondary, monthNames, monthNamesShort) {
8860 var changeMonth = this._get(inst, 'changeMonth');
8861 var changeYear = this._get(inst, 'changeYear');
8862 var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
8863 var html = '<div class="ui-datepicker-title">';
8864 var monthHtml = '';
8865 // month selection
8866 if (secondary || !changeMonth)
8867 monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
8868 else {
8869 var inMinYear = (minDate && minDate.getFullYear() == drawYear);
8870 var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
8871 monthHtml += '<select class="ui-datepicker-month" ' +
8872 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
8873 '>';
8874 for (var month = 0; month < 12; month++) {
8875 if ((!inMinYear || month >= minDate.getMonth()) &&
8876 (!inMaxYear || month <= maxDate.getMonth()))
8877 monthHtml += '<option value="' + month + '"' +
8878 (month == drawMonth ? ' selected="selected"' : '') +
8879 '>' + monthNamesShort[month] + '</option>';
8880 }
8881 monthHtml += '</select>';
8882 }
8883 if (!showMonthAfterYear)
8884 html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
8885 // year selection
8886 if ( !inst.yearshtml ) {
8887 inst.yearshtml = '';
8888 if (secondary || !changeYear)
8889 html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
8890 else {
8891 // determine range of years to display
8892 var years = this._get(inst, 'yearRange').split(':');
8893 var thisYear = new Date().getFullYear();
8894 var determineYear = function(value) {
8895 var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
8896 (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
8897 parseInt(value, 10)));
8898 return (isNaN(year) ? thisYear : year);
8899 };
8900 var year = determineYear(years[0]);
8901 var endYear = Math.max(year, determineYear(years[1] || ''));
8902 year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
8903 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
8904 inst.yearshtml += '<select class="ui-datepicker-year" ' +
8905 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
8906 '>';
8907 for (; year <= endYear; year++) {
8908 inst.yearshtml += '<option value="' + year + '"' +
8909 (year == drawYear ? ' selected="selected"' : '') +
8910 '>' + year + '</option>';
8911 }
8912 inst.yearshtml += '</select>';
8913
8914 html += inst.yearshtml;
8915 inst.yearshtml = null;
8916 }
8917 }
8918 html += this._get(inst, 'yearSuffix');
8919 if (showMonthAfterYear)
8920 html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
8921 html += '</div>'; // Close datepicker_header
8922 return html;
8923 },
8924
8925 /* Adjust one of the date sub-fields. */
8926 _adjustInstDate: function(inst, offset, period) {
8927 var year = inst.drawYear + (period == 'Y' ? offset : 0);
8928 var month = inst.drawMonth + (period == 'M' ? offset : 0);
8929 var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
8930 (period == 'D' ? offset : 0);
8931 var date = this._restrictMinMax(inst,
8932 this._daylightSavingAdjust(new Date(year, month, day)));
8933 inst.selectedDay = date.getDate();
8934 inst.drawMonth = inst.selectedMonth = date.getMonth();
8935 inst.drawYear = inst.selectedYear = date.getFullYear();
8936 if (period == 'M' || period == 'Y')
8937 this._notifyChange(inst);
8938 },
8939
8940 /* Ensure a date is within any min/max bounds. */
8941 _restrictMinMax: function(inst, date) {
8942 var minDate = this._getMinMaxDate(inst, 'min');
8943 var maxDate = this._getMinMaxDate(inst, 'max');
8944 var newDate = (minDate && date < minDate ? minDate : date);
8945 newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
8946 return newDate;
8947 },
8948
8949 /* Notify change of month/year. */
8950 _notifyChange: function(inst) {
8951 var onChange = this._get(inst, 'onChangeMonthYear');
8952 if (onChange)
8953 onChange.apply((inst.input ? inst.input[0] : null),
8954 [inst.selectedYear, inst.selectedMonth + 1, inst]);
8955 },
8956
8957 /* Determine the number of months to show. */
8958 _getNumberOfMonths: function(inst) {
8959 var numMonths = this._get(inst, 'numberOfMonths');
8960 return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
8961 },
8962
8963 /* Determine the current maximum date - ensure no time components are set. */
8964 _getMinMaxDate: function(inst, minMax) {
8965 return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
8966 },
8967
8968 /* Find the number of days in a given month. */
8969 _getDaysInMonth: function(year, month) {
8970 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
8971 },
8972
8973 /* Find the day of the week of the first of a month. */
8974 _getFirstDayOfMonth: function(year, month) {
8975 return new Date(year, month, 1).getDay();
8976 },
8977
8978 /* Determines if we should allow a "next/prev" month display change. */
8979 _canAdjustMonth: function(inst, offset, curYear, curMonth) {
8980 var numMonths = this._getNumberOfMonths(inst);
8981 var date = this._daylightSavingAdjust(new Date(curYear,
8982 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
8983 if (offset < 0)
8984 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
8985 return this._isInRange(inst, date);
8986 },
8987
8988 /* Is the given date in the accepted range? */
8989 _isInRange: function(inst, date) {
8990 var minDate = this._getMinMaxDate(inst, 'min');
8991 var maxDate = this._getMinMaxDate(inst, 'max');
8992 return ((!minDate || date.getTime() >= minDate.getTime()) &&
8993 (!maxDate || date.getTime() <= maxDate.getTime()));
8994 },
8995
8996 /* Provide the configuration settings for formatting/parsing. */
8997 _getFormatConfig: function(inst) {
8998 var shortYearCutoff = this._get(inst, 'shortYearCutoff');
8999 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
9000 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
9001 return {shortYearCutoff: shortYearCutoff,
9002 dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
9003 monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
9004 },
9005
9006 /* Format the given date for display. */
9007 _formatDate: function(inst, day, month, year) {
9008 if (!day) {
9009 inst.currentDay = inst.selectedDay;
9010 inst.currentMonth = inst.selectedMonth;
9011 inst.currentYear = inst.selectedYear;
9012 }
9013 var date = (day ? (typeof day == 'object' ? day :
9014 this._daylightSavingAdjust(new Date(year, month, day))) :
9015 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
9016 return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
9017 }
9018 });
9019
9020 /*
9021 * Bind hover events for datepicker elements.
9022 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9023 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9024 */
9025 function bindHover(dpDiv) {
9026 var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
9027 return dpDiv.bind('mouseout', function(event) {
9028 var elem = $( event.target ).closest( selector );
9029 if ( !elem.length ) {
9030 return;
9031 }
9032 elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" );
9033 })
9034 .bind('mouseover', function(event) {
9035 var elem = $( event.target ).closest( selector );
9036 if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) ||
9037 !elem.length ) {
9038 return;
9039 }
9040 elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
9041 elem.addClass('ui-state-hover');
9042 if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover');
9043 if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover');
9044 });
9045 }
9046
9047 /* jQuery extend now ignores nulls! */
9048 function extendRemove(target, props) {
9049 $.extend(target, props);
9050 for (var name in props)
9051 if (props[name] == null || props[name] == undefined)
9052 target[name] = props[name];
9053 return target;
9054 };
9055
9056 /* Determine whether an object is an array. */
9057 function isArray(a) {
9058 return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
9059 (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
9060 };
9061
9062 /* Invoke the datepicker functionality.
9063 @param options string - a command, optionally followed by additional parameters or
9064 Object - settings for attaching new datepicker functionality
9065 @return jQuery object */
9066 $.fn.datepicker = function(options){
9067
9068 /* Verify an empty collection wasn't passed - Fixes #6976 */
9069 if ( !this.length ) {
9070 return this;
9071 }
9072
9073 /* Initialise the date picker. */
9074 if (!$.datepicker.initialized) {
9075 $(document).mousedown($.datepicker._checkExternalClick).
9076 find('body').append($.datepicker.dpDiv);
9077 $.datepicker.initialized = true;
9078 }
9079
9080 var otherArgs = Array.prototype.slice.call(arguments, 1);
9081 if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
9082 return $.datepicker['_' + options + 'Datepicker'].
9083 apply($.datepicker, [this[0]].concat(otherArgs));
9084 if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
9085 return $.datepicker['_' + options + 'Datepicker'].
9086 apply($.datepicker, [this[0]].concat(otherArgs));
9087 return this.each(function() {
9088 typeof options == 'string' ?
9089 $.datepicker['_' + options + 'Datepicker'].
9090 apply($.datepicker, [this].concat(otherArgs)) :
9091 $.datepicker._attachDatepicker(this, options);
9092 });
9093 };
9094
9095 $.datepicker = new Datepicker(); // singleton instance
9096 $.datepicker.initialized = false;
9097 $.datepicker.uuid = new Date().getTime();
9098 $.datepicker.version = "1.8.16";
9099
9100 // Workaround for #4055
9101 // Add another global to avoid noConflict issues with inline event handlers
9102 window['DP_jQuery_' + dpuuid] = $;
9103
9104 })(jQuery);
9105 /*
9106 * jQuery UI Dialog 1.8.16
9107 *
9108 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
9109 * Dual licensed under the MIT or GPL Version 2 licenses.
9110 * http://jquery.org/license
9111 *
9112 * http://docs.jquery.com/UI/Dialog
9113 *
9114 * Depends:
9115 * jquery.ui.core.js
9116 * jquery.ui.widget.js
9117 * jquery.ui.button.js
9118 * jquery.ui.draggable.js
9119 * jquery.ui.mouse.js
9120 * jquery.ui.position.js
9121 * jquery.ui.resizable.js
9122 */
9123 (function( $, undefined ) {
9124
9125 var uiDialogClasses =
9126 'ui-dialog ' +
9127 'ui-widget ' +
9128 'ui-widget-content ' +
9129 'ui-corner-all ',
9130 sizeRelatedOptions = {
9131 buttons: true,
9132 height: true,
9133 maxHeight: true,
9134 maxWidth: true,
9135 minHeight: true,
9136 minWidth: true,
9137 width: true
9138 },
9139 resizableRelatedOptions = {
9140 maxHeight: true,
9141 maxWidth: true,
9142 minHeight: true,
9143 minWidth: true
9144 },
9145 // support for jQuery 1.3.2 - handle common attrFn methods for dialog
9146 attrFn = $.attrFn || {
9147 val: true,
9148 css: true,
9149 html: true,
9150 text: true,
9151 data: true,
9152 width: true,
9153 height: true,
9154 offset: true,
9155 click: true
9156 };
9157
9158 $.widget("ui.dialog", {
9159 options: {
9160 autoOpen: true,
9161 buttons: {},
9162 closeOnEscape: true,
9163 closeText: 'close',
9164 dialogClass: '',
9165 draggable: true,
9166 hide: null,
9167 height: 'auto',
9168 maxHeight: false,
9169 maxWidth: false,
9170 minHeight: 150,
9171 minWidth: 150,
9172 modal: false,
9173 position: {
9174 my: 'center',
9175 at: 'center',
9176 collision: 'fit',
9177 // ensure that the titlebar is never outside the document
9178 using: function(pos) {
9179 var topOffset = $(this).css(pos).offset().top;
9180 if (topOffset < 0) {
9181 $(this).css('top', pos.top - topOffset);
9182 }
9183 }
9184 },
9185 resizable: true,
9186 show: null,
9187 stack: true,
9188 title: '',
9189 width: 300,
9190 zIndex: 1000
9191 },
9192
9193 _create: function() {
9194 this.originalTitle = this.element.attr('title');
9195 // #5742 - .attr() might return a DOMElement
9196 if ( typeof this.originalTitle !== "string" ) {
9197 this.originalTitle = "";
9198 }
9199
9200 this.options.title = this.options.title || this.originalTitle;
9201 var self = this,
9202 options = self.options,
9203
9204 title = options.title || '&#160;',
9205 titleId = $.ui.dialog.getTitleId(self.element),
9206
9207 uiDialog = (self.uiDialog = $('<div></div>'))
9208 .appendTo(document.body)
9209 .hide()
9210 .addClass(uiDialogClasses + options.dialogClass)
9211 .css({
9212 zIndex: options.zIndex
9213 })
9214 // setting tabIndex makes the div focusable
9215 // setting outline to 0 prevents a border on focus in Mozilla
9216 .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
9217 if (options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
9218 event.keyCode === $.ui.keyCode.ESCAPE) {
9219
9220 self.close(event);
9221 event.preventDefault();
9222 }
9223 })
9224 .attr({
9225 role: 'dialog',
9226 'aria-labelledby': titleId
9227 })
9228 .mousedown(function(event) {
9229 self.moveToTop(false, event);
9230 }),
9231
9232 uiDialogContent = self.element
9233 .show()
9234 .removeAttr('title')
9235 .addClass(
9236 'ui-dialog-content ' +
9237 'ui-widget-content')
9238 .appendTo(uiDialog),
9239
9240 uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
9241 .addClass(
9242 'ui-dialog-titlebar ' +
9243 'ui-widget-header ' +
9244 'ui-corner-all ' +
9245 'ui-helper-clearfix'
9246 )
9247 .prependTo(uiDialog),
9248
9249 uiDialogTitlebarClose = $('<a href="#"></a>')
9250 .addClass(
9251 'ui-dialog-titlebar-close ' +
9252 'ui-corner-all'
9253 )
9254 .attr('role', 'button')
9255 .hover(
9256 function() {
9257 uiDialogTitlebarClose.addClass('ui-state-hover');
9258 },
9259 function() {
9260 uiDialogTitlebarClose.removeClass('ui-state-hover');
9261 }
9262 )
9263 .focus(function() {
9264 uiDialogTitlebarClose.addClass('ui-state-focus');
9265 })
9266 .blur(function() {
9267 uiDialogTitlebarClose.removeClass('ui-state-focus');
9268 })
9269 .click(function(event) {
9270 self.close(event);
9271 return false;
9272 })
9273 .appendTo(uiDialogTitlebar),
9274
9275 uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
9276 .addClass(
9277 'ui-icon ' +
9278 'ui-icon-closethick'
9279 )
9280 .text(options.closeText)
9281 .appendTo(uiDialogTitlebarClose),
9282
9283 uiDialogTitle = $('<span></span>')
9284 .addClass('ui-dialog-title')
9285 .attr('id', titleId)
9286 .html(title)
9287 .prependTo(uiDialogTitlebar);
9288
9289 //handling of deprecated beforeclose (vs beforeClose) option
9290 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
9291 //TODO: remove in 1.9pre
9292 if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
9293 options.beforeClose = options.beforeclose;
9294 }
9295
9296 uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
9297
9298 if (options.draggable && $.fn.draggable) {
9299 self._makeDraggable();
9300 }
9301 if (options.resizable && $.fn.resizable) {
9302 self._makeResizable();
9303 }
9304
9305 self._createButtons(options.buttons);
9306 self._isOpen = false;
9307
9308 if ($.fn.bgiframe) {
9309 uiDialog.bgiframe();
9310 }
9311 },
9312
9313 _init: function() {
9314 if ( this.options.autoOpen ) {
9315 this.open();
9316 }
9317 },
9318
9319 destroy: function() {
9320 var self = this;
9321
9322 if (self.overlay) {
9323 self.overlay.destroy();
9324 }
9325 self.uiDialog.hide();
9326 self.element
9327 .unbind('.dialog')
9328 .removeData('dialog')
9329 .removeClass('ui-dialog-content ui-widget-content')
9330 .hide().appendTo('body');
9331 self.uiDialog.remove();
9332
9333 if (self.originalTitle) {
9334 self.element.attr('title', self.originalTitle);
9335 }
9336
9337 return self;
9338 },
9339
9340 widget: function() {
9341 return this.uiDialog;
9342 },
9343
9344 close: function(event) {
9345 var self = this,
9346 maxZ, thisZ;
9347
9348 if (false === self._trigger('beforeClose', event)) {
9349 return;
9350 }
9351
9352 if (self.overlay) {
9353 self.overlay.destroy();
9354 }
9355 self.uiDialog.unbind('keypress.ui-dialog');
9356
9357 self._isOpen = false;
9358
9359 if (self.options.hide) {
9360 self.uiDialog.hide(self.options.hide, function() {
9361 self._trigger('close', event);
9362 });
9363 } else {
9364 self.uiDialog.hide();
9365 self._trigger('close', event);
9366 }
9367
9368 $.ui.dialog.overlay.resize();
9369
9370 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
9371 if (self.options.modal) {
9372 maxZ = 0;
9373 $('.ui-dialog').each(function() {
9374 if (this !== self.uiDialog[0]) {
9375 thisZ = $(this).css('z-index');
9376 if(!isNaN(thisZ)) {
9377 maxZ = Math.max(maxZ, thisZ);
9378 }
9379 }
9380 });
9381 $.ui.dialog.maxZ = maxZ;
9382 }
9383
9384 return self;
9385 },
9386
9387 isOpen: function() {
9388 return this._isOpen;
9389 },
9390
9391 // the force parameter allows us to move modal dialogs to their correct
9392 // position on open
9393 moveToTop: function(force, event) {
9394 var self = this,
9395 options = self.options,
9396 saveScroll;
9397
9398 if ((options.modal && !force) ||
9399 (!options.stack && !options.modal)) {
9400 return self._trigger('focus', event);
9401 }
9402
9403 if (options.zIndex > $.ui.dialog.maxZ) {
9404 $.ui.dialog.maxZ = options.zIndex;
9405 }
9406 if (self.overlay) {
9407 $.ui.dialog.maxZ += 1;
9408 self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
9409 }
9410
9411 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
9412 // http://ui.jquery.com/bugs/ticket/3193
9413 saveScroll = { scrollTop: self.element.scrollTop(), scrollLeft: self.element.scrollLeft() };
9414 $.ui.dialog.maxZ += 1;
9415 self.uiDialog.css('z-index', $.ui.dialog.maxZ);
9416 self.element.attr(saveScroll);
9417 self._trigger('focus', event);
9418
9419 return self;
9420 },
9421
9422 open: function() {
9423 if (this._isOpen) { return; }
9424
9425 var self = this,
9426 options = self.options,
9427 uiDialog = self.uiDialog;
9428
9429 self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
9430 self._size();
9431 self._position(options.position);
9432 uiDialog.show(options.show);
9433 self.moveToTop(true);
9434
9435 // prevent tabbing out of modal dialogs
9436 if (options.modal) {
9437 uiDialog.bind('keypress.ui-dialog', function(event) {
9438 if (event.keyCode !== $.ui.keyCode.TAB) {
9439 return;
9440 }
9441
9442 var tabbables = $(':tabbable', this),
9443 first = tabbables.filter(':first'),
9444 last = tabbables.filter(':last');
9445
9446 if (event.target === last[0] && !event.shiftKey) {
9447 first.focus(1);
9448 return false;
9449 } else if (event.target === first[0] && event.shiftKey) {
9450 last.focus(1);
9451 return false;
9452 }
9453 });
9454 }
9455
9456 // set focus to the first tabbable element in the content area or the first button
9457 // if there are no tabbable elements, set focus on the dialog itself
9458 $(self.element.find(':tabbable').get().concat(
9459 uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
9460 uiDialog.get()))).eq(0).focus();
9461
9462 self._isOpen = true;
9463 self._trigger('open');
9464
9465 return self;
9466 },
9467
9468 _createButtons: function(buttons) {
9469 var self = this,
9470 hasButtons = false,
9471 uiDialogButtonPane = $('<div></div>')
9472 .addClass(
9473 'ui-dialog-buttonpane ' +
9474 'ui-widget-content ' +
9475 'ui-helper-clearfix'
9476 ),
9477 uiButtonSet = $( "<div></div>" )
9478 .addClass( "ui-dialog-buttonset" )
9479 .appendTo( uiDialogButtonPane );
9480
9481 // if we already have a button pane, remove it
9482 self.uiDialog.find('.ui-dialog-buttonpane').remove();
9483
9484 if (typeof buttons === 'object' && buttons !== null) {
9485 $.each(buttons, function() {
9486 return !(hasButtons = true);
9487 });
9488 }
9489 if (hasButtons) {
9490 $.each(buttons, function(name, props) {
9491 props = $.isFunction( props ) ?
9492 { click: props, text: name } :
9493 props;
9494 var button = $('<button type="button"></button>')
9495 .click(function() {
9496 props.click.apply(self.element[0], arguments);
9497 })
9498 .appendTo(uiButtonSet);
9499 // can't use .attr( props, true ) with jQuery 1.3.2.
9500 $.each( props, function( key, value ) {
9501 if ( key === "click" ) {
9502 return;
9503 }
9504 if ( key in attrFn ) {
9505 button[ key ]( value );
9506 } else {
9507 button.attr( key, value );
9508 }
9509 });
9510 if ($.fn.button) {
9511 button.button();
9512 }
9513 });
9514 uiDialogButtonPane.appendTo(self.uiDialog);
9515 }
9516 },
9517
9518 _makeDraggable: function() {
9519 var self = this,
9520 options = self.options,
9521 doc = $(document),
9522 heightBeforeDrag;
9523
9524 function filteredUi(ui) {
9525 return {
9526 position: ui.position,
9527 offset: ui.offset
9528 };
9529 }
9530
9531 self.uiDialog.draggable({
9532 cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
9533 handle: '.ui-dialog-titlebar',
9534 containment: 'document',
9535 start: function(event, ui) {
9536 heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
9537 $(this).height($(this).height()).addClass("ui-dialog-dragging");
9538 self._trigger('dragStart', event, filteredUi(ui));
9539 },
9540 drag: function(event, ui) {
9541 self._trigger('drag', event, filteredUi(ui));
9542 },
9543 stop: function(event, ui) {
9544 options.position = [ui.position.left - doc.scrollLeft(),
9545 ui.position.top - doc.scrollTop()];
9546 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
9547 self._trigger('dragStop', event, filteredUi(ui));
9548 $.ui.dialog.overlay.resize();
9549 }
9550 });
9551 },
9552
9553 _makeResizable: function(handles) {
9554 handles = (handles === undefined ? this.options.resizable : handles);
9555 var self = this,
9556 options = self.options,
9557 // .ui-resizable has position: relative defined in the stylesheet
9558 // but dialogs have to use absolute or fixed positioning
9559 position = self.uiDialog.css('position'),
9560 resizeHandles = (typeof handles === 'string' ?
9561 handles :
9562 'n,e,s,w,se,sw,ne,nw'
9563 );
9564
9565 function filteredUi(ui) {
9566 return {
9567 originalPosition: ui.originalPosition,
9568 originalSize: ui.originalSize,
9569 position: ui.position,
9570 size: ui.size
9571 };
9572 }
9573
9574 self.uiDialog.resizable({
9575 cancel: '.ui-dialog-content',
9576 containment: 'document',
9577 alsoResize: self.element,
9578 maxWidth: options.maxWidth,
9579 maxHeight: options.maxHeight,
9580 minWidth: options.minWidth,
9581 minHeight: self._minHeight(),
9582 handles: resizeHandles,
9583 start: function(event, ui) {
9584 $(this).addClass("ui-dialog-resizing");
9585 self._trigger('resizeStart', event, filteredUi(ui));
9586 },
9587 resize: function(event, ui) {
9588 self._trigger('resize', event, filteredUi(ui));
9589 },
9590 stop: function(event, ui) {
9591 $(this).removeClass("ui-dialog-resizing");
9592 options.height = $(this).height();
9593 options.width = $(this).width();
9594 self._trigger('resizeStop', event, filteredUi(ui));
9595 $.ui.dialog.overlay.resize();
9596 }
9597 })
9598 .css('position', position)
9599 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
9600 },
9601
9602 _minHeight: function() {
9603 var options = this.options;
9604
9605 if (options.height === 'auto') {
9606 return options.minHeight;
9607 } else {
9608 return Math.min(options.minHeight, options.height);
9609 }
9610 },
9611
9612 _position: function(position) {
9613 var myAt = [],
9614 offset = [0, 0],
9615 isVisible;
9616
9617 if (position) {
9618 // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
9619 // if (typeof position == 'string' || $.isArray(position)) {
9620 // myAt = $.isArray(position) ? position : position.split(' ');
9621
9622 if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
9623 myAt = position.split ? position.split(' ') : [position[0], position[1]];
9624 if (myAt.length === 1) {
9625 myAt[1] = myAt[0];
9626 }
9627
9628 $.each(['left', 'top'], function(i, offsetPosition) {
9629 if (+myAt[i] === myAt[i]) {
9630 offset[i] = myAt[i];
9631 myAt[i] = offsetPosition;
9632 }
9633 });
9634
9635 position = {
9636 my: myAt.join(" "),
9637 at: myAt.join(" "),
9638 offset: offset.join(" ")
9639 };
9640 }
9641
9642 position = $.extend({}, $.ui.dialog.prototype.options.position, position);
9643 } else {
9644 position = $.ui.dialog.prototype.options.position;
9645 }
9646
9647 // need to show the dialog to get the actual offset in the position plugin
9648 isVisible = this.uiDialog.is(':visible');
9649 if (!isVisible) {
9650 this.uiDialog.show();
9651 }
9652 this.uiDialog
9653 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
9654 .css({ top: 0, left: 0 })
9655 .position($.extend({ of: window }, position));
9656 if (!isVisible) {
9657 this.uiDialog.hide();
9658 }
9659 },
9660
9661 _setOptions: function( options ) {
9662 var self = this,
9663 resizableOptions = {},
9664 resize = false;
9665
9666 $.each( options, function( key, value ) {
9667 self._setOption( key, value );
9668
9669 if ( key in sizeRelatedOptions ) {
9670 resize = true;
9671 }
9672 if ( key in resizableRelatedOptions ) {
9673 resizableOptions[ key ] = value;
9674 }
9675 });
9676
9677 if ( resize ) {
9678 this._size();
9679 }
9680 if ( this.uiDialog.is( ":data(resizable)" ) ) {
9681 this.uiDialog.resizable( "option", resizableOptions );
9682 }
9683 },
9684
9685 _setOption: function(key, value){
9686 var self = this,
9687 uiDialog = self.uiDialog;
9688
9689 switch (key) {
9690 //handling of deprecated beforeclose (vs beforeClose) option
9691 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
9692 //TODO: remove in 1.9pre
9693 case "beforeclose":
9694 key = "beforeClose";
9695 break;
9696 case "buttons":
9697 self._createButtons(value);
9698 break;
9699 case "closeText":
9700 // ensure that we always pass a string
9701 self.uiDialogTitlebarCloseText.text("" + value);
9702 break;
9703 case "dialogClass":
9704 uiDialog
9705 .removeClass(self.options.dialogClass)
9706 .addClass(uiDialogClasses + value);
9707 break;
9708 case "disabled":
9709 if (value) {
9710 uiDialog.addClass('ui-dialog-disabled');
9711 } else {
9712 uiDialog.removeClass('ui-dialog-disabled');
9713 }
9714 break;
9715 case "draggable":
9716 var isDraggable = uiDialog.is( ":data(draggable)" );
9717 if ( isDraggable && !value ) {
9718 uiDialog.draggable( "destroy" );
9719 }
9720
9721 if ( !isDraggable && value ) {
9722 self._makeDraggable();
9723 }
9724 break;
9725 case "position":
9726 self._position(value);
9727 break;
9728 case "resizable":
9729 // currently resizable, becoming non-resizable
9730 var isResizable = uiDialog.is( ":data(resizable)" );
9731 if (isResizable && !value) {
9732 uiDialog.resizable('destroy');
9733 }
9734
9735 // currently resizable, changing handles
9736 if (isResizable && typeof value === 'string') {
9737 uiDialog.resizable('option', 'handles', value);
9738 }
9739
9740 // currently non-resizable, becoming resizable
9741 if (!isResizable && value !== false) {
9742 self._makeResizable(value);
9743 }
9744 break;
9745 case "title":
9746 // convert whatever was passed in o a string, for html() to not throw up
9747 $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
9748 break;
9749 }
9750
9751 $.Widget.prototype._setOption.apply(self, arguments);
9752 },
9753
9754 _size: function() {
9755 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
9756 * divs will both have width and height set, so we need to reset them
9757 */
9758 var options = this.options,
9759 nonContentHeight,
9760 minContentHeight,
9761 isVisible = this.uiDialog.is( ":visible" );
9762
9763 // reset content sizing
9764 this.element.show().css({
9765 width: 'auto',
9766 minHeight: 0,
9767 height: 0
9768 });
9769
9770 if (options.minWidth > options.width) {
9771 options.width = options.minWidth;
9772 }
9773
9774 // reset wrapper sizing
9775 // determine the height of all the non-content elements
9776 nonContentHeight = this.uiDialog.css({
9777 height: 'auto',
9778 width: options.width
9779 })
9780 .height();
9781 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
9782
9783 if ( options.height === "auto" ) {
9784 // only needed for IE6 support
9785 if ( $.support.minHeight ) {
9786 this.element.css({
9787 minHeight: minContentHeight,
9788 height: "auto"
9789 });
9790 } else {
9791 this.uiDialog.show();
9792 var autoHeight = this.element.css( "height", "auto" ).height();
9793 if ( !isVisible ) {
9794 this.uiDialog.hide();
9795 }
9796 this.element.height( Math.max( autoHeight, minContentHeight ) );
9797 }
9798 } else {
9799 this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
9800 }
9801
9802 if (this.uiDialog.is(':data(resizable)')) {
9803 this.uiDialog.resizable('option', 'minHeight', this._minHeight());
9804 }
9805 }
9806 });
9807
9808 $.extend($.ui.dialog, {
9809 version: "1.8.16",
9810
9811 uuid: 0,
9812 maxZ: 0,
9813
9814 getTitleId: function($el) {
9815 var id = $el.attr('id');
9816 if (!id) {
9817 this.uuid += 1;
9818 id = this.uuid;
9819 }
9820 return 'ui-dialog-title-' + id;
9821 },
9822
9823 overlay: function(dialog) {
9824 this.$el = $.ui.dialog.overlay.create(dialog);
9825 }
9826 });
9827
9828 $.extend($.ui.dialog.overlay, {
9829 instances: [],
9830 // reuse old instances due to IE memory leak with alpha transparency (see #5185)
9831 oldInstances: [],
9832 maxZ: 0,
9833 events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
9834 function(event) { return event + '.dialog-overlay'; }).join(' '),
9835 create: function(dialog) {
9836 if (this.instances.length === 0) {
9837 // prevent use of anchors and inputs
9838 // we use a setTimeout in case the overlay is created from an
9839 // event that we're going to be cancelling (see #2804)
9840 setTimeout(function() {
9841 // handle $(el).dialog().dialog('close') (see #4065)
9842 if ($.ui.dialog.overlay.instances.length) {
9843 $(document).bind($.ui.dialog.overlay.events, function(event) {
9844 // stop events if the z-index of the target is < the z-index of the overlay
9845 // we cannot return true when we don't want to cancel the event (#3523)
9846 if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
9847 return false;
9848 }
9849 });
9850 }
9851 }, 1);
9852
9853 // allow closing by pressing the escape key
9854 $(document).bind('keydown.dialog-overlay', function(event) {
9855 if (dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
9856 event.keyCode === $.ui.keyCode.ESCAPE) {
9857
9858 dialog.close(event);
9859 event.preventDefault();
9860 }
9861 });
9862
9863 // handle window resize
9864 $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
9865 }
9866
9867 var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
9868 .appendTo(document.body)
9869 .css({
9870 width: this.width(),
9871 height: this.height()
9872 });
9873
9874 if ($.fn.bgiframe) {
9875 $el.bgiframe();
9876 }
9877
9878 this.instances.push($el);
9879 return $el;
9880 },
9881
9882 destroy: function($el) {
9883 var indexOf = $.inArray($el, this.instances);
9884 if (indexOf != -1){
9885 this.oldInstances.push(this.instances.splice(indexOf, 1)[0]);
9886 }
9887
9888 if (this.instances.length === 0) {
9889 $([document, window]).unbind('.dialog-overlay');
9890 }
9891
9892 $el.remove();
9893
9894 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
9895 var maxZ = 0;
9896 $.each(this.instances, function() {
9897 maxZ = Math.max(maxZ, this.css('z-index'));
9898 });
9899 this.maxZ = maxZ;
9900 },
9901
9902 height: function() {
9903 var scrollHeight,
9904 offsetHeight;
9905 // handle IE 6
9906 if ($.browser.msie && $.browser.version < 7) {
9907 scrollHeight = Math.max(
9908 document.documentElement.scrollHeight,
9909 document.body.scrollHeight
9910 );
9911 offsetHeight = Math.max(
9912 document.documentElement.offsetHeight,
9913 document.body.offsetHeight
9914 );
9915
9916 if (scrollHeight < offsetHeight) {
9917 return $(window).height() + 'px';
9918 } else {
9919 return scrollHeight + 'px';
9920 }
9921 // handle "good" browsers
9922 } else {
9923 return $(document).height() + 'px';
9924 }
9925 },
9926
9927 width: function() {
9928 var scrollWidth,
9929 offsetWidth;
9930 // handle IE
9931 if ( $.browser.msie ) {
9932 scrollWidth = Math.max(
9933 document.documentElement.scrollWidth,
9934 document.body.scrollWidth
9935 );
9936 offsetWidth = Math.max(
9937 document.documentElement.offsetWidth,
9938 document.body.offsetWidth
9939 );
9940
9941 if (scrollWidth < offsetWidth) {
9942 return $(window).width() + 'px';
9943 } else {
9944 return scrollWidth + 'px';
9945 }
9946 // handle "good" browsers
9947 } else {
9948 return $(document).width() + 'px';
9949 }
9950 },
9951
9952 resize: function() {
9953 /* If the dialog is draggable and the user drags it past the
9954 * right edge of the window, the document becomes wider so we
9955 * need to stretch the overlay. If the user then drags the
9956 * dialog back to the left, the document will become narrower,
9957 * so we need to shrink the overlay to the appropriate size.
9958 * This is handled by shrinking the overlay before setting it
9959 * to the full document size.
9960 */
9961 var $overlays = $([]);
9962 $.each($.ui.dialog.overlay.instances, function() {
9963 $overlays = $overlays.add(this);
9964 });
9965
9966 $overlays.css({
9967 width: 0,
9968 height: 0
9969 }).css({
9970 width: $.ui.dialog.overlay.width(),
9971 height: $.ui.dialog.overlay.height()
9972 });
9973 }
9974 });
9975
9976 $.extend($.ui.dialog.overlay.prototype, {
9977 destroy: function() {
9978 $.ui.dialog.overlay.destroy(this.$el);
9979 }
9980 });
9981
9982 }(jQuery));
9983 /*
9984 * jQuery UI Position 1.8.16
9985 *
9986 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
9987 * Dual licensed under the MIT or GPL Version 2 licenses.
9988 * http://jquery.org/license
9989 *
9990 * http://docs.jquery.com/UI/Position
9991 */
9992 (function( $, undefined ) {
9993
9994 $.ui = $.ui || {};
9995
9996 var horizontalPositions = /left|center|right/,
9997 verticalPositions = /top|center|bottom/,
9998 center = "center",
9999 _position = $.fn.position,
10000 _offset = $.fn.offset;
10001
10002 $.fn.position = function( options ) {
10003 if ( !options || !options.of ) {
10004 return _position.apply( this, arguments );
10005 }
10006
10007 // make a copy, we don't want to modify arguments
10008 options = $.extend( {}, options );
10009
10010 var target = $( options.of ),
10011 targetElem = target[0],
10012 collision = ( options.collision || "flip" ).split( " " ),
10013 offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
10014 targetWidth,
10015 targetHeight,
10016 basePosition;
10017
10018 if ( targetElem.nodeType === 9 ) {
10019 targetWidth = target.width();
10020 targetHeight = target.height();
10021 basePosition = { top: 0, left: 0 };
10022 // TODO: use $.isWindow() in 1.9
10023 } else if ( targetElem.setTimeout ) {
10024 targetWidth = target.width();
10025 targetHeight = target.height();
10026 basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
10027 } else if ( targetElem.preventDefault ) {
10028 // force left top to allow flipping
10029 options.at = "left top";
10030 targetWidth = targetHeight = 0;
10031 basePosition = { top: options.of.pageY, left: options.of.pageX };
10032 } else {
10033 targetWidth = target.outerWidth();
10034 targetHeight = target.outerHeight();
10035 basePosition = target.offset();
10036 }
10037
10038 // force my and at to have valid horizontal and veritcal positions
10039 // if a value is missing or invalid, it will be converted to center
10040 $.each( [ "my", "at" ], function() {
10041 var pos = ( options[this] || "" ).split( " " );
10042 if ( pos.length === 1) {
10043 pos = horizontalPositions.test( pos[0] ) ?
10044 pos.concat( [center] ) :
10045 verticalPositions.test( pos[0] ) ?
10046 [ center ].concat( pos ) :
10047 [ center, center ];
10048 }
10049 pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
10050 pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
10051 options[ this ] = pos;
10052 });
10053
10054 // normalize collision option
10055 if ( collision.length === 1 ) {
10056 collision[ 1 ] = collision[ 0 ];
10057 }
10058
10059 // normalize offset option
10060 offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
10061 if ( offset.length === 1 ) {
10062 offset[ 1 ] = offset[ 0 ];
10063 }
10064 offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
10065
10066 if ( options.at[0] === "right" ) {
10067 basePosition.left += targetWidth;
10068 } else if ( options.at[0] === center ) {
10069 basePosition.left += targetWidth / 2;
10070 }
10071
10072 if ( options.at[1] === "bottom" ) {
10073 basePosition.top += targetHeight;
10074 } else if ( options.at[1] === center ) {
10075 basePosition.top += targetHeight / 2;
10076 }
10077
10078 basePosition.left += offset[ 0 ];
10079 basePosition.top += offset[ 1 ];
10080
10081 return this.each(function() {
10082 var elem = $( this ),
10083 elemWidth = elem.outerWidth(),
10084 elemHeight = elem.outerHeight(),
10085 marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
10086 marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
10087 collisionWidth = elemWidth + marginLeft +
10088 ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
10089 collisionHeight = elemHeight + marginTop +
10090 ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
10091 position = $.extend( {}, basePosition ),
10092 collisionPosition;
10093
10094 if ( options.my[0] === "right" ) {
10095 position.left -= elemWidth;
10096 } else if ( options.my[0] === center ) {
10097 position.left -= elemWidth / 2;
10098 }
10099
10100 if ( options.my[1] === "bottom" ) {
10101 position.top -= elemHeight;
10102 } else if ( options.my[1] === center ) {
10103 position.top -= elemHeight / 2;
10104 }
10105
10106 // prevent fractions (see #5280)
10107 position.left = Math.round( position.left );
10108 position.top = Math.round( position.top );
10109
10110 collisionPosition = {
10111 left: position.left - marginLeft,
10112 top: position.top - marginTop
10113 };
10114
10115 $.each( [ "left", "top" ], function( i, dir ) {
10116 if ( $.ui.position[ collision[i] ] ) {
10117 $.ui.position[ collision[i] ][ dir ]( position, {
10118 targetWidth: targetWidth,
10119 targetHeight: targetHeight,
10120 elemWidth: elemWidth,
10121 elemHeight: elemHeight,
10122 collisionPosition: collisionPosition,
10123 collisionWidth: collisionWidth,
10124 collisionHeight: collisionHeight,
10125 offset: offset,
10126 my: options.my,
10127 at: options.at
10128 });
10129 }
10130 });
10131
10132 if ( $.fn.bgiframe ) {
10133 elem.bgiframe();
10134 }
10135 elem.offset( $.extend( position, { using: options.using } ) );
10136 });
10137 };
10138
10139 $.ui.position = {
10140 fit: {
10141 left: function( position, data ) {
10142 var win = $( window ),
10143 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
10144 position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
10145 },
10146 top: function( position, data ) {
10147 var win = $( window ),
10148 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
10149 position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
10150 }
10151 },
10152
10153 flip: {
10154 left: function( position, data ) {
10155 if ( data.at[0] === center ) {
10156 return;
10157 }
10158 var win = $( window ),
10159 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
10160 myOffset = data.my[ 0 ] === "left" ?
10161 -data.elemWidth :
10162 data.my[ 0 ] === "right" ?
10163 data.elemWidth :
10164 0,
10165 atOffset = data.at[ 0 ] === "left" ?
10166 data.targetWidth :
10167 -data.targetWidth,
10168 offset = -2 * data.offset[ 0 ];
10169 position.left += data.collisionPosition.left < 0 ?
10170 myOffset + atOffset + offset :
10171 over > 0 ?
10172 myOffset + atOffset + offset :
10173 0;
10174 },
10175 top: function( position, data ) {
10176 if ( data.at[1] === center ) {
10177 return;
10178 }
10179 var win = $( window ),
10180 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
10181 myOffset = data.my[ 1 ] === "top" ?
10182 -data.elemHeight :
10183 data.my[ 1 ] === "bottom" ?
10184 data.elemHeight :
10185 0,
10186 atOffset = data.at[ 1 ] === "top" ?
10187 data.targetHeight :
10188 -data.targetHeight,
10189 offset = -2 * data.offset[ 1 ];
10190 position.top += data.collisionPosition.top < 0 ?
10191 myOffset + atOffset + offset :
10192 over > 0 ?
10193 myOffset + atOffset + offset :
10194 0;
10195 }
10196 }
10197 };
10198
10199 // offset setter from jQuery 1.4
10200 if ( !$.offset.setOffset ) {
10201 $.offset.setOffset = function( elem, options ) {
10202 // set position first, in-case top/left are set even on static elem
10203 if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
10204 elem.style.position = "relative";
10205 }
10206 var curElem = $( elem ),
10207 curOffset = curElem.offset(),
10208 curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0,
10209 curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0,
10210 props = {
10211 top: (options.top - curOffset.top) + curTop,
10212 left: (options.left - curOffset.left) + curLeft
10213 };
10214
10215 if ( 'using' in options ) {
10216 options.using.call( elem, props );
10217 } else {
10218 curElem.css( props );
10219 }
10220 };
10221
10222 $.fn.offset = function( options ) {
10223 var elem = this[ 0 ];
10224 if ( !elem || !elem.ownerDocument ) { return null; }
10225 if ( options ) {
10226 return this.each(function() {
10227 $.offset.setOffset( this, options );
10228 });
10229 }
10230 return _offset.call( this );
10231 };
10232 }
10233
10234 }( jQuery ));
10235 /*
10236 * jQuery UI Progressbar 1.8.16
10237 *
10238 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10239 * Dual licensed under the MIT or GPL Version 2 licenses.
10240 * http://jquery.org/license
10241 *
10242 * http://docs.jquery.com/UI/Progressbar
10243 *
10244 * Depends:
10245 * jquery.ui.core.js
10246 * jquery.ui.widget.js
10247 */
10248 (function( $, undefined ) {
10249
10250 $.widget( "ui.progressbar", {
10251 options: {
10252 value: 0,
10253 max: 100
10254 },
10255
10256 min: 0,
10257
10258 _create: function() {
10259 this.element
10260 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
10261 .attr({
10262 role: "progressbar",
10263 "aria-valuemin": this.min,
10264 "aria-valuemax": this.options.max,
10265 "aria-valuenow": this._value()
10266 });
10267
10268 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
10269 .appendTo( this.element );
10270
10271 this.oldValue = this._value();
10272 this._refreshValue();
10273 },
10274
10275 destroy: function() {
10276 this.element
10277 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
10278 .removeAttr( "role" )
10279 .removeAttr( "aria-valuemin" )
10280 .removeAttr( "aria-valuemax" )
10281 .removeAttr( "aria-valuenow" );
10282
10283 this.valueDiv.remove();
10284
10285 $.Widget.prototype.destroy.apply( this, arguments );
10286 },
10287
10288 value: function( newValue ) {
10289 if ( newValue === undefined ) {
10290 return this._value();
10291 }
10292
10293 this._setOption( "value", newValue );
10294 return this;
10295 },
10296
10297 _setOption: function( key, value ) {
10298 if ( key === "value" ) {
10299 this.options.value = value;
10300 this._refreshValue();
10301 if ( this._value() === this.options.max ) {
10302 this._trigger( "complete" );
10303 }
10304 }
10305
10306 $.Widget.prototype._setOption.apply( this, arguments );
10307 },
10308
10309 _value: function() {
10310 var val = this.options.value;
10311 // normalize invalid value
10312 if ( typeof val !== "number" ) {
10313 val = 0;
10314 }
10315 return Math.min( this.options.max, Math.max( this.min, val ) );
10316 },
10317
10318 _percentage: function() {
10319 return 100 * this._value() / this.options.max;
10320 },
10321
10322 _refreshValue: function() {
10323 var value = this.value();
10324 var percentage = this._percentage();
10325
10326 if ( this.oldValue !== value ) {
10327 this.oldValue = value;
10328 this._trigger( "change" );
10329 }
10330
10331 this.valueDiv
10332 .toggle( value > this.min )
10333 .toggleClass( "ui-corner-right", value === this.options.max )
10334 .width( percentage.toFixed(0) + "%" );
10335 this.element.attr( "aria-valuenow", value );
10336 }
10337 });
10338
10339 $.extend( $.ui.progressbar, {
10340 version: "1.8.16"
10341 });
10342
10343 })( jQuery );
10344 /*
10345 * jQuery UI Slider 1.8.16
10346 *
10347 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10348 * Dual licensed under the MIT or GPL Version 2 licenses.
10349 * http://jquery.org/license
10350 *
10351 * http://docs.jquery.com/UI/Slider
10352 *
10353 * Depends:
10354 * jquery.ui.core.js
10355 * jquery.ui.mouse.js
10356 * jquery.ui.widget.js
10357 */
10358 (function( $, undefined ) {
10359
10360 // number of pages in a slider
10361 // (how many times can you page up/down to go through the whole range)
10362 var numPages = 5;
10363
10364 $.widget( "ui.slider", $.ui.mouse, {
10365
10366 widgetEventPrefix: "slide",
10367
10368 options: {
10369 animate: false,
10370 distance: 0,
10371 max: 100,
10372 min: 0,
10373 orientation: "horizontal",
10374 range: false,
10375 step: 1,
10376 value: 0,
10377 values: null
10378 },
10379
10380 _create: function() {
10381 var self = this,
10382 o = this.options,
10383 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
10384 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
10385 handleCount = ( o.values && o.values.length ) || 1,
10386 handles = [];
10387
10388 this._keySliding = false;
10389 this._mouseSliding = false;
10390 this._animateOff = true;
10391 this._handleIndex = null;
10392 this._detectOrientation();
10393 this._mouseInit();
10394
10395 this.element
10396 .addClass( "ui-slider" +
10397 " ui-slider-" + this.orientation +
10398 " ui-widget" +
10399 " ui-widget-content" +
10400 " ui-corner-all" +
10401 ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) );
10402
10403 this.range = $([]);
10404
10405 if ( o.range ) {
10406 if ( o.range === true ) {
10407 if ( !o.values ) {
10408 o.values = [ this._valueMin(), this._valueMin() ];
10409 }
10410 if ( o.values.length && o.values.length !== 2 ) {
10411 o.values = [ o.values[0], o.values[0] ];
10412 }
10413 }
10414
10415 this.range = $( "<div></div>" )
10416 .appendTo( this.element )
10417 .addClass( "ui-slider-range" +
10418 // note: this isn't the most fittingly semantic framework class for this element,
10419 // but worked best visually with a variety of themes
10420 " ui-widget-header" +
10421 ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) );
10422 }
10423
10424 for ( var i = existingHandles.length; i < handleCount; i += 1 ) {
10425 handles.push( handle );
10426 }
10427
10428 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) );
10429
10430 this.handle = this.handles.eq( 0 );
10431
10432 this.handles.add( this.range ).filter( "a" )
10433 .click(function( event ) {
10434 event.preventDefault();
10435 })
10436 .hover(function() {
10437 if ( !o.disabled ) {
10438 $( this ).addClass( "ui-state-hover" );
10439 }
10440 }, function() {
10441 $( this ).removeClass( "ui-state-hover" );
10442 })
10443 .focus(function() {
10444 if ( !o.disabled ) {
10445 $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
10446 $( this ).addClass( "ui-state-focus" );
10447 } else {
10448 $( this ).blur();
10449 }
10450 })
10451 .blur(function() {
10452 $( this ).removeClass( "ui-state-focus" );
10453 });
10454
10455 this.handles.each(function( i ) {
10456 $( this ).data( "index.ui-slider-handle", i );
10457 });
10458
10459 this.handles
10460 .keydown(function( event ) {
10461 var ret = true,
10462 index = $( this ).data( "index.ui-slider-handle" ),
10463 allowed,
10464 curVal,
10465 newVal,
10466 step;
10467
10468 if ( self.options.disabled ) {
10469 return;
10470 }
10471
10472 switch ( event.keyCode ) {
10473 case $.ui.keyCode.HOME:
10474 case $.ui.keyCode.END:
10475 case $.ui.keyCode.PAGE_UP:
10476 case $.ui.keyCode.PAGE_DOWN:
10477 case $.ui.keyCode.UP:
10478 case $.ui.keyCode.RIGHT:
10479 case $.ui.keyCode.DOWN:
10480 case $.ui.keyCode.LEFT:
10481 ret = false;
10482 if ( !self._keySliding ) {
10483 self._keySliding = true;
10484 $( this ).addClass( "ui-state-active" );
10485 allowed = self._start( event, index );
10486 if ( allowed === false ) {
10487 return;
10488 }
10489 }
10490 break;
10491 }
10492
10493 step = self.options.step;
10494 if ( self.options.values && self.options.values.length ) {
10495 curVal = newVal = self.values( index );
10496 } else {
10497 curVal = newVal = self.value();
10498 }
10499
10500 switch ( event.keyCode ) {
10501 case $.ui.keyCode.HOME:
10502 newVal = self._valueMin();
10503 break;
10504 case $.ui.keyCode.END:
10505 newVal = self._valueMax();
10506 break;
10507 case $.ui.keyCode.PAGE_UP:
10508 newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
10509 break;
10510 case $.ui.keyCode.PAGE_DOWN:
10511 newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
10512 break;
10513 case $.ui.keyCode.UP:
10514 case $.ui.keyCode.RIGHT:
10515 if ( curVal === self._valueMax() ) {
10516 return;
10517 }
10518 newVal = self._trimAlignValue( curVal + step );
10519 break;
10520 case $.ui.keyCode.DOWN:
10521 case $.ui.keyCode.LEFT:
10522 if ( curVal === self._valueMin() ) {
10523 return;
10524 }
10525 newVal = self._trimAlignValue( curVal - step );
10526 break;
10527 }
10528
10529 self._slide( event, index, newVal );
10530
10531 return ret;
10532
10533 })
10534 .keyup(function( event ) {
10535 var index = $( this ).data( "index.ui-slider-handle" );
10536
10537 if ( self._keySliding ) {
10538 self._keySliding = false;
10539 self._stop( event, index );
10540 self._change( event, index );
10541 $( this ).removeClass( "ui-state-active" );
10542 }
10543
10544 });
10545
10546 this._refreshValue();
10547
10548 this._animateOff = false;
10549 },
10550
10551 destroy: function() {
10552 this.handles.remove();
10553 this.range.remove();
10554
10555 this.element
10556 .removeClass( "ui-slider" +
10557 " ui-slider-horizontal" +
10558 " ui-slider-vertical" +
10559 " ui-slider-disabled" +
10560 " ui-widget" +
10561 " ui-widget-content" +
10562 " ui-corner-all" )
10563 .removeData( "slider" )
10564 .unbind( ".slider" );
10565
10566 this._mouseDestroy();
10567
10568 return this;
10569 },
10570
10571 _mouseCapture: function( event ) {
10572 var o = this.options,
10573 position,
10574 normValue,
10575 distance,
10576 closestHandle,
10577 self,
10578 index,
10579 allowed,
10580 offset,
10581 mouseOverHandle;
10582
10583 if ( o.disabled ) {
10584 return false;
10585 }
10586
10587 this.elementSize = {
10588 width: this.element.outerWidth(),
10589 height: this.element.outerHeight()
10590 };
10591 this.elementOffset = this.element.offset();
10592
10593 position = { x: event.pageX, y: event.pageY };
10594 normValue = this._normValueFromMouse( position );
10595 distance = this._valueMax() - this._valueMin() + 1;
10596 self = this;
10597 this.handles.each(function( i ) {
10598 var thisDistance = Math.abs( normValue - self.values(i) );
10599 if ( distance > thisDistance ) {
10600 distance = thisDistance;
10601 closestHandle = $( this );
10602 index = i;
10603 }
10604 });
10605
10606 // workaround for bug #3736 (if both handles of a range are at 0,
10607 // the first is always used as the one with least distance,
10608 // and moving it is obviously prevented by preventing negative ranges)
10609 if( o.range === true && this.values(1) === o.min ) {
10610 index += 1;
10611 closestHandle = $( this.handles[index] );
10612 }
10613
10614 allowed = this._start( event, index );
10615 if ( allowed === false ) {
10616 return false;
10617 }
10618 this._mouseSliding = true;
10619
10620 self._handleIndex = index;
10621
10622 closestHandle
10623 .addClass( "ui-state-active" )
10624 .focus();
10625
10626 offset = closestHandle.offset();
10627 mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
10628 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
10629 left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
10630 top: event.pageY - offset.top -
10631 ( closestHandle.height() / 2 ) -
10632 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
10633 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
10634 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
10635 };
10636
10637 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
10638 this._slide( event, index, normValue );
10639 }
10640 this._animateOff = true;
10641 return true;
10642 },
10643
10644 _mouseStart: function( event ) {
10645 return true;
10646 },
10647
10648 _mouseDrag: function( event ) {
10649 var position = { x: event.pageX, y: event.pageY },
10650 normValue = this._normValueFromMouse( position );
10651
10652 this._slide( event, this._handleIndex, normValue );
10653
10654 return false;
10655 },
10656
10657 _mouseStop: function( event ) {
10658 this.handles.removeClass( "ui-state-active" );
10659 this._mouseSliding = false;
10660
10661 this._stop( event, this._handleIndex );
10662 this._change( event, this._handleIndex );
10663
10664 this._handleIndex = null;
10665 this._clickOffset = null;
10666 this._animateOff = false;
10667
10668 return false;
10669 },
10670
10671 _detectOrientation: function() {
10672 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
10673 },
10674
10675 _normValueFromMouse: function( position ) {
10676 var pixelTotal,
10677 pixelMouse,
10678 percentMouse,
10679 valueTotal,
10680 valueMouse;
10681
10682 if ( this.orientation === "horizontal" ) {
10683 pixelTotal = this.elementSize.width;
10684 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
10685 } else {
10686 pixelTotal = this.elementSize.height;
10687 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
10688 }
10689
10690 percentMouse = ( pixelMouse / pixelTotal );
10691 if ( percentMouse > 1 ) {
10692 percentMouse = 1;
10693 }
10694 if ( percentMouse < 0 ) {
10695 percentMouse = 0;
10696 }
10697 if ( this.orientation === "vertical" ) {
10698 percentMouse = 1 - percentMouse;
10699 }
10700
10701 valueTotal = this._valueMax() - this._valueMin();
10702 valueMouse = this._valueMin() + percentMouse * valueTotal;
10703
10704 return this._trimAlignValue( valueMouse );
10705 },
10706
10707 _start: function( event, index ) {
10708 var uiHash = {
10709 handle: this.handles[ index ],
10710 value: this.value()
10711 };
10712 if ( this.options.values && this.options.values.length ) {
10713 uiHash.value = this.values( index );
10714 uiHash.values = this.values();
10715 }
10716 return this._trigger( "start", event, uiHash );
10717 },
10718
10719 _slide: function( event, index, newVal ) {
10720 var otherVal,
10721 newValues,
10722 allowed;
10723
10724 if ( this.options.values && this.options.values.length ) {
10725 otherVal = this.values( index ? 0 : 1 );
10726
10727 if ( ( this.options.values.length === 2 && this.options.range === true ) &&
10728 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
10729 ) {
10730 newVal = otherVal;
10731 }
10732
10733 if ( newVal !== this.values( index ) ) {
10734 newValues = this.values();
10735 newValues[ index ] = newVal;
10736 // A slide can be canceled by returning false from the slide callback
10737 allowed = this._trigger( "slide", event, {
10738 handle: this.handles[ index ],
10739 value: newVal,
10740 values: newValues
10741 } );
10742 otherVal = this.values( index ? 0 : 1 );
10743 if ( allowed !== false ) {
10744 this.values( index, newVal, true );
10745 }
10746 }
10747 } else {
10748 if ( newVal !== this.value() ) {
10749 // A slide can be canceled by returning false from the slide callback
10750 allowed = this._trigger( "slide", event, {
10751 handle: this.handles[ index ],
10752 value: newVal
10753 } );
10754 if ( allowed !== false ) {
10755 this.value( newVal );
10756 }
10757 }
10758 }
10759 },
10760
10761 _stop: function( event, index ) {
10762 var uiHash = {
10763 handle: this.handles[ index ],
10764 value: this.value()
10765 };
10766 if ( this.options.values && this.options.values.length ) {
10767 uiHash.value = this.values( index );
10768 uiHash.values = this.values();
10769 }
10770
10771 this._trigger( "stop", event, uiHash );
10772 },
10773
10774 _change: function( event, index ) {
10775 if ( !this._keySliding && !this._mouseSliding ) {
10776 var uiHash = {
10777 handle: this.handles[ index ],
10778 value: this.value()
10779 };
10780 if ( this.options.values && this.options.values.length ) {
10781 uiHash.value = this.values( index );
10782 uiHash.values = this.values();
10783 }
10784
10785 this._trigger( "change", event, uiHash );
10786 }
10787 },
10788
10789 value: function( newValue ) {
10790 if ( arguments.length ) {
10791 this.options.value = this._trimAlignValue( newValue );
10792 this._refreshValue();
10793 this._change( null, 0 );
10794 return;
10795 }
10796
10797 return this._value();
10798 },
10799
10800 values: function( index, newValue ) {
10801 var vals,
10802 newValues,
10803 i;
10804
10805 if ( arguments.length > 1 ) {
10806 this.options.values[ index ] = this._trimAlignValue( newValue );
10807 this._refreshValue();
10808 this._change( null, index );
10809 return;
10810 }
10811
10812 if ( arguments.length ) {
10813 if ( $.isArray( arguments[ 0 ] ) ) {
10814 vals = this.options.values;
10815 newValues = arguments[ 0 ];
10816 for ( i = 0; i < vals.length; i += 1 ) {
10817 vals[ i ] = this._trimAlignValue( newValues[ i ] );
10818 this._change( null, i );
10819 }
10820 this._refreshValue();
10821 } else {
10822 if ( this.options.values && this.options.values.length ) {
10823 return this._values( index );
10824 } else {
10825 return this.value();
10826 }
10827 }
10828 } else {
10829 return this._values();
10830 }
10831 },
10832
10833 _setOption: function( key, value ) {
10834 var i,
10835 valsLength = 0;
10836
10837 if ( $.isArray( this.options.values ) ) {
10838 valsLength = this.options.values.length;
10839 }
10840
10841 $.Widget.prototype._setOption.apply( this, arguments );
10842
10843 switch ( key ) {
10844 case "disabled":
10845 if ( value ) {
10846 this.handles.filter( ".ui-state-focus" ).blur();
10847 this.handles.removeClass( "ui-state-hover" );
10848 this.handles.propAttr( "disabled", true );
10849 this.element.addClass( "ui-disabled" );
10850 } else {
10851 this.handles.propAttr( "disabled", false );
10852 this.element.removeClass( "ui-disabled" );
10853 }
10854 break;
10855 case "orientation":
10856 this._detectOrientation();
10857 this.element
10858 .removeClass( "ui-slider-horizontal ui-slider-vertical" )
10859 .addClass( "ui-slider-" + this.orientation );
10860 this._refreshValue();
10861 break;
10862 case "value":
10863 this._animateOff = true;
10864 this._refreshValue();
10865 this._change( null, 0 );
10866 this._animateOff = false;
10867 break;
10868 case "values":
10869 this._animateOff = true;
10870 this._refreshValue();
10871 for ( i = 0; i < valsLength; i += 1 ) {
10872 this._change( null, i );
10873 }
10874 this._animateOff = false;
10875 break;
10876 }
10877 },
10878
10879 //internal value getter
10880 // _value() returns value trimmed by min and max, aligned by step
10881 _value: function() {
10882 var val = this.options.value;
10883 val = this._trimAlignValue( val );
10884
10885 return val;
10886 },
10887
10888 //internal values getter
10889 // _values() returns array of values trimmed by min and max, aligned by step
10890 // _values( index ) returns single value trimmed by min and max, aligned by step
10891 _values: function( index ) {
10892 var val,
10893 vals,
10894 i;
10895
10896 if ( arguments.length ) {
10897 val = this.options.values[ index ];
10898 val = this._trimAlignValue( val );
10899
10900 return val;
10901 } else {
10902 // .slice() creates a copy of the array
10903 // this copy gets trimmed by min and max and then returned
10904 vals = this.options.values.slice();
10905 for ( i = 0; i < vals.length; i+= 1) {
10906 vals[ i ] = this._trimAlignValue( vals[ i ] );
10907 }
10908
10909 return vals;
10910 }
10911 },
10912
10913 // returns the step-aligned value that val is closest to, between (inclusive) min and max
10914 _trimAlignValue: function( val ) {
10915 if ( val <= this._valueMin() ) {
10916 return this._valueMin();
10917 }
10918 if ( val >= this._valueMax() ) {
10919 return this._valueMax();
10920 }
10921 var step = ( this.options.step > 0 ) ? this.options.step : 1,
10922 valModStep = (val - this._valueMin()) % step,
10923 alignValue = val - valModStep;
10924
10925 if ( Math.abs(valModStep) * 2 >= step ) {
10926 alignValue += ( valModStep > 0 ) ? step : ( -step );
10927 }
10928
10929 // Since JavaScript has problems with large floats, round
10930 // the final value to 5 digits after the decimal point (see #4124)
10931 return parseFloat( alignValue.toFixed(5) );
10932 },
10933
10934 _valueMin: function() {
10935 return this.options.min;
10936 },
10937
10938 _valueMax: function() {
10939 return this.options.max;
10940 },
10941
10942 _refreshValue: function() {
10943 var oRange = this.options.range,
10944 o = this.options,
10945 self = this,
10946 animate = ( !this._animateOff ) ? o.animate : false,
10947 valPercent,
10948 _set = {},
10949 lastValPercent,
10950 value,
10951 valueMin,
10952 valueMax;
10953
10954 if ( this.options.values && this.options.values.length ) {
10955 this.handles.each(function( i, j ) {
10956 valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
10957 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
10958 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
10959 if ( self.options.range === true ) {
10960 if ( self.orientation === "horizontal" ) {
10961 if ( i === 0 ) {
10962 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
10963 }
10964 if ( i === 1 ) {
10965 self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
10966 }
10967 } else {
10968 if ( i === 0 ) {
10969 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
10970 }
10971 if ( i === 1 ) {
10972 self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
10973 }
10974 }
10975 }
10976 lastValPercent = valPercent;
10977 });
10978 } else {
10979 value = this.value();
10980 valueMin = this._valueMin();
10981 valueMax = this._valueMax();
10982 valPercent = ( valueMax !== valueMin ) ?
10983 ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
10984 0;
10985 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
10986 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
10987
10988 if ( oRange === "min" && this.orientation === "horizontal" ) {
10989 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
10990 }
10991 if ( oRange === "max" && this.orientation === "horizontal" ) {
10992 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
10993 }
10994 if ( oRange === "min" && this.orientation === "vertical" ) {
10995 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
10996 }
10997 if ( oRange === "max" && this.orientation === "vertical" ) {
10998 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
10999 }
11000 }
11001 }
11002
11003 });
11004
11005 $.extend( $.ui.slider, {
11006 version: "1.8.16"
11007 });
11008
11009 }(jQuery));
11010 /*
11011 * jQuery UI Tabs 1.8.16
11012 *
11013 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11014 * Dual licensed under the MIT or GPL Version 2 licenses.
11015 * http://jquery.org/license
11016 *
11017 * http://docs.jquery.com/UI/Tabs
11018 *
11019 * Depends:
11020 * jquery.ui.core.js
11021 * jquery.ui.widget.js
11022 */
11023 (function( $, undefined ) {
11024
11025 var tabId = 0,
11026 listId = 0;
11027
11028 function getNextTabId() {
11029 return ++tabId;
11030 }
11031
11032 function getNextListId() {
11033 return ++listId;
11034 }
11035
11036 $.widget( "ui.tabs", {
11037 options: {
11038 add: null,
11039 ajaxOptions: null,
11040 cache: false,
11041 cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
11042 collapsible: false,
11043 disable: null,
11044 disabled: [],
11045 enable: null,
11046 event: "click",
11047 fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
11048 idPrefix: "ui-tabs-",
11049 load: null,
11050 panelTemplate: "<div></div>",
11051 remove: null,
11052 select: null,
11053 show: null,
11054 spinner: "<em>Loading&#8230;</em>",
11055 tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
11056 },
11057
11058 _create: function() {
11059 this._tabify( true );
11060 },
11061
11062 _setOption: function( key, value ) {
11063 if ( key == "selected" ) {
11064 if (this.options.collapsible && value == this.options.selected ) {
11065 return;
11066 }
11067 this.select( value );
11068 } else {
11069 this.options[ key ] = value;
11070 this._tabify();
11071 }
11072 },
11073
11074 _tabId: function( a ) {
11075 return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
11076 this.options.idPrefix + getNextTabId();
11077 },
11078
11079 _sanitizeSelector: function( hash ) {
11080 // we need this because an id may contain a ":"
11081 return hash.replace( /:/g, "\\:" );
11082 },
11083
11084 _cookie: function() {
11085 var cookie = this.cookie ||
11086 ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
11087 return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
11088 },
11089
11090 _ui: function( tab, panel ) {
11091 return {
11092 tab: tab,
11093 panel: panel,
11094 index: this.anchors.index( tab )
11095 };
11096 },
11097
11098 _cleanup: function() {
11099 // restore all former loading tabs labels
11100 this.lis.filter( ".ui-state-processing" )
11101 .removeClass( "ui-state-processing" )
11102 .find( "span:data(label.tabs)" )
11103 .each(function() {
11104 var el = $( this );
11105 el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
11106 });
11107 },
11108
11109 _tabify: function( init ) {
11110 var self = this,
11111 o = this.options,
11112 fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
11113
11114 this.list = this.element.find( "ol,ul" ).eq( 0 );
11115 this.lis = $( " > li:has(a[href])", this.list );
11116 this.anchors = this.lis.map(function() {
11117 return $( "a", this )[ 0 ];
11118 });
11119 this.panels = $( [] );
11120
11121 this.anchors.each(function( i, a ) {
11122 var href = $( a ).attr( "href" );
11123 // For dynamically created HTML that contains a hash as href IE < 8 expands
11124 // such href to the full page url with hash and then misinterprets tab as ajax.
11125 // Same consideration applies for an added tab with a fragment identifier
11126 // since a[href=#fragment-identifier] does unexpectedly not match.
11127 // Thus normalize href attribute...
11128 var hrefBase = href.split( "#" )[ 0 ],
11129 baseEl;
11130 if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
11131 ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
11132 href = a.hash;
11133 a.href = href;
11134 }
11135
11136 // inline tab
11137 if ( fragmentId.test( href ) ) {
11138 self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) );
11139 // remote tab
11140 // prevent loading the page itself if href is just "#"
11141 } else if ( href && href !== "#" ) {
11142 // required for restore on destroy
11143 $.data( a, "href.tabs", href );
11144
11145 // TODO until #3808 is fixed strip fragment identifier from url
11146 // (IE fails to load from such url)
11147 $.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
11148
11149 var id = self._tabId( a );
11150 a.href = "#" + id;
11151 var $panel = self.element.find( "#" + id );
11152 if ( !$panel.length ) {
11153 $panel = $( o.panelTemplate )
11154 .attr( "id", id )
11155 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
11156 .insertAfter( self.panels[ i - 1 ] || self.list );
11157 $panel.data( "destroy.tabs", true );
11158 }
11159 self.panels = self.panels.add( $panel );
11160 // invalid tab href
11161 } else {
11162 o.disabled.push( i );
11163 }
11164 });
11165
11166 // initialization from scratch
11167 if ( init ) {
11168 // attach necessary classes for styling
11169 this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
11170 this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
11171 this.lis.addClass( "ui-state-default ui-corner-top" );
11172 this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
11173
11174 // Selected tab
11175 // use "selected" option or try to retrieve:
11176 // 1. from fragment identifier in url
11177 // 2. from cookie
11178 // 3. from selected class attribute on <li>
11179 if ( o.selected === undefined ) {
11180 if ( location.hash ) {
11181 this.anchors.each(function( i, a ) {
11182 if ( a.hash == location.hash ) {
11183 o.selected = i;
11184 return false;
11185 }
11186 });
11187 }
11188 if ( typeof o.selected !== "number" && o.cookie ) {
11189 o.selected = parseInt( self._cookie(), 10 );
11190 }
11191 if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
11192 o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
11193 }
11194 o.selected = o.selected || ( this.lis.length ? 0 : -1 );
11195 } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
11196 o.selected = -1;
11197 }
11198
11199 // sanity check - default to first tab...
11200 o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
11201 ? o.selected
11202 : 0;
11203
11204 // Take disabling tabs via class attribute from HTML
11205 // into account and update option properly.
11206 // A selected tab cannot become disabled.
11207 o.disabled = $.unique( o.disabled.concat(
11208 $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
11209 return self.lis.index( n );
11210 })
11211 ) ).sort();
11212
11213 if ( $.inArray( o.selected, o.disabled ) != -1 ) {
11214 o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
11215 }
11216
11217 // highlight selected tab
11218 this.panels.addClass( "ui-tabs-hide" );
11219 this.lis.removeClass( "ui-tabs-selected ui-state-active" );
11220 // check for length avoids error when initializing empty list
11221 if ( o.selected >= 0 && this.anchors.length ) {
11222 self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
11223 this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
11224
11225 // seems to be expected behavior that the show callback is fired
11226 self.element.queue( "tabs", function() {
11227 self._trigger( "show", null,
11228 self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) );
11229 });
11230
11231 this.load( o.selected );
11232 }
11233
11234 // clean up to avoid memory leaks in certain versions of IE 6
11235 // TODO: namespace this event
11236 $( window ).bind( "unload", function() {
11237 self.lis.add( self.anchors ).unbind( ".tabs" );
11238 self.lis = self.anchors = self.panels = null;
11239 });
11240 // update selected after add/remove
11241 } else {
11242 o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
11243 }
11244
11245 // update collapsible
11246 // TODO: use .toggleClass()
11247 this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
11248
11249 // set or update cookie after init and add/remove respectively
11250 if ( o.cookie ) {
11251 this._cookie( o.selected, o.cookie );
11252 }
11253
11254 // disable tabs
11255 for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
11256 $( li )[ $.inArray( i, o.disabled ) != -1 &&
11257 // TODO: use .toggleClass()
11258 !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
11259 }
11260
11261 // reset cache if switching from cached to not cached
11262 if ( o.cache === false ) {
11263 this.anchors.removeData( "cache.tabs" );
11264 }
11265
11266 // remove all handlers before, tabify may run on existing tabs after add or option change
11267 this.lis.add( this.anchors ).unbind( ".tabs" );
11268
11269 if ( o.event !== "mouseover" ) {
11270 var addState = function( state, el ) {
11271 if ( el.is( ":not(.ui-state-disabled)" ) ) {
11272 el.addClass( "ui-state-" + state );
11273 }
11274 };
11275 var removeState = function( state, el ) {
11276 el.removeClass( "ui-state-" + state );
11277 };
11278 this.lis.bind( "mouseover.tabs" , function() {
11279 addState( "hover", $( this ) );
11280 });
11281 this.lis.bind( "mouseout.tabs", function() {
11282 removeState( "hover", $( this ) );
11283 });
11284 this.anchors.bind( "focus.tabs", function() {
11285 addState( "focus", $( this ).closest( "li" ) );
11286 });
11287 this.anchors.bind( "blur.tabs", function() {
11288 removeState( "focus", $( this ).closest( "li" ) );
11289 });
11290 }
11291
11292 // set up animations
11293 var hideFx, showFx;
11294 if ( o.fx ) {
11295 if ( $.isArray( o.fx ) ) {
11296 hideFx = o.fx[ 0 ];
11297 showFx = o.fx[ 1 ];
11298 } else {
11299 hideFx = showFx = o.fx;
11300 }
11301 }
11302
11303 // Reset certain styles left over from animation
11304 // and prevent IE's ClearType bug...
11305 function resetStyle( $el, fx ) {
11306 $el.css( "display", "" );
11307 if ( !$.support.opacity && fx.opacity ) {
11308 $el[ 0 ].style.removeAttribute( "filter" );
11309 }
11310 }
11311
11312 // Show a tab...
11313 var showTab = showFx
11314 ? function( clicked, $show ) {
11315 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
11316 $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
11317 .animate( showFx, showFx.duration || "normal", function() {
11318 resetStyle( $show, showFx );
11319 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
11320 });
11321 }
11322 : function( clicked, $show ) {
11323 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
11324 $show.removeClass( "ui-tabs-hide" );
11325 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
11326 };
11327
11328 // Hide a tab, $show is optional...
11329 var hideTab = hideFx
11330 ? function( clicked, $hide ) {
11331 $hide.animate( hideFx, hideFx.duration || "normal", function() {
11332 self.lis.removeClass( "ui-tabs-selected ui-state-active" );
11333 $hide.addClass( "ui-tabs-hide" );
11334 resetStyle( $hide, hideFx );
11335 self.element.dequeue( "tabs" );
11336 });
11337 }
11338 : function( clicked, $hide, $show ) {
11339 self.lis.removeClass( "ui-tabs-selected ui-state-active" );
11340 $hide.addClass( "ui-tabs-hide" );
11341 self.element.dequeue( "tabs" );
11342 };
11343
11344 // attach tab event handler, unbind to avoid duplicates from former tabifying...
11345 this.anchors.bind( o.event + ".tabs", function() {
11346 var el = this,
11347 $li = $(el).closest( "li" ),
11348 $hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
11349 $show = self.element.find( self._sanitizeSelector( el.hash ) );
11350
11351 // If tab is already selected and not collapsible or tab disabled or
11352 // or is already loading or click callback returns false stop here.
11353 // Check if click handler returns false last so that it is not executed
11354 // for a disabled or loading tab!
11355 if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
11356 $li.hasClass( "ui-state-disabled" ) ||
11357 $li.hasClass( "ui-state-processing" ) ||
11358 self.panels.filter( ":animated" ).length ||
11359 self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
11360 this.blur();
11361 return false;
11362 }
11363
11364 o.selected = self.anchors.index( this );
11365
11366 self.abort();
11367
11368 // if tab may be closed
11369 if ( o.collapsible ) {
11370 if ( $li.hasClass( "ui-tabs-selected" ) ) {
11371 o.selected = -1;
11372
11373 if ( o.cookie ) {
11374 self._cookie( o.selected, o.cookie );
11375 }
11376
11377 self.element.queue( "tabs", function() {
11378 hideTab( el, $hide );
11379 }).dequeue( "tabs" );
11380
11381 this.blur();
11382 return false;
11383 } else if ( !$hide.length ) {
11384 if ( o.cookie ) {
11385 self._cookie( o.selected, o.cookie );
11386 }
11387
11388 self.element.queue( "tabs", function() {
11389 showTab( el, $show );
11390 });
11391
11392 // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
11393 self.load( self.anchors.index( this ) );
11394
11395 this.blur();
11396 return false;
11397 }
11398 }
11399
11400 if ( o.cookie ) {
11401 self._cookie( o.selected, o.cookie );
11402 }
11403
11404 // show new tab
11405 if ( $show.length ) {
11406 if ( $hide.length ) {
11407 self.element.queue( "tabs", function() {
11408 hideTab( el, $hide );
11409 });
11410 }
11411 self.element.queue( "tabs", function() {
11412 showTab( el, $show );
11413 });
11414
11415 self.load( self.anchors.index( this ) );
11416 } else {
11417 throw "jQuery UI Tabs: Mismatching fragment identifier.";
11418 }
11419
11420 // Prevent IE from keeping other link focussed when using the back button
11421 // and remove dotted border from clicked link. This is controlled via CSS
11422 // in modern browsers; blur() removes focus from address bar in Firefox
11423 // which can become a usability and annoying problem with tabs('rotate').
11424 if ( $.browser.msie ) {
11425 this.blur();
11426 }
11427 });
11428
11429 // disable click in any case
11430 this.anchors.bind( "click.tabs", function(){
11431 return false;
11432 });
11433 },
11434
11435 _getIndex: function( index ) {
11436 // meta-function to give users option to provide a href string instead of a numerical index.
11437 // also sanitizes numerical indexes to valid values.
11438 if ( typeof index == "string" ) {
11439 index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
11440 }
11441
11442 return index;
11443 },
11444
11445 destroy: function() {
11446 var o = this.options;
11447
11448 this.abort();
11449
11450 this.element
11451 .unbind( ".tabs" )
11452 .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
11453 .removeData( "tabs" );
11454
11455 this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
11456
11457 this.anchors.each(function() {
11458 var href = $.data( this, "href.tabs" );
11459 if ( href ) {
11460 this.href = href;
11461 }
11462 var $this = $( this ).unbind( ".tabs" );
11463 $.each( [ "href", "load", "cache" ], function( i, prefix ) {
11464 $this.removeData( prefix + ".tabs" );
11465 });
11466 });
11467
11468 this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
11469 if ( $.data( this, "destroy.tabs" ) ) {
11470 $( this ).remove();
11471 } else {
11472 $( this ).removeClass([
11473 "ui-state-default",
11474 "ui-corner-top",
11475 "ui-tabs-selected",
11476 "ui-state-active",
11477 "ui-state-hover",
11478 "ui-state-focus",
11479 "ui-state-disabled",
11480 "ui-tabs-panel",
11481 "ui-widget-content",
11482 "ui-corner-bottom",
11483 "ui-tabs-hide"
11484 ].join( " " ) );
11485 }
11486 });
11487
11488 if ( o.cookie ) {
11489 this._cookie( null, o.cookie );
11490 }
11491
11492 return this;
11493 },
11494
11495 add: function( url, label, index ) {
11496 if ( index === undefined ) {
11497 index = this.anchors.length;
11498 }
11499
11500 var self = this,
11501 o = this.options,
11502 $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
11503 id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
11504
11505 $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
11506
11507 // try to find an existing element before creating a new one
11508 var $panel = self.element.find( "#" + id );
11509 if ( !$panel.length ) {
11510 $panel = $( o.panelTemplate )
11511 .attr( "id", id )
11512 .data( "destroy.tabs", true );
11513 }
11514 $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
11515
11516 if ( index >= this.lis.length ) {
11517 $li.appendTo( this.list );
11518 $panel.appendTo( this.list[ 0 ].parentNode );
11519 } else {
11520 $li.insertBefore( this.lis[ index ] );
11521 $panel.insertBefore( this.panels[ index ] );
11522 }
11523
11524 o.disabled = $.map( o.disabled, function( n, i ) {
11525 return n >= index ? ++n : n;
11526 });
11527
11528 this._tabify();
11529
11530 if ( this.anchors.length == 1 ) {
11531 o.selected = 0;
11532 $li.addClass( "ui-tabs-selected ui-state-active" );
11533 $panel.removeClass( "ui-tabs-hide" );
11534 this.element.queue( "tabs", function() {
11535 self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
11536 });
11537
11538 this.load( 0 );
11539 }
11540
11541 this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
11542 return this;
11543 },
11544
11545 remove: function( index ) {
11546 index = this._getIndex( index );
11547 var o = this.options,
11548 $li = this.lis.eq( index ).remove(),
11549 $panel = this.panels.eq( index ).remove();
11550
11551 // If selected tab was removed focus tab to the right or
11552 // in case the last tab was removed the tab to the left.
11553 if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
11554 this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
11555 }
11556
11557 o.disabled = $.map(
11558 $.grep( o.disabled, function(n, i) {
11559 return n != index;
11560 }),
11561 function( n, i ) {
11562 return n >= index ? --n : n;
11563 });
11564
11565 this._tabify();
11566
11567 this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
11568 return this;
11569 },
11570
11571 enable: function( index ) {
11572 index = this._getIndex( index );
11573 var o = this.options;
11574 if ( $.inArray( index, o.disabled ) == -1 ) {
11575 return;
11576 }
11577
11578 this.lis.eq( index ).removeClass( "ui-state-disabled" );
11579 o.disabled = $.grep( o.disabled, function( n, i ) {
11580 return n != index;
11581 });
11582
11583 this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
11584 return this;
11585 },
11586
11587 disable: function( index ) {
11588 index = this._getIndex( index );
11589 var self = this, o = this.options;
11590 // cannot disable already selected tab
11591 if ( index != o.selected ) {
11592 this.lis.eq( index ).addClass( "ui-state-disabled" );
11593
11594 o.disabled.push( index );
11595 o.disabled.sort();
11596
11597 this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
11598 }
11599
11600 return this;
11601 },
11602
11603 select: function( index ) {
11604 index = this._getIndex( index );
11605 if ( index == -1 ) {
11606 if ( this.options.collapsible && this.options.selected != -1 ) {
11607 index = this.options.selected;
11608 } else {
11609 return this;
11610 }
11611 }
11612 this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
11613 return this;
11614 },
11615
11616 load: function( index ) {
11617 index = this._getIndex( index );
11618 var self = this,
11619 o = this.options,
11620 a = this.anchors.eq( index )[ 0 ],
11621 url = $.data( a, "load.tabs" );
11622
11623 this.abort();
11624
11625 // not remote or from cache
11626 if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
11627 this.element.dequeue( "tabs" );
11628 return;
11629 }
11630
11631 // load remote from here on
11632 this.lis.eq( index ).addClass( "ui-state-processing" );
11633
11634 if ( o.spinner ) {
11635 var span = $( "span", a );
11636 span.data( "label.tabs", span.html() ).html( o.spinner );
11637 }
11638
11639 this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
11640 url: url,
11641 success: function( r, s ) {
11642 self.element.find( self._sanitizeSelector( a.hash ) ).html( r );
11643
11644 // take care of tab labels
11645 self._cleanup();
11646
11647 if ( o.cache ) {
11648 $.data( a, "cache.tabs", true );
11649 }
11650
11651 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
11652 try {
11653 o.ajaxOptions.success( r, s );
11654 }
11655 catch ( e ) {}
11656 },
11657 error: function( xhr, s, e ) {
11658 // take care of tab labels
11659 self._cleanup();
11660
11661 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
11662 try {
11663 // Passing index avoid a race condition when this method is
11664 // called after the user has selected another tab.
11665 // Pass the anchor that initiated this request allows
11666 // loadError to manipulate the tab content panel via $(a.hash)
11667 o.ajaxOptions.error( xhr, s, index, a );
11668 }
11669 catch ( e ) {}
11670 }
11671 } ) );
11672
11673 // last, so that load event is fired before show...
11674 self.element.dequeue( "tabs" );
11675
11676 return this;
11677 },
11678
11679 abort: function() {
11680 // stop possibly running animations
11681 this.element.queue( [] );
11682 this.panels.stop( false, true );
11683
11684 // "tabs" queue must not contain more than two elements,
11685 // which are the callbacks for the latest clicked tab...
11686 this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
11687
11688 // terminate pending requests from other tabs
11689 if ( this.xhr ) {
11690 this.xhr.abort();
11691 delete this.xhr;
11692 }
11693
11694 // take care of tab labels
11695 this._cleanup();
11696 return this;
11697 },
11698
11699 url: function( index, url ) {
11700 this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
11701 return this;
11702 },
11703
11704 length: function() {
11705 return this.anchors.length;
11706 }
11707 });
11708
11709 $.extend( $.ui.tabs, {
11710 version: "1.8.16"
11711 });
11712
11713 /*
11714 * Tabs Extensions
11715 */
11716
11717 /*
11718 * Rotate
11719 */
11720 $.extend( $.ui.tabs.prototype, {
11721 rotation: null,
11722 rotate: function( ms, continuing ) {
11723 var self = this,
11724 o = this.options;
11725
11726 var rotate = self._rotate || ( self._rotate = function( e ) {
11727 clearTimeout( self.rotation );
11728 self.rotation = setTimeout(function() {
11729 var t = o.selected;
11730 self.select( ++t < self.anchors.length ? t : 0 );
11731 }, ms );
11732
11733 if ( e ) {
11734 e.stopPropagation();
11735 }
11736 });
11737
11738 var stop = self._unrotate || ( self._unrotate = !continuing
11739 ? function(e) {
11740 if (e.clientX) { // in case of a true click
11741 self.rotate(null);
11742 }
11743 }
11744 : function( e ) {
11745 t = o.selected;
11746 rotate();
11747 });
11748
11749 // start rotation
11750 if ( ms ) {
11751 this.element.bind( "tabsshow", rotate );
11752 this.anchors.bind( o.event + ".tabs", stop );
11753 rotate();
11754 // stop rotation
11755 } else {
11756 clearTimeout( self.rotation );
11757 this.element.unbind( "tabsshow", rotate );
11758 this.anchors.unbind( o.event + ".tabs", stop );
11759 delete this._rotate;
11760 delete this._unrotate;
11761 }
11762
11763 return this;
11764 }
11765 });
11766
11767 })( jQuery );