source: dashboard/lib/js/jquery-ui-latest.js@ 370

Last change on this file since 370 was 335, checked in by Rick van der Zwet, 13 years ago

New layout and UI

File size: 368.7 KB
Line 
1/*!
2 * jQuery UI 1.8.7
3 *
4 * Copyright 2010, 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 || {};
16if ( $.ui.version ) {
17 return;
18}
19
20$.extend( $.ui, {
21 version: "1.8.7",
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 _focus: $.fn.focus,
62 focus: function( delay, fn ) {
63 return typeof delay === "number" ?
64 this.each(function() {
65 var elem = this;
66 setTimeout(function() {
67 $( elem ).focus();
68 if ( fn ) {
69 fn.call( elem );
70 }
71 }, delay );
72 }) :
73 this._focus.apply( this, arguments );
74 },
75
76 scrollParent: function() {
77 var scrollParent;
78 if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
79 scrollParent = this.parents().filter(function() {
80 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));
81 }).eq(0);
82 } else {
83 scrollParent = this.parents().filter(function() {
84 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
85 }).eq(0);
86 }
87
88 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
89 },
90
91 zIndex: function( zIndex ) {
92 if ( zIndex !== undefined ) {
93 return this.css( "zIndex", zIndex );
94 }
95
96 if ( this.length ) {
97 var elem = $( this[ 0 ] ), position, value;
98 while ( elem.length && elem[ 0 ] !== document ) {
99 // Ignore z-index if position is set to a value where z-index is ignored by the browser
100 // This makes behavior of this function consistent across browsers
101 // WebKit always returns auto if the element is positioned
102 position = elem.css( "position" );
103 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
104 // IE returns 0 when zIndex is not specified
105 // other browsers return a string
106 // we ignore the case of nested elements with an explicit value of 0
107 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
108 value = parseInt( elem.css( "zIndex" ), 10 );
109 if ( !isNaN( value ) && value !== 0 ) {
110 return value;
111 }
112 }
113 elem = elem.parent();
114 }
115 }
116
117 return 0;
118 },
119
120 disableSelection: function() {
121 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
122 ".ui-disableSelection", function( event ) {
123 event.preventDefault();
124 });
125 },
126
127 enableSelection: function() {
128 return this.unbind( ".ui-disableSelection" );
129 }
130});
131
132$.each( [ "Width", "Height" ], function( i, name ) {
133 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
134 type = name.toLowerCase(),
135 orig = {
136 innerWidth: $.fn.innerWidth,
137 innerHeight: $.fn.innerHeight,
138 outerWidth: $.fn.outerWidth,
139 outerHeight: $.fn.outerHeight
140 };
141
142 function reduce( elem, size, border, margin ) {
143 $.each( side, function() {
144 size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
145 if ( border ) {
146 size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
147 }
148 if ( margin ) {
149 size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
150 }
151 });
152 return size;
153 }
154
155 $.fn[ "inner" + name ] = function( size ) {
156 if ( size === undefined ) {
157 return orig[ "inner" + name ].call( this );
158 }
159
160 return this.each(function() {
161 $( this ).css( type, reduce( this, size ) + "px" );
162 });
163 };
164
165 $.fn[ "outer" + name] = function( size, margin ) {
166 if ( typeof size !== "number" ) {
167 return orig[ "outer" + name ].call( this, size );
168 }
169
170 return this.each(function() {
171 $( this).css( type, reduce( this, size, true, margin ) + "px" );
172 });
173 };
174});
175
176// selectors
177function visible( element ) {
178 return !$( element ).parents().andSelf().filter(function() {
179 return $.curCSS( this, "visibility" ) === "hidden" ||
180 $.expr.filters.hidden( this );
181 }).length;
182}
183
184$.extend( $.expr[ ":" ], {
185 data: function( elem, i, match ) {
186 return !!$.data( elem, match[ 3 ] );
187 },
188
189 focusable: function( element ) {
190 var nodeName = element.nodeName.toLowerCase(),
191 tabIndex = $.attr( element, "tabindex" );
192 if ( "area" === nodeName ) {
193 var map = element.parentNode,
194 mapName = map.name,
195 img;
196 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
197 return false;
198 }
199 img = $( "img[usemap=#" + mapName + "]" )[0];
200 return !!img && visible( img );
201 }
202 return ( /input|select|textarea|button|object/.test( nodeName )
203 ? !element.disabled
204 : "a" == nodeName
205 ? element.href || !isNaN( tabIndex )
206 : !isNaN( tabIndex ))
207 // the element and all of its ancestors must be visible
208 && visible( element );
209 },
210
211 tabbable: function( element ) {
212 var tabIndex = $.attr( element, "tabindex" );
213 return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
214 }
215});
216
217// support
218$(function() {
219 var body = document.body,
220 div = body.appendChild( div = document.createElement( "div" ) );
221
222 $.extend( div.style, {
223 minHeight: "100px",
224 height: "auto",
225 padding: 0,
226 borderWidth: 0
227 });
228
229 $.support.minHeight = div.offsetHeight === 100;
230 $.support.selectstart = "onselectstart" in div;
231
232 // set display to none to avoid a layout bug in IE
233 // http://dev.jquery.com/ticket/4014
234 body.removeChild( div ).style.display = "none";
235});
236
237
238
239
240
241// deprecated
242$.extend( $.ui, {
243 // $.ui.plugin is deprecated. Use the proxy pattern instead.
244 plugin: {
245 add: function( module, option, set ) {
246 var proto = $.ui[ module ].prototype;
247 for ( var i in set ) {
248 proto.plugins[ i ] = proto.plugins[ i ] || [];
249 proto.plugins[ i ].push( [ option, set[ i ] ] );
250 }
251 },
252 call: function( instance, name, args ) {
253 var set = instance.plugins[ name ];
254 if ( !set || !instance.element[ 0 ].parentNode ) {
255 return;
256 }
257
258 for ( var i = 0; i < set.length; i++ ) {
259 if ( instance.options[ set[ i ][ 0 ] ] ) {
260 set[ i ][ 1 ].apply( instance.element, args );
261 }
262 }
263 }
264 },
265
266 // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
267 contains: function( a, b ) {
268 return document.compareDocumentPosition ?
269 a.compareDocumentPosition( b ) & 16 :
270 a !== b && a.contains( b );
271 },
272
273 // only used by resizable
274 hasScroll: function( el, a ) {
275
276 //If overflow is hidden, the element might have extra content, but the user wants to hide it
277 if ( $( el ).css( "overflow" ) === "hidden") {
278 return false;
279 }
280
281 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
282 has = false;
283
284 if ( el[ scroll ] > 0 ) {
285 return true;
286 }
287
288 // TODO: determine which cases actually cause this to happen
289 // if the element doesn't have the scroll set, see if it's possible to
290 // set the scroll
291 el[ scroll ] = 1;
292 has = ( el[ scroll ] > 0 );
293 el[ scroll ] = 0;
294 return has;
295 },
296
297 // these are odd functions, fix the API or move into individual plugins
298 isOverAxis: function( x, reference, size ) {
299 //Determines when x coordinate is over "b" element axis
300 return ( x > reference ) && ( x < ( reference + size ) );
301 },
302 isOver: function( y, x, top, left, height, width ) {
303 //Determines when x, y coordinates is over "b" element
304 return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
305 }
306});
307
308})( jQuery );
309/*!
310 * jQuery UI Widget 1.8.7
311 *
312 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
313 * Dual licensed under the MIT or GPL Version 2 licenses.
314 * http://jquery.org/license
315 *
316 * http://docs.jquery.com/UI/Widget
317 */
318(function( $, undefined ) {
319
320// jQuery 1.4+
321if ( $.cleanData ) {
322 var _cleanData = $.cleanData;
323 $.cleanData = function( elems ) {
324 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
325 $( elem ).triggerHandler( "remove" );
326 }
327 _cleanData( elems );
328 };
329} else {
330 var _remove = $.fn.remove;
331 $.fn.remove = function( selector, keepData ) {
332 return this.each(function() {
333 if ( !keepData ) {
334 if ( !selector || $.filter( selector, [ this ] ).length ) {
335 $( "*", this ).add( [ this ] ).each(function() {
336 $( this ).triggerHandler( "remove" );
337 });
338 }
339 }
340 return _remove.call( $(this), selector, keepData );
341 });
342 };
343}
344
345$.widget = function( name, base, prototype ) {
346 var namespace = name.split( "." )[ 0 ],
347 fullName;
348 name = name.split( "." )[ 1 ];
349 fullName = namespace + "-" + name;
350
351 if ( !prototype ) {
352 prototype = base;
353 base = $.Widget;
354 }
355
356 // create selector for plugin
357 $.expr[ ":" ][ fullName ] = function( elem ) {
358 return !!$.data( elem, name );
359 };
360
361 $[ namespace ] = $[ namespace ] || {};
362 $[ namespace ][ name ] = function( options, element ) {
363 // allow instantiation without initializing for simple inheritance
364 if ( arguments.length ) {
365 this._createWidget( options, element );
366 }
367 };
368
369 var basePrototype = new base();
370 // we need to make the options hash a property directly on the new instance
371 // otherwise we'll modify the options hash on the prototype that we're
372 // inheriting from
373// $.each( basePrototype, function( key, val ) {
374// if ( $.isPlainObject(val) ) {
375// basePrototype[ key ] = $.extend( {}, val );
376// }
377// });
378 basePrototype.options = $.extend( true, {}, basePrototype.options );
379 $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
380 namespace: namespace,
381 widgetName: name,
382 widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
383 widgetBaseClass: fullName
384 }, prototype );
385
386 $.widget.bridge( name, $[ namespace ][ name ] );
387};
388
389$.widget.bridge = function( name, object ) {
390 $.fn[ name ] = function( options ) {
391 var isMethodCall = typeof options === "string",
392 args = Array.prototype.slice.call( arguments, 1 ),
393 returnValue = this;
394
395 // allow multiple hashes to be passed on init
396 options = !isMethodCall && args.length ?
397 $.extend.apply( null, [ true, options ].concat(args) ) :
398 options;
399
400 // prevent calls to internal methods
401 if ( isMethodCall && options.charAt( 0 ) === "_" ) {
402 return returnValue;
403 }
404
405 if ( isMethodCall ) {
406 this.each(function() {
407 var instance = $.data( this, name ),
408 methodValue = instance && $.isFunction( instance[options] ) ?
409 instance[ options ].apply( instance, args ) :
410 instance;
411 // TODO: add this back in 1.9 and use $.error() (see #5972)
412// if ( !instance ) {
413// throw "cannot call methods on " + name + " prior to initialization; " +
414// "attempted to call method '" + options + "'";
415// }
416// if ( !$.isFunction( instance[options] ) ) {
417// throw "no such method '" + options + "' for " + name + " widget instance";
418// }
419// var methodValue = instance[ options ].apply( instance, args );
420 if ( methodValue !== instance && methodValue !== undefined ) {
421 returnValue = methodValue;
422 return false;
423 }
424 });
425 } else {
426 this.each(function() {
427 var instance = $.data( this, name );
428 if ( instance ) {
429 instance.option( options || {} )._init();
430 } else {
431 $.data( this, name, new object( options, this ) );
432 }
433 });
434 }
435
436 return returnValue;
437 };
438};
439
440$.Widget = function( options, element ) {
441 // allow instantiation without initializing for simple inheritance
442 if ( arguments.length ) {
443 this._createWidget( options, element );
444 }
445};
446
447$.Widget.prototype = {
448 widgetName: "widget",
449 widgetEventPrefix: "",
450 options: {
451 disabled: false
452 },
453 _createWidget: function( options, element ) {
454 // $.widget.bridge stores the plugin instance, but we do it anyway
455 // so that it's stored even before the _create function runs
456 $.data( element, this.widgetName, this );
457 this.element = $( element );
458 this.options = $.extend( true, {},
459 this.options,
460 this._getCreateOptions(),
461 options );
462
463 var self = this;
464 this.element.bind( "remove." + this.widgetName, function() {
465 self.destroy();
466 });
467
468 this._create();
469 this._trigger( "create" );
470 this._init();
471 },
472 _getCreateOptions: function() {
473 return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
474 },
475 _create: function() {},
476 _init: function() {},
477
478 destroy: function() {
479 this.element
480 .unbind( "." + this.widgetName )
481 .removeData( this.widgetName );
482 this.widget()
483 .unbind( "." + this.widgetName )
484 .removeAttr( "aria-disabled" )
485 .removeClass(
486 this.widgetBaseClass + "-disabled " +
487 "ui-state-disabled" );
488 },
489
490 widget: function() {
491 return this.element;
492 },
493
494 option: function( key, value ) {
495 var options = key;
496
497 if ( arguments.length === 0 ) {
498 // don't return a reference to the internal hash
499 return $.extend( {}, this.options );
500 }
501
502 if (typeof key === "string" ) {
503 if ( value === undefined ) {
504 return this.options[ key ];
505 }
506 options = {};
507 options[ key ] = value;
508 }
509
510 this._setOptions( options );
511
512 return this;
513 },
514 _setOptions: function( options ) {
515 var self = this;
516 $.each( options, function( key, value ) {
517 self._setOption( key, value );
518 });
519
520 return this;
521 },
522 _setOption: function( key, value ) {
523 this.options[ key ] = value;
524
525 if ( key === "disabled" ) {
526 this.widget()
527 [ value ? "addClass" : "removeClass"](
528 this.widgetBaseClass + "-disabled" + " " +
529 "ui-state-disabled" )
530 .attr( "aria-disabled", value );
531 }
532
533 return this;
534 },
535
536 enable: function() {
537 return this._setOption( "disabled", false );
538 },
539 disable: function() {
540 return this._setOption( "disabled", true );
541 },
542
543 _trigger: function( type, event, data ) {
544 var callback = this.options[ type ];
545
546 event = $.Event( event );
547 event.type = ( type === this.widgetEventPrefix ?
548 type :
549 this.widgetEventPrefix + type ).toLowerCase();
550 data = data || {};
551
552 // copy original event properties over to the new event
553 // this would happen if we could call $.event.fix instead of $.Event
554 // but we don't have a way to force an event to be fixed multiple times
555 if ( event.originalEvent ) {
556 for ( var i = $.event.props.length, prop; i; ) {
557 prop = $.event.props[ --i ];
558 event[ prop ] = event.originalEvent[ prop ];
559 }
560 }
561
562 this.element.trigger( event, data );
563
564 return !( $.isFunction(callback) &&
565 callback.call( this.element[0], event, data ) === false ||
566 event.isDefaultPrevented() );
567 }
568};
569
570})( jQuery );
571/*!
572 * jQuery UI Mouse 1.8.7
573 *
574 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
575 * Dual licensed under the MIT or GPL Version 2 licenses.
576 * http://jquery.org/license
577 *
578 * http://docs.jquery.com/UI/Mouse
579 *
580 * Depends:
581 * jquery.ui.widget.js
582 */
583(function( $, undefined ) {
584
585$.widget("ui.mouse", {
586 options: {
587 cancel: ':input,option',
588 distance: 1,
589 delay: 0
590 },
591 _mouseInit: function() {
592 var self = this;
593
594 this.element
595 .bind('mousedown.'+this.widgetName, function(event) {
596 return self._mouseDown(event);
597 })
598 .bind('click.'+this.widgetName, function(event) {
599 if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
600 $.removeData(event.target, self.widgetName + '.preventClickEvent');
601 event.stopImmediatePropagation();
602 return false;
603 }
604 });
605
606 this.started = false;
607 },
608
609 // TODO: make sure destroying one instance of mouse doesn't mess with
610 // other instances of mouse
611 _mouseDestroy: function() {
612 this.element.unbind('.'+this.widgetName);
613 },
614
615 _mouseDown: function(event) {
616 // don't let more than one widget handle mouseStart
617 // TODO: figure out why we have to use originalEvent
618 event.originalEvent = event.originalEvent || {};
619 if (event.originalEvent.mouseHandled) { return; }
620
621 // we may have missed mouseup (out of window)
622 (this._mouseStarted && this._mouseUp(event));
623
624 this._mouseDownEvent = event;
625
626 var self = this,
627 btnIsLeft = (event.which == 1),
628 elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
629 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
630 return true;
631 }
632
633 this.mouseDelayMet = !this.options.delay;
634 if (!this.mouseDelayMet) {
635 this._mouseDelayTimer = setTimeout(function() {
636 self.mouseDelayMet = true;
637 }, this.options.delay);
638 }
639
640 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
641 this._mouseStarted = (this._mouseStart(event) !== false);
642 if (!this._mouseStarted) {
643 event.preventDefault();
644 return true;
645 }
646 }
647
648 // these delegates are required to keep context
649 this._mouseMoveDelegate = function(event) {
650 return self._mouseMove(event);
651 };
652 this._mouseUpDelegate = function(event) {
653 return self._mouseUp(event);
654 };
655 $(document)
656 .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
657 .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
658
659 event.preventDefault();
660 event.originalEvent.mouseHandled = true;
661 return true;
662 },
663
664 _mouseMove: function(event) {
665 // IE mouseup check - mouseup happened when mouse was out of window
666 if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
667 return this._mouseUp(event);
668 }
669
670 if (this._mouseStarted) {
671 this._mouseDrag(event);
672 return event.preventDefault();
673 }
674
675 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
676 this._mouseStarted =
677 (this._mouseStart(this._mouseDownEvent, event) !== false);
678 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
679 }
680
681 return !this._mouseStarted;
682 },
683
684 _mouseUp: function(event) {
685 $(document)
686 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
687 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
688
689 if (this._mouseStarted) {
690 this._mouseStarted = false;
691
692 if (event.target == this._mouseDownEvent.target) {
693 $.data(event.target, this.widgetName + '.preventClickEvent', true);
694 }
695
696 this._mouseStop(event);
697 }
698
699 return false;
700 },
701
702 _mouseDistanceMet: function(event) {
703 return (Math.max(
704 Math.abs(this._mouseDownEvent.pageX - event.pageX),
705 Math.abs(this._mouseDownEvent.pageY - event.pageY)
706 ) >= this.options.distance
707 );
708 },
709
710 _mouseDelayMet: function(event) {
711 return this.mouseDelayMet;
712 },
713
714 // These are placeholder methods, to be overriden by extending plugin
715 _mouseStart: function(event) {},
716 _mouseDrag: function(event) {},
717 _mouseStop: function(event) {},
718 _mouseCapture: function(event) { return true; }
719});
720
721})(jQuery);
722/*
723 * jQuery UI Draggable 1.8.7
724 *
725 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
726 * Dual licensed under the MIT or GPL Version 2 licenses.
727 * http://jquery.org/license
728 *
729 * http://docs.jquery.com/UI/Draggables
730 *
731 * Depends:
732 * jquery.ui.core.js
733 * jquery.ui.mouse.js
734 * jquery.ui.widget.js
735 */
736(function( $, undefined ) {
737
738$.widget("ui.draggable", $.ui.mouse, {
739 widgetEventPrefix: "drag",
740 options: {
741 addClasses: true,
742 appendTo: "parent",
743 axis: false,
744 connectToSortable: false,
745 containment: false,
746 cursor: "auto",
747 cursorAt: false,
748 grid: false,
749 handle: false,
750 helper: "original",
751 iframeFix: false,
752 opacity: false,
753 refreshPositions: false,
754 revert: false,
755 revertDuration: 500,
756 scope: "default",
757 scroll: true,
758 scrollSensitivity: 20,
759 scrollSpeed: 20,
760 snap: false,
761 snapMode: "both",
762 snapTolerance: 20,
763 stack: false,
764 zIndex: false
765 },
766 _create: function() {
767
768 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
769 this.element[0].style.position = 'relative';
770
771 (this.options.addClasses && this.element.addClass("ui-draggable"));
772 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
773
774 this._mouseInit();
775
776 },
777
778 destroy: function() {
779 if(!this.element.data('draggable')) return;
780 this.element
781 .removeData("draggable")
782 .unbind(".draggable")
783 .removeClass("ui-draggable"
784 + " ui-draggable-dragging"
785 + " ui-draggable-disabled");
786 this._mouseDestroy();
787
788 return this;
789 },
790
791 _mouseCapture: function(event) {
792
793 var o = this.options;
794
795 // among others, prevent a drag on a resizable-handle
796 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
797 return false;
798
799 //Quit if we're not on a valid handle
800 this.handle = this._getHandle(event);
801 if (!this.handle)
802 return false;
803
804 return true;
805
806 },
807
808 _mouseStart: function(event) {
809
810 var o = this.options;
811
812 //Create and append the visible helper
813 this.helper = this._createHelper(event);
814
815 //Cache the helper size
816 this._cacheHelperProportions();
817
818 //If ddmanager is used for droppables, set the global draggable
819 if($.ui.ddmanager)
820 $.ui.ddmanager.current = this;
821
822 /*
823 * - Position generation -
824 * This block generates everything position related - it's the core of draggables.
825 */
826
827 //Cache the margins of the original element
828 this._cacheMargins();
829
830 //Store the helper's css position
831 this.cssPosition = this.helper.css("position");
832 this.scrollParent = this.helper.scrollParent();
833
834 //The element's absolute position on the page minus margins
835 this.offset = this.positionAbs = this.element.offset();
836 this.offset = {
837 top: this.offset.top - this.margins.top,
838 left: this.offset.left - this.margins.left
839 };
840
841 $.extend(this.offset, {
842 click: { //Where the click happened, relative to the element
843 left: event.pageX - this.offset.left,
844 top: event.pageY - this.offset.top
845 },
846 parent: this._getParentOffset(),
847 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
848 });
849
850 //Generate the original position
851 this.originalPosition = this.position = this._generatePosition(event);
852 this.originalPageX = event.pageX;
853 this.originalPageY = event.pageY;
854
855 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
856 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
857
858 //Set a containment if given in the options
859 if(o.containment)
860 this._setContainment();
861
862 //Trigger event + callbacks
863 if(this._trigger("start", event) === false) {
864 this._clear();
865 return false;
866 }
867
868 //Recache the helper size
869 this._cacheHelperProportions();
870
871 //Prepare the droppable offsets
872 if ($.ui.ddmanager && !o.dropBehaviour)
873 $.ui.ddmanager.prepareOffsets(this, event);
874
875 this.helper.addClass("ui-draggable-dragging");
876 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
877 return true;
878 },
879
880 _mouseDrag: function(event, noPropagation) {
881
882 //Compute the helpers position
883 this.position = this._generatePosition(event);
884 this.positionAbs = this._convertPositionTo("absolute");
885
886 //Call plugins and callbacks and use the resulting position if something is returned
887 if (!noPropagation) {
888 var ui = this._uiHash();
889 if(this._trigger('drag', event, ui) === false) {
890 this._mouseUp({});
891 return false;
892 }
893 this.position = ui.position;
894 }
895
896 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
897 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
898 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
899
900 return false;
901 },
902
903 _mouseStop: function(event) {
904
905 //If we are using droppables, inform the manager about the drop
906 var dropped = false;
907 if ($.ui.ddmanager && !this.options.dropBehaviour)
908 dropped = $.ui.ddmanager.drop(this, event);
909
910 //if a drop comes from outside (a sortable)
911 if(this.dropped) {
912 dropped = this.dropped;
913 this.dropped = false;
914 }
915
916 //if the original element is removed, don't bother to continue
917 if(!this.element[0] || !this.element[0].parentNode)
918 return false;
919
920 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))) {
921 var self = this;
922 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
923 if(self._trigger("stop", event) !== false) {
924 self._clear();
925 }
926 });
927 } else {
928 if(this._trigger("stop", event) !== false) {
929 this._clear();
930 }
931 }
932
933 return false;
934 },
935
936 cancel: function() {
937
938 if(this.helper.is(".ui-draggable-dragging")) {
939 this._mouseUp({});
940 } else {
941 this._clear();
942 }
943
944 return this;
945
946 },
947
948 _getHandle: function(event) {
949
950 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
951 $(this.options.handle, this.element)
952 .find("*")
953 .andSelf()
954 .each(function() {
955 if(this == event.target) handle = true;
956 });
957
958 return handle;
959
960 },
961
962 _createHelper: function(event) {
963
964 var o = this.options;
965 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
966
967 if(!helper.parents('body').length)
968 helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
969
970 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
971 helper.css("position", "absolute");
972
973 return helper;
974
975 },
976
977 _adjustOffsetFromHelper: function(obj) {
978 if (typeof obj == 'string') {
979 obj = obj.split(' ');
980 }
981 if ($.isArray(obj)) {
982 obj = {left: +obj[0], top: +obj[1] || 0};
983 }
984 if ('left' in obj) {
985 this.offset.click.left = obj.left + this.margins.left;
986 }
987 if ('right' in obj) {
988 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
989 }
990 if ('top' in obj) {
991 this.offset.click.top = obj.top + this.margins.top;
992 }
993 if ('bottom' in obj) {
994 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
995 }
996 },
997
998 _getParentOffset: function() {
999
1000 //Get the offsetParent and cache its position
1001 this.offsetParent = this.helper.offsetParent();
1002 var po = this.offsetParent.offset();
1003
1004 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1005 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1006 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1007 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1008 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
1009 po.left += this.scrollParent.scrollLeft();
1010 po.top += this.scrollParent.scrollTop();
1011 }
1012
1013 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
1014 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
1015 po = { top: 0, left: 0 };
1016
1017 return {
1018 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1019 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1020 };
1021
1022 },
1023
1024 _getRelativeOffset: function() {
1025
1026 if(this.cssPosition == "relative") {
1027 var p = this.element.position();
1028 return {
1029 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1030 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1031 };
1032 } else {
1033 return { top: 0, left: 0 };
1034 }
1035
1036 },
1037
1038 _cacheMargins: function() {
1039 this.margins = {
1040 left: (parseInt(this.element.css("marginLeft"),10) || 0),
1041 top: (parseInt(this.element.css("marginTop"),10) || 0)
1042 };
1043 },
1044
1045 _cacheHelperProportions: function() {
1046 this.helperProportions = {
1047 width: this.helper.outerWidth(),
1048 height: this.helper.outerHeight()
1049 };
1050 },
1051
1052 _setContainment: function() {
1053
1054 var o = this.options;
1055 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
1056 if(o.containment == 'document' || o.containment == 'window') this.containment = [
1057 (o.containment == 'document' ? 0 : $(window).scrollLeft()) - this.offset.relative.left - this.offset.parent.left,
1058 (o.containment == 'document' ? 0 : $(window).scrollTop()) - this.offset.relative.top - this.offset.parent.top,
1059 (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
1060 (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
1061 ];
1062
1063 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
1064 var ce = $(o.containment)[0]; if(!ce) return;
1065 var co = $(o.containment).offset();
1066 var over = ($(ce).css("overflow") != 'hidden');
1067
1068 this.containment = [
1069 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
1070 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
1071 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,
1072 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
1073 ];
1074 } else if(o.containment.constructor == Array) {
1075 this.containment = o.containment;
1076 }
1077
1078 },
1079
1080 _convertPositionTo: function(d, pos) {
1081
1082 if(!pos) pos = this.position;
1083 var mod = d == "absolute" ? 1 : -1;
1084 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);
1085
1086 return {
1087 top: (
1088 pos.top // The absolute mouse position
1089 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1090 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
1091 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
1092 ),
1093 left: (
1094 pos.left // The absolute mouse position
1095 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1096 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
1097 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
1098 )
1099 };
1100
1101 },
1102
1103 _generatePosition: function(event) {
1104
1105 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);
1106 var pageX = event.pageX;
1107 var pageY = event.pageY;
1108
1109 /*
1110 * - Position constraining -
1111 * Constrain the position to a mix of grid, containment.
1112 */
1113
1114 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
1115
1116 if(this.containment) {
1117 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
1118 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
1119 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
1120 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
1121 }
1122
1123 if(o.grid) {
1124 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
1125 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;
1126
1127 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
1128 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;
1129 }
1130
1131 }
1132
1133 return {
1134 top: (
1135 pageY // The absolute mouse position
1136 - this.offset.click.top // Click offset (relative to the element)
1137 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
1138 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
1139 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
1140 ),
1141 left: (
1142 pageX // The absolute mouse position
1143 - this.offset.click.left // Click offset (relative to the element)
1144 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
1145 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
1146 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
1147 )
1148 };
1149
1150 },
1151
1152 _clear: function() {
1153 this.helper.removeClass("ui-draggable-dragging");
1154 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
1155 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
1156 this.helper = null;
1157 this.cancelHelperRemoval = false;
1158 },
1159
1160 // From now on bulk stuff - mainly helpers
1161
1162 _trigger: function(type, event, ui) {
1163 ui = ui || this._uiHash();
1164 $.ui.plugin.call(this, type, [event, ui]);
1165 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
1166 return $.Widget.prototype._trigger.call(this, type, event, ui);
1167 },
1168
1169 plugins: {},
1170
1171 _uiHash: function(event) {
1172 return {
1173 helper: this.helper,
1174 position: this.position,
1175 originalPosition: this.originalPosition,
1176 offset: this.positionAbs
1177 };
1178 }
1179
1180});
1181
1182$.extend($.ui.draggable, {
1183 version: "1.8.7"
1184});
1185
1186$.ui.plugin.add("draggable", "connectToSortable", {
1187 start: function(event, ui) {
1188
1189 var inst = $(this).data("draggable"), o = inst.options,
1190 uiSortable = $.extend({}, ui, { item: inst.element });
1191 inst.sortables = [];
1192 $(o.connectToSortable).each(function() {
1193 var sortable = $.data(this, 'sortable');
1194 if (sortable && !sortable.options.disabled) {
1195 inst.sortables.push({
1196 instance: sortable,
1197 shouldRevert: sortable.options.revert
1198 });
1199 sortable._refreshItems(); //Do a one-time refresh at start to refresh the containerCache
1200 sortable._trigger("activate", event, uiSortable);
1201 }
1202 });
1203
1204 },
1205 stop: function(event, ui) {
1206
1207 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1208 var inst = $(this).data("draggable"),
1209 uiSortable = $.extend({}, ui, { item: inst.element });
1210
1211 $.each(inst.sortables, function() {
1212 if(this.instance.isOver) {
1213
1214 this.instance.isOver = 0;
1215
1216 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
1217 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1218
1219 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
1220 if(this.shouldRevert) this.instance.options.revert = true;
1221
1222 //Trigger the stop of the sortable
1223 this.instance._mouseStop(event);
1224
1225 this.instance.options.helper = this.instance.options._helper;
1226
1227 //If the helper has been the original item, restore properties in the sortable
1228 if(inst.options.helper == 'original')
1229 this.instance.currentItem.css({ top: 'auto', left: 'auto' });
1230
1231 } else {
1232 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1233 this.instance._trigger("deactivate", event, uiSortable);
1234 }
1235
1236 });
1237
1238 },
1239 drag: function(event, ui) {
1240
1241 var inst = $(this).data("draggable"), self = this;
1242
1243 var checkPos = function(o) {
1244 var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
1245 var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
1246 var itemHeight = o.height, itemWidth = o.width;
1247 var itemTop = o.top, itemLeft = o.left;
1248
1249 return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
1250 };
1251
1252 $.each(inst.sortables, function(i) {
1253
1254 //Copy over some variables to allow calling the sortable's native _intersectsWith
1255 this.instance.positionAbs = inst.positionAbs;
1256 this.instance.helperProportions = inst.helperProportions;
1257 this.instance.offset.click = inst.offset.click;
1258
1259 if(this.instance._intersectsWith(this.instance.containerCache)) {
1260
1261 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1262 if(!this.instance.isOver) {
1263
1264 this.instance.isOver = 1;
1265 //Now we fake the start of dragging for the sortable instance,
1266 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1267 //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)
1268 this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
1269 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1270 this.instance.options.helper = function() { return ui.helper[0]; };
1271
1272 event.target = this.instance.currentItem[0];
1273 this.instance._mouseCapture(event, true);
1274 this.instance._mouseStart(event, true, true);
1275
1276 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1277 this.instance.offset.click.top = inst.offset.click.top;
1278 this.instance.offset.click.left = inst.offset.click.left;
1279 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1280 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1281
1282 inst._trigger("toSortable", event);
1283 inst.dropped = this.instance.element; //draggable revert needs that
1284 //hack so receive/update callbacks work (mostly)
1285 inst.currentItem = inst.element;
1286 this.instance.fromOutside = inst;
1287
1288 }
1289
1290 //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
1291 if(this.instance.currentItem) this.instance._mouseDrag(event);
1292
1293 } else {
1294
1295 //If it doesn't intersect with the sortable, and it intersected before,
1296 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1297 if(this.instance.isOver) {
1298
1299 this.instance.isOver = 0;
1300 this.instance.cancelHelperRemoval = true;
1301
1302 //Prevent reverting on this forced stop
1303 this.instance.options.revert = false;
1304
1305 // The out event needs to be triggered independently
1306 this.instance._trigger('out', event, this.instance._uiHash(this.instance));
1307
1308 this.instance._mouseStop(event, true);
1309 this.instance.options.helper = this.instance.options._helper;
1310
1311 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1312 this.instance.currentItem.remove();
1313 if(this.instance.placeholder) this.instance.placeholder.remove();
1314
1315 inst._trigger("fromSortable", event);
1316 inst.dropped = false; //draggable revert needs that
1317 }
1318
1319 };
1320
1321 });
1322
1323 }
1324});
1325
1326$.ui.plugin.add("draggable", "cursor", {
1327 start: function(event, ui) {
1328 var t = $('body'), o = $(this).data('draggable').options;
1329 if (t.css("cursor")) o._cursor = t.css("cursor");
1330 t.css("cursor", o.cursor);
1331 },
1332 stop: function(event, ui) {
1333 var o = $(this).data('draggable').options;
1334 if (o._cursor) $('body').css("cursor", o._cursor);
1335 }
1336});
1337
1338$.ui.plugin.add("draggable", "iframeFix", {
1339 start: function(event, ui) {
1340 var o = $(this).data('draggable').options;
1341 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1342 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
1343 .css({
1344 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
1345 position: "absolute", opacity: "0.001", zIndex: 1000
1346 })
1347 .css($(this).offset())
1348 .appendTo("body");
1349 });
1350 },
1351 stop: function(event, ui) {
1352 $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
1353 }
1354});
1355
1356$.ui.plugin.add("draggable", "opacity", {
1357 start: function(event, ui) {
1358 var t = $(ui.helper), o = $(this).data('draggable').options;
1359 if(t.css("opacity")) o._opacity = t.css("opacity");
1360 t.css('opacity', o.opacity);
1361 },
1362 stop: function(event, ui) {
1363 var o = $(this).data('draggable').options;
1364 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
1365 }
1366});
1367
1368$.ui.plugin.add("draggable", "scroll", {
1369 start: function(event, ui) {
1370 var i = $(this).data("draggable");
1371 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
1372 },
1373 drag: function(event, ui) {
1374
1375 var i = $(this).data("draggable"), o = i.options, scrolled = false;
1376
1377 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
1378
1379 if(!o.axis || o.axis != 'x') {
1380 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
1381 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1382 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
1383 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1384 }
1385
1386 if(!o.axis || o.axis != 'y') {
1387 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
1388 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1389 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
1390 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1391 }
1392
1393 } else {
1394
1395 if(!o.axis || o.axis != 'x') {
1396 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
1397 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1398 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
1399 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1400 }
1401
1402 if(!o.axis || o.axis != 'y') {
1403 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
1404 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1405 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
1406 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1407 }
1408
1409 }
1410
1411 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
1412 $.ui.ddmanager.prepareOffsets(i, event);
1413
1414 }
1415});
1416
1417$.ui.plugin.add("draggable", "snap", {
1418 start: function(event, ui) {
1419
1420 var i = $(this).data("draggable"), o = i.options;
1421 i.snapElements = [];
1422
1423 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
1424 var $t = $(this); var $o = $t.offset();
1425 if(this != i.element[0]) i.snapElements.push({
1426 item: this,
1427 width: $t.outerWidth(), height: $t.outerHeight(),
1428 top: $o.top, left: $o.left
1429 });
1430 });
1431
1432 },
1433 drag: function(event, ui) {
1434
1435 var inst = $(this).data("draggable"), o = inst.options;
1436 var d = o.snapTolerance;
1437
1438 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
1439 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
1440
1441 for (var i = inst.snapElements.length - 1; i >= 0; i--){
1442
1443 var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
1444 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
1445
1446 //Yes, I know, this is insane ;)
1447 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))) {
1448 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 })));
1449 inst.snapElements[i].snapping = false;
1450 continue;
1451 }
1452
1453 if(o.snapMode != 'inner') {
1454 var ts = Math.abs(t - y2) <= d;
1455 var bs = Math.abs(b - y1) <= d;
1456 var ls = Math.abs(l - x2) <= d;
1457 var rs = Math.abs(r - x1) <= d;
1458 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1459 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1460 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1461 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1462 }
1463
1464 var first = (ts || bs || ls || rs);
1465
1466 if(o.snapMode != 'outer') {
1467 var ts = Math.abs(t - y1) <= d;
1468 var bs = Math.abs(b - y2) <= d;
1469 var ls = Math.abs(l - x1) <= d;
1470 var rs = Math.abs(r - x2) <= d;
1471 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1472 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1473 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1474 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1475 }
1476
1477 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
1478 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1479 inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1480
1481 };
1482
1483 }
1484});
1485
1486$.ui.plugin.add("draggable", "stack", {
1487 start: function(event, ui) {
1488
1489 var o = $(this).data("draggable").options;
1490
1491 var group = $.makeArray($(o.stack)).sort(function(a,b) {
1492 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
1493 });
1494 if (!group.length) { return; }
1495
1496 var min = parseInt(group[0].style.zIndex) || 0;
1497 $(group).each(function(i) {
1498 this.style.zIndex = min + i;
1499 });
1500
1501 this[0].style.zIndex = min + group.length;
1502
1503 }
1504});
1505
1506$.ui.plugin.add("draggable", "zIndex", {
1507 start: function(event, ui) {
1508 var t = $(ui.helper), o = $(this).data("draggable").options;
1509 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
1510 t.css('zIndex', o.zIndex);
1511 },
1512 stop: function(event, ui) {
1513 var o = $(this).data("draggable").options;
1514 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
1515 }
1516});
1517
1518})(jQuery);
1519/*
1520 * jQuery UI Droppable 1.8.7
1521 *
1522 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
1523 * Dual licensed under the MIT or GPL Version 2 licenses.
1524 * http://jquery.org/license
1525 *
1526 * http://docs.jquery.com/UI/Droppables
1527 *
1528 * Depends:
1529 * jquery.ui.core.js
1530 * jquery.ui.widget.js
1531 * jquery.ui.mouse.js
1532 * jquery.ui.draggable.js
1533 */
1534(function( $, undefined ) {
1535
1536$.widget("ui.droppable", {
1537 widgetEventPrefix: "drop",
1538 options: {
1539 accept: '*',
1540 activeClass: false,
1541 addClasses: true,
1542 greedy: false,
1543 hoverClass: false,
1544 scope: 'default',
1545 tolerance: 'intersect'
1546 },
1547 _create: function() {
1548
1549 var o = this.options, accept = o.accept;
1550 this.isover = 0; this.isout = 1;
1551
1552 this.accept = $.isFunction(accept) ? accept : function(d) {
1553 return d.is(accept);
1554 };
1555
1556 //Store the droppable's proportions
1557 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
1558
1559 // Add the reference and positions to the manager
1560 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
1561 $.ui.ddmanager.droppables[o.scope].push(this);
1562
1563 (o.addClasses && this.element.addClass("ui-droppable"));
1564
1565 },
1566
1567 destroy: function() {
1568 var drop = $.ui.ddmanager.droppables[this.options.scope];
1569 for ( var i = 0; i < drop.length; i++ )
1570 if ( drop[i] == this )
1571 drop.splice(i, 1);
1572
1573 this.element
1574 .removeClass("ui-droppable ui-droppable-disabled")
1575 .removeData("droppable")
1576 .unbind(".droppable");
1577
1578 return this;
1579 },
1580
1581 _setOption: function(key, value) {
1582
1583 if(key == 'accept') {
1584 this.accept = $.isFunction(value) ? value : function(d) {
1585 return d.is(value);
1586 };
1587 }
1588 $.Widget.prototype._setOption.apply(this, arguments);
1589 },
1590
1591 _activate: function(event) {
1592 var draggable = $.ui.ddmanager.current;
1593 if(this.options.activeClass) this.element.addClass(this.options.activeClass);
1594 (draggable && this._trigger('activate', event, this.ui(draggable)));
1595 },
1596
1597 _deactivate: function(event) {
1598 var draggable = $.ui.ddmanager.current;
1599 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1600 (draggable && this._trigger('deactivate', event, this.ui(draggable)));
1601 },
1602
1603 _over: function(event) {
1604
1605 var draggable = $.ui.ddmanager.current;
1606 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1607
1608 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1609 if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
1610 this._trigger('over', event, this.ui(draggable));
1611 }
1612
1613 },
1614
1615 _out: function(event) {
1616
1617 var draggable = $.ui.ddmanager.current;
1618 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1619
1620 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1621 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1622 this._trigger('out', event, this.ui(draggable));
1623 }
1624
1625 },
1626
1627 _drop: function(event,custom) {
1628
1629 var draggable = custom || $.ui.ddmanager.current;
1630 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
1631
1632 var childrenIntersection = false;
1633 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
1634 var inst = $.data(this, 'droppable');
1635 if(
1636 inst.options.greedy
1637 && !inst.options.disabled
1638 && inst.options.scope == draggable.options.scope
1639 && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
1640 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
1641 ) { childrenIntersection = true; return false; }
1642 });
1643 if(childrenIntersection) return false;
1644
1645 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1646 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1647 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1648 this._trigger('drop', event, this.ui(draggable));
1649 return this.element;
1650 }
1651
1652 return false;
1653
1654 },
1655
1656 ui: function(c) {
1657 return {
1658 draggable: (c.currentItem || c.element),
1659 helper: c.helper,
1660 position: c.position,
1661 offset: c.positionAbs
1662 };
1663 }
1664
1665});
1666
1667$.extend($.ui.droppable, {
1668 version: "1.8.7"
1669});
1670
1671$.ui.intersect = function(draggable, droppable, toleranceMode) {
1672
1673 if (!droppable.offset) return false;
1674
1675 var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
1676 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
1677 var l = droppable.offset.left, r = l + droppable.proportions.width,
1678 t = droppable.offset.top, b = t + droppable.proportions.height;
1679
1680 switch (toleranceMode) {
1681 case 'fit':
1682 return (l <= x1 && x2 <= r
1683 && t <= y1 && y2 <= b);
1684 break;
1685 case 'intersect':
1686 return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
1687 && x2 - (draggable.helperProportions.width / 2) < r // Left Half
1688 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
1689 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
1690 break;
1691 case 'pointer':
1692 var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
1693 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
1694 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
1695 return isOver;
1696 break;
1697 case 'touch':
1698 return (
1699 (y1 >= t && y1 <= b) || // Top edge touching
1700 (y2 >= t && y2 <= b) || // Bottom edge touching
1701 (y1 < t && y2 > b) // Surrounded vertically
1702 ) && (
1703 (x1 >= l && x1 <= r) || // Left edge touching
1704 (x2 >= l && x2 <= r) || // Right edge touching
1705 (x1 < l && x2 > r) // Surrounded horizontally
1706 );
1707 break;
1708 default:
1709 return false;
1710 break;
1711 }
1712
1713};
1714
1715/*
1716 This manager tracks offsets of draggables and droppables
1717*/
1718$.ui.ddmanager = {
1719 current: null,
1720 droppables: { 'default': [] },
1721 prepareOffsets: function(t, event) {
1722
1723 var m = $.ui.ddmanager.droppables[t.options.scope] || [];
1724 var type = event ? event.type : null; // workaround for #2317
1725 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
1726
1727 droppablesLoop: for (var i = 0; i < m.length; i++) {
1728
1729 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted
1730 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
1731 m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue
1732
1733 m[i].offset = m[i].element.offset();
1734 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
1735
1736 if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
1737
1738 }
1739
1740 },
1741 drop: function(draggable, event) {
1742
1743 var dropped = false;
1744 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
1745
1746 if(!this.options) return;
1747 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
1748 dropped = dropped || this._drop.call(this, event);
1749
1750 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1751 this.isout = 1; this.isover = 0;
1752 this._deactivate.call(this, event);
1753 }
1754
1755 });
1756 return dropped;
1757
1758 },
1759 drag: function(draggable, event) {
1760
1761 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
1762 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
1763
1764 //Run through all droppables and check their positions based on specific tolerance options
1765 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
1766
1767 if(this.options.disabled || this.greedyChild || !this.visible) return;
1768 var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
1769
1770 var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
1771 if(!c) return;
1772
1773 var parentInstance;
1774 if (this.options.greedy) {
1775 var parent = this.element.parents(':data(droppable):eq(0)');
1776 if (parent.length) {
1777 parentInstance = $.data(parent[0], 'droppable');
1778 parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
1779 }
1780 }
1781
1782 // we just moved into a greedy child
1783 if (parentInstance && c == 'isover') {
1784 parentInstance['isover'] = 0;
1785 parentInstance['isout'] = 1;
1786 parentInstance._out.call(parentInstance, event);
1787 }
1788
1789 this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
1790 this[c == "isover" ? "_over" : "_out"].call(this, event);
1791
1792 // we just moved out of a greedy child
1793 if (parentInstance && c == 'isout') {
1794 parentInstance['isout'] = 0;
1795 parentInstance['isover'] = 1;
1796 parentInstance._over.call(parentInstance, event);
1797 }
1798 });
1799
1800 }
1801};
1802
1803})(jQuery);
1804/*
1805 * jQuery UI Resizable 1.8.7
1806 *
1807 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
1808 * Dual licensed under the MIT or GPL Version 2 licenses.
1809 * http://jquery.org/license
1810 *
1811 * http://docs.jquery.com/UI/Resizables
1812 *
1813 * Depends:
1814 * jquery.ui.core.js
1815 * jquery.ui.mouse.js
1816 * jquery.ui.widget.js
1817 */
1818(function( $, undefined ) {
1819
1820$.widget("ui.resizable", $.ui.mouse, {
1821 widgetEventPrefix: "resize",
1822 options: {
1823 alsoResize: false,
1824 animate: false,
1825 animateDuration: "slow",
1826 animateEasing: "swing",
1827 aspectRatio: false,
1828 autoHide: false,
1829 containment: false,
1830 ghost: false,
1831 grid: false,
1832 handles: "e,s,se",
1833 helper: false,
1834 maxHeight: null,
1835 maxWidth: null,
1836 minHeight: 10,
1837 minWidth: 10,
1838 zIndex: 1000
1839 },
1840 _create: function() {
1841
1842 var self = this, o = this.options;
1843 this.element.addClass("ui-resizable");
1844
1845 $.extend(this, {
1846 _aspectRatio: !!(o.aspectRatio),
1847 aspectRatio: o.aspectRatio,
1848 originalElement: this.element,
1849 _proportionallyResizeElements: [],
1850 _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
1851 });
1852
1853 //Wrap the element if it cannot hold child nodes
1854 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
1855
1856 //Opera fix for relative positioning
1857 if (/relative/.test(this.element.css('position')) && $.browser.opera)
1858 this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
1859
1860 //Create a wrapper element and set the wrapper to the new current internal element
1861 this.element.wrap(
1862 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
1863 position: this.element.css('position'),
1864 width: this.element.outerWidth(),
1865 height: this.element.outerHeight(),
1866 top: this.element.css('top'),
1867 left: this.element.css('left')
1868 })
1869 );
1870
1871 //Overwrite the original this.element
1872 this.element = this.element.parent().data(
1873 "resizable", this.element.data('resizable')
1874 );
1875
1876 this.elementIsWrapper = true;
1877
1878 //Move margins to the wrapper
1879 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
1880 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
1881
1882 //Prevent Safari textarea resize
1883 this.originalResizeStyle = this.originalElement.css('resize');
1884 this.originalElement.css('resize', 'none');
1885
1886 //Push the actual element to our proportionallyResize internal array
1887 this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
1888
1889 // avoid IE jump (hard set the margin)
1890 this.originalElement.css({ margin: this.originalElement.css('margin') });
1891
1892 // fix handlers offset
1893 this._proportionallyResize();
1894
1895 }
1896
1897 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' });
1898 if(this.handles.constructor == String) {
1899
1900 if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
1901 var n = this.handles.split(","); this.handles = {};
1902
1903 for(var i = 0; i < n.length; i++) {
1904
1905 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
1906 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
1907
1908 // increase zIndex of sw, se, ne, nw axis
1909 //TODO : this modifies original option
1910 if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
1911
1912 //TODO : What's going on here?
1913 if ('se' == handle) {
1914 axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
1915 };
1916
1917 //Insert into internal handles object and append to element
1918 this.handles[handle] = '.ui-resizable-'+handle;
1919 this.element.append(axis);
1920 }
1921
1922 }
1923
1924 this._renderAxis = function(target) {
1925
1926 target = target || this.element;
1927
1928 for(var i in this.handles) {
1929
1930 if(this.handles[i].constructor == String)
1931 this.handles[i] = $(this.handles[i], this.element).show();
1932
1933 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
1934 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
1935
1936 var axis = $(this.handles[i], this.element), padWrapper = 0;
1937
1938 //Checking the correct pad and border
1939 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
1940
1941 //The padding type i have to apply...
1942 var padPos = [ 'padding',
1943 /ne|nw|n/.test(i) ? 'Top' :
1944 /se|sw|s/.test(i) ? 'Bottom' :
1945 /^e$/.test(i) ? 'Right' : 'Left' ].join("");
1946
1947 target.css(padPos, padWrapper);
1948
1949 this._proportionallyResize();
1950
1951 }
1952
1953 //TODO: What's that good for? There's not anything to be executed left
1954 if(!$(this.handles[i]).length)
1955 continue;
1956
1957 }
1958 };
1959
1960 //TODO: make renderAxis a prototype function
1961 this._renderAxis(this.element);
1962
1963 this._handles = $('.ui-resizable-handle', this.element)
1964 .disableSelection();
1965
1966 //Matching axis name
1967 this._handles.mouseover(function() {
1968 if (!self.resizing) {
1969 if (this.className)
1970 var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
1971 //Axis, default = se
1972 self.axis = axis && axis[1] ? axis[1] : 'se';
1973 }
1974 });
1975
1976 //If we want to auto hide the elements
1977 if (o.autoHide) {
1978 this._handles.hide();
1979 $(this.element)
1980 .addClass("ui-resizable-autohide")
1981 .hover(function() {
1982 $(this).removeClass("ui-resizable-autohide");
1983 self._handles.show();
1984 },
1985 function(){
1986 if (!self.resizing) {
1987 $(this).addClass("ui-resizable-autohide");
1988 self._handles.hide();
1989 }
1990 });
1991 }
1992
1993 //Initialize the mouse interaction
1994 this._mouseInit();
1995
1996 },
1997
1998 destroy: function() {
1999
2000 this._mouseDestroy();
2001
2002 var _destroy = function(exp) {
2003 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
2004 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
2005 };
2006
2007 //TODO: Unwrap at same DOM position
2008 if (this.elementIsWrapper) {
2009 _destroy(this.element);
2010 var wrapper = this.element;
2011 wrapper.after(
2012 this.originalElement.css({
2013 position: wrapper.css('position'),
2014 width: wrapper.outerWidth(),
2015 height: wrapper.outerHeight(),
2016 top: wrapper.css('top'),
2017 left: wrapper.css('left')
2018 })
2019 ).remove();
2020 }
2021
2022 this.originalElement.css('resize', this.originalResizeStyle);
2023 _destroy(this.originalElement);
2024
2025 return this;
2026 },
2027
2028 _mouseCapture: function(event) {
2029 var handle = false;
2030 for (var i in this.handles) {
2031 if ($(this.handles[i])[0] == event.target) {
2032 handle = true;
2033 }
2034 }
2035
2036 return !this.options.disabled && handle;
2037 },
2038
2039 _mouseStart: function(event) {
2040
2041 var o = this.options, iniPos = this.element.position(), el = this.element;
2042
2043 this.resizing = true;
2044 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
2045
2046 // bugfix for http://dev.jquery.com/ticket/1749
2047 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
2048 el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
2049 }
2050
2051 //Opera fixing relative position
2052 if ($.browser.opera && (/relative/).test(el.css('position')))
2053 el.css({ position: 'relative', top: 'auto', left: 'auto' });
2054
2055 this._renderProxy();
2056
2057 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
2058
2059 if (o.containment) {
2060 curleft += $(o.containment).scrollLeft() || 0;
2061 curtop += $(o.containment).scrollTop() || 0;
2062 }
2063
2064 //Store needed variables
2065 this.offset = this.helper.offset();
2066 this.position = { left: curleft, top: curtop };
2067 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2068 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2069 this.originalPosition = { left: curleft, top: curtop };
2070 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
2071 this.originalMousePosition = { left: event.pageX, top: event.pageY };
2072
2073 //Aspect Ratio
2074 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
2075
2076 var cursor = $('.ui-resizable-' + this.axis).css('cursor');
2077 $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
2078
2079 el.addClass("ui-resizable-resizing");
2080 this._propagate("start", event);
2081 return true;
2082 },
2083
2084 _mouseDrag: function(event) {
2085
2086 //Increase performance, avoid regex
2087 var el = this.helper, o = this.options, props = {},
2088 self = this, smp = this.originalMousePosition, a = this.axis;
2089
2090 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
2091 var trigger = this._change[a];
2092 if (!trigger) return false;
2093
2094 // Calculate the attrs that will be change
2095 var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
2096
2097 if (this._aspectRatio || event.shiftKey)
2098 data = this._updateRatio(data, event);
2099
2100 data = this._respectSize(data, event);
2101
2102 // plugins callbacks need to be called first
2103 this._propagate("resize", event);
2104
2105 el.css({
2106 top: this.position.top + "px", left: this.position.left + "px",
2107 width: this.size.width + "px", height: this.size.height + "px"
2108 });
2109
2110 if (!this._helper && this._proportionallyResizeElements.length)
2111 this._proportionallyResize();
2112
2113 this._updateCache(data);
2114
2115 // calling the user callback at the end
2116 this._trigger('resize', event, this.ui());
2117
2118 return false;
2119 },
2120
2121 _mouseStop: function(event) {
2122
2123 this.resizing = false;
2124 var o = this.options, self = this;
2125
2126 if(this._helper) {
2127 var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2128 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2129 soffsetw = ista ? 0 : self.sizeDiff.width;
2130
2131 var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
2132 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2133 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2134
2135 if (!o.animate)
2136 this.element.css($.extend(s, { top: top, left: left }));
2137
2138 self.helper.height(self.size.height);
2139 self.helper.width(self.size.width);
2140
2141 if (this._helper && !o.animate) this._proportionallyResize();
2142 }
2143
2144 $('body').css('cursor', 'auto');
2145
2146 this.element.removeClass("ui-resizable-resizing");
2147
2148 this._propagate("stop", event);
2149
2150 if (this._helper) this.helper.remove();
2151 return false;
2152
2153 },
2154
2155 _updateCache: function(data) {
2156 var o = this.options;
2157 this.offset = this.helper.offset();
2158 if (isNumber(data.left)) this.position.left = data.left;
2159 if (isNumber(data.top)) this.position.top = data.top;
2160 if (isNumber(data.height)) this.size.height = data.height;
2161 if (isNumber(data.width)) this.size.width = data.width;
2162 },
2163
2164 _updateRatio: function(data, event) {
2165
2166 var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
2167
2168 if (data.height) data.width = (csize.height * this.aspectRatio);
2169 else if (data.width) data.height = (csize.width / this.aspectRatio);
2170
2171 if (a == 'sw') {
2172 data.left = cpos.left + (csize.width - data.width);
2173 data.top = null;
2174 }
2175 if (a == 'nw') {
2176 data.top = cpos.top + (csize.height - data.height);
2177 data.left = cpos.left + (csize.width - data.width);
2178 }
2179
2180 return data;
2181 },
2182
2183 _respectSize: function(data, event) {
2184
2185 var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
2186 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
2187 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
2188
2189 if (isminw) data.width = o.minWidth;
2190 if (isminh) data.height = o.minHeight;
2191 if (ismaxw) data.width = o.maxWidth;
2192 if (ismaxh) data.height = o.maxHeight;
2193
2194 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
2195 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
2196
2197 if (isminw && cw) data.left = dw - o.minWidth;
2198 if (ismaxw && cw) data.left = dw - o.maxWidth;
2199 if (isminh && ch) data.top = dh - o.minHeight;
2200 if (ismaxh && ch) data.top = dh - o.maxHeight;
2201
2202 // fixing jump error on top/left - bug #2330
2203 var isNotwh = !data.width && !data.height;
2204 if (isNotwh && !data.left && data.top) data.top = null;
2205 else if (isNotwh && !data.top && data.left) data.left = null;
2206
2207 return data;
2208 },
2209
2210 _proportionallyResize: function() {
2211
2212 var o = this.options;
2213 if (!this._proportionallyResizeElements.length) return;
2214 var element = this.helper || this.element;
2215
2216 for (var i=0; i < this._proportionallyResizeElements.length; i++) {
2217
2218 var prel = this._proportionallyResizeElements[i];
2219
2220 if (!this.borderDif) {
2221 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
2222 p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
2223
2224 this.borderDif = $.map(b, function(v, i) {
2225 var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
2226 return border + padding;
2227 });
2228 }
2229
2230 if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
2231 continue;
2232
2233 prel.css({
2234 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
2235 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
2236 });
2237
2238 };
2239
2240 },
2241
2242 _renderProxy: function() {
2243
2244 var el = this.element, o = this.options;
2245 this.elementOffset = el.offset();
2246
2247 if(this._helper) {
2248
2249 this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
2250
2251 // fix ie6 offset TODO: This seems broken
2252 var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
2253 pxyoffset = ( ie6 ? 2 : -1 );
2254
2255 this.helper.addClass(this._helper).css({
2256 width: this.element.outerWidth() + pxyoffset,
2257 height: this.element.outerHeight() + pxyoffset,
2258 position: 'absolute',
2259 left: this.elementOffset.left - ie6offset +'px',
2260 top: this.elementOffset.top - ie6offset +'px',
2261 zIndex: ++o.zIndex //TODO: Don't modify option
2262 });
2263
2264 this.helper
2265 .appendTo("body")
2266 .disableSelection();
2267
2268 } else {
2269 this.helper = this.element;
2270 }
2271
2272 },
2273
2274 _change: {
2275 e: function(event, dx, dy) {
2276 return { width: this.originalSize.width + dx };
2277 },
2278 w: function(event, dx, dy) {
2279 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2280 return { left: sp.left + dx, width: cs.width - dx };
2281 },
2282 n: function(event, dx, dy) {
2283 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2284 return { top: sp.top + dy, height: cs.height - dy };
2285 },
2286 s: function(event, dx, dy) {
2287 return { height: this.originalSize.height + dy };
2288 },
2289 se: function(event, dx, dy) {
2290 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2291 },
2292 sw: function(event, dx, dy) {
2293 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2294 },
2295 ne: function(event, dx, dy) {
2296 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2297 },
2298 nw: function(event, dx, dy) {
2299 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2300 }
2301 },
2302
2303 _propagate: function(n, event) {
2304 $.ui.plugin.call(this, n, [event, this.ui()]);
2305 (n != "resize" && this._trigger(n, event, this.ui()));
2306 },
2307
2308 plugins: {},
2309
2310 ui: function() {
2311 return {
2312 originalElement: this.originalElement,
2313 element: this.element,
2314 helper: this.helper,
2315 position: this.position,
2316 size: this.size,
2317 originalSize: this.originalSize,
2318 originalPosition: this.originalPosition
2319 };
2320 }
2321
2322});
2323
2324$.extend($.ui.resizable, {
2325 version: "1.8.7"
2326});
2327
2328/*
2329 * Resizable Extensions
2330 */
2331
2332$.ui.plugin.add("resizable", "alsoResize", {
2333
2334 start: function (event, ui) {
2335 var self = $(this).data("resizable"), o = self.options;
2336
2337 var _store = function (exp) {
2338 $(exp).each(function() {
2339 var el = $(this);
2340 el.data("resizable-alsoresize", {
2341 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
2342 left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
2343 position: el.css('position') // to reset Opera on stop()
2344 });
2345 });
2346 };
2347
2348 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
2349 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
2350 else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
2351 }else{
2352 _store(o.alsoResize);
2353 }
2354 },
2355
2356 resize: function (event, ui) {
2357 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
2358
2359 var delta = {
2360 height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
2361 top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
2362 },
2363
2364 _alsoResize = function (exp, c) {
2365 $(exp).each(function() {
2366 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {},
2367 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
2368
2369 $.each(css, function (i, prop) {
2370 var sum = (start[prop]||0) + (delta[prop]||0);
2371 if (sum && sum >= 0)
2372 style[prop] = sum || null;
2373 });
2374
2375 // Opera fixing relative position
2376 if ($.browser.opera && /relative/.test(el.css('position'))) {
2377 self._revertToRelativePosition = true;
2378 el.css({ position: 'absolute', top: 'auto', left: 'auto' });
2379 }
2380
2381 el.css(style);
2382 });
2383 };
2384
2385 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2386 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
2387 }else{
2388 _alsoResize(o.alsoResize);
2389 }
2390 },
2391
2392 stop: function (event, ui) {
2393 var self = $(this).data("resizable"), o = self.options;
2394
2395 var _reset = function (exp) {
2396 $(exp).each(function() {
2397 var el = $(this);
2398 // reset position for Opera - no need to verify it was changed
2399 el.css({ position: el.data("resizable-alsoresize").position });
2400 });
2401 };
2402
2403 if (self._revertToRelativePosition) {
2404 self._revertToRelativePosition = false;
2405 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2406 $.each(o.alsoResize, function (exp) { _reset(exp); });
2407 }else{
2408 _reset(o.alsoResize);
2409 }
2410 }
2411
2412 $(this).removeData("resizable-alsoresize");
2413 }
2414});
2415
2416$.ui.plugin.add("resizable", "animate", {
2417
2418 stop: function(event, ui) {
2419 var self = $(this).data("resizable"), o = self.options;
2420
2421 var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2422 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2423 soffsetw = ista ? 0 : self.sizeDiff.width;
2424
2425 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
2426 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2427 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2428
2429 self.element.animate(
2430 $.extend(style, top && left ? { top: top, left: left } : {}), {
2431 duration: o.animateDuration,
2432 easing: o.animateEasing,
2433 step: function() {
2434
2435 var data = {
2436 width: parseInt(self.element.css('width'), 10),
2437 height: parseInt(self.element.css('height'), 10),
2438 top: parseInt(self.element.css('top'), 10),
2439 left: parseInt(self.element.css('left'), 10)
2440 };
2441
2442 if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
2443
2444 // propagating resize, and updating values for each animation step
2445 self._updateCache(data);
2446 self._propagate("resize", event);
2447
2448 }
2449 }
2450 );
2451 }
2452
2453});
2454
2455$.ui.plugin.add("resizable", "containment", {
2456
2457 start: function(event, ui) {
2458 var self = $(this).data("resizable"), o = self.options, el = self.element;
2459 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
2460 if (!ce) return;
2461
2462 self.containerElement = $(ce);
2463
2464 if (/document/.test(oc) || oc == document) {
2465 self.containerOffset = { left: 0, top: 0 };
2466 self.containerPosition = { left: 0, top: 0 };
2467
2468 self.parentData = {
2469 element: $(document), left: 0, top: 0,
2470 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
2471 };
2472 }
2473
2474 // i'm a node, so compute top, left, right, bottom
2475 else {
2476 var element = $(ce), p = [];
2477 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
2478
2479 self.containerOffset = element.offset();
2480 self.containerPosition = element.position();
2481 self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
2482
2483 var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width,
2484 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
2485
2486 self.parentData = {
2487 element: ce, left: co.left, top: co.top, width: width, height: height
2488 };
2489 }
2490 },
2491
2492 resize: function(event, ui) {
2493 var self = $(this).data("resizable"), o = self.options,
2494 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
2495 pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
2496
2497 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
2498
2499 if (cp.left < (self._helper ? co.left : 0)) {
2500 self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
2501 if (pRatio) self.size.height = self.size.width / o.aspectRatio;
2502 self.position.left = o.helper ? co.left : 0;
2503 }
2504
2505 if (cp.top < (self._helper ? co.top : 0)) {
2506 self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
2507 if (pRatio) self.size.width = self.size.height * o.aspectRatio;
2508 self.position.top = self._helper ? co.top : 0;
2509 }
2510
2511 self.offset.left = self.parentData.left+self.position.left;
2512 self.offset.top = self.parentData.top+self.position.top;
2513
2514 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
2515 hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
2516
2517 var isParent = self.containerElement.get(0) == self.element.parent().get(0),
2518 isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
2519
2520 if(isParent && isOffsetRelative) woset -= self.parentData.left;
2521
2522 if (woset + self.size.width >= self.parentData.width) {
2523 self.size.width = self.parentData.width - woset;
2524 if (pRatio) self.size.height = self.size.width / self.aspectRatio;
2525 }
2526
2527 if (hoset + self.size.height >= self.parentData.height) {
2528 self.size.height = self.parentData.height - hoset;
2529 if (pRatio) self.size.width = self.size.height * self.aspectRatio;
2530 }
2531 },
2532
2533 stop: function(event, ui){
2534 var self = $(this).data("resizable"), o = self.options, cp = self.position,
2535 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
2536
2537 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
2538
2539 if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
2540 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2541
2542 if (self._helper && !o.animate && (/static/).test(ce.css('position')))
2543 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2544
2545 }
2546});
2547
2548$.ui.plugin.add("resizable", "ghost", {
2549
2550 start: function(event, ui) {
2551
2552 var self = $(this).data("resizable"), o = self.options, cs = self.size;
2553
2554 self.ghost = self.originalElement.clone();
2555 self.ghost
2556 .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
2557 .addClass('ui-resizable-ghost')
2558 .addClass(typeof o.ghost == 'string' ? o.ghost : '');
2559
2560 self.ghost.appendTo(self.helper);
2561
2562 },
2563
2564 resize: function(event, ui){
2565 var self = $(this).data("resizable"), o = self.options;
2566 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
2567 },
2568
2569 stop: function(event, ui){
2570 var self = $(this).data("resizable"), o = self.options;
2571 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
2572 }
2573
2574});
2575
2576$.ui.plugin.add("resizable", "grid", {
2577
2578 resize: function(event, ui) {
2579 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;
2580 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
2581 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);
2582
2583 if (/^(se|s|e)$/.test(a)) {
2584 self.size.width = os.width + ox;
2585 self.size.height = os.height + oy;
2586 }
2587 else if (/^(ne)$/.test(a)) {
2588 self.size.width = os.width + ox;
2589 self.size.height = os.height + oy;
2590 self.position.top = op.top - oy;
2591 }
2592 else if (/^(sw)$/.test(a)) {
2593 self.size.width = os.width + ox;
2594 self.size.height = os.height + oy;
2595 self.position.left = op.left - ox;
2596 }
2597 else {
2598 self.size.width = os.width + ox;
2599 self.size.height = os.height + oy;
2600 self.position.top = op.top - oy;
2601 self.position.left = op.left - ox;
2602 }
2603 }
2604
2605});
2606
2607var num = function(v) {
2608 return parseInt(v, 10) || 0;
2609};
2610
2611var isNumber = function(value) {
2612 return !isNaN(parseInt(value, 10));
2613};
2614
2615})(jQuery);
2616/*
2617 * jQuery UI Selectable 1.8.7
2618 *
2619 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
2620 * Dual licensed under the MIT or GPL Version 2 licenses.
2621 * http://jquery.org/license
2622 *
2623 * http://docs.jquery.com/UI/Selectables
2624 *
2625 * Depends:
2626 * jquery.ui.core.js
2627 * jquery.ui.mouse.js
2628 * jquery.ui.widget.js
2629 */
2630(function( $, undefined ) {
2631
2632$.widget("ui.selectable", $.ui.mouse, {
2633 options: {
2634 appendTo: 'body',
2635 autoRefresh: true,
2636 distance: 0,
2637 filter: '*',
2638 tolerance: 'touch'
2639 },
2640 _create: function() {
2641 var self = this;
2642
2643 this.element.addClass("ui-selectable");
2644
2645 this.dragged = false;
2646
2647 // cache selectee children based on filter
2648 var selectees;
2649 this.refresh = function() {
2650 selectees = $(self.options.filter, self.element[0]);
2651 selectees.each(function() {
2652 var $this = $(this);
2653 var pos = $this.offset();
2654 $.data(this, "selectable-item", {
2655 element: this,
2656 $element: $this,
2657 left: pos.left,
2658 top: pos.top,
2659 right: pos.left + $this.outerWidth(),
2660 bottom: pos.top + $this.outerHeight(),
2661 startselected: false,
2662 selected: $this.hasClass('ui-selected'),
2663 selecting: $this.hasClass('ui-selecting'),
2664 unselecting: $this.hasClass('ui-unselecting')
2665 });
2666 });
2667 };
2668 this.refresh();
2669
2670 this.selectees = selectees.addClass("ui-selectee");
2671
2672 this._mouseInit();
2673
2674 this.helper = $("<div class='ui-selectable-helper'></div>");
2675 },
2676
2677 destroy: function() {
2678 this.selectees
2679 .removeClass("ui-selectee")
2680 .removeData("selectable-item");
2681 this.element
2682 .removeClass("ui-selectable ui-selectable-disabled")
2683 .removeData("selectable")
2684 .unbind(".selectable");
2685 this._mouseDestroy();
2686
2687 return this;
2688 },
2689
2690 _mouseStart: function(event) {
2691 var self = this;
2692
2693 this.opos = [event.pageX, event.pageY];
2694
2695 if (this.options.disabled)
2696 return;
2697
2698 var options = this.options;
2699
2700 this.selectees = $(options.filter, this.element[0]);
2701
2702 this._trigger("start", event);
2703
2704 $(options.appendTo).append(this.helper);
2705 // position helper (lasso)
2706 this.helper.css({
2707 "left": event.clientX,
2708 "top": event.clientY,
2709 "width": 0,
2710 "height": 0
2711 });
2712
2713 if (options.autoRefresh) {
2714 this.refresh();
2715 }
2716
2717 this.selectees.filter('.ui-selected').each(function() {
2718 var selectee = $.data(this, "selectable-item");
2719 selectee.startselected = true;
2720 if (!event.metaKey) {
2721 selectee.$element.removeClass('ui-selected');
2722 selectee.selected = false;
2723 selectee.$element.addClass('ui-unselecting');
2724 selectee.unselecting = true;
2725 // selectable UNSELECTING callback
2726 self._trigger("unselecting", event, {
2727 unselecting: selectee.element
2728 });
2729 }
2730 });
2731
2732 $(event.target).parents().andSelf().each(function() {
2733 var selectee = $.data(this, "selectable-item");
2734 if (selectee) {
2735 var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
2736 selectee.$element
2737 .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
2738 .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
2739 selectee.unselecting = !doSelect;
2740 selectee.selecting = doSelect;
2741 selectee.selected = doSelect;
2742 // selectable (UN)SELECTING callback
2743 if (doSelect) {
2744 self._trigger("selecting", event, {
2745 selecting: selectee.element
2746 });
2747 } else {
2748 self._trigger("unselecting", event, {
2749 unselecting: selectee.element
2750 });
2751 }
2752 return false;
2753 }
2754 });
2755
2756 },
2757
2758 _mouseDrag: function(event) {
2759 var self = this;
2760 this.dragged = true;
2761
2762 if (this.options.disabled)
2763 return;
2764
2765 var options = this.options;
2766
2767 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
2768 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
2769 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
2770 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
2771
2772 this.selectees.each(function() {
2773 var selectee = $.data(this, "selectable-item");
2774 //prevent helper from being selected if appendTo: selectable
2775 if (!selectee || selectee.element == self.element[0])
2776 return;
2777 var hit = false;
2778 if (options.tolerance == 'touch') {
2779 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
2780 } else if (options.tolerance == 'fit') {
2781 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
2782 }
2783
2784 if (hit) {
2785 // SELECT
2786 if (selectee.selected) {
2787 selectee.$element.removeClass('ui-selected');
2788 selectee.selected = false;
2789 }
2790 if (selectee.unselecting) {
2791 selectee.$element.removeClass('ui-unselecting');
2792 selectee.unselecting = false;
2793 }
2794 if (!selectee.selecting) {
2795 selectee.$element.addClass('ui-selecting');
2796 selectee.selecting = true;
2797 // selectable SELECTING callback
2798 self._trigger("selecting", event, {
2799 selecting: selectee.element
2800 });
2801 }
2802 } else {
2803 // UNSELECT
2804 if (selectee.selecting) {
2805 if (event.metaKey && selectee.startselected) {
2806 selectee.$element.removeClass('ui-selecting');
2807 selectee.selecting = false;
2808 selectee.$element.addClass('ui-selected');
2809 selectee.selected = true;
2810 } else {
2811 selectee.$element.removeClass('ui-selecting');
2812 selectee.selecting = false;
2813 if (selectee.startselected) {
2814 selectee.$element.addClass('ui-unselecting');
2815 selectee.unselecting = true;
2816 }
2817 // selectable UNSELECTING callback
2818 self._trigger("unselecting", event, {
2819 unselecting: selectee.element
2820 });
2821 }
2822 }
2823 if (selectee.selected) {
2824 if (!event.metaKey && !selectee.startselected) {
2825 selectee.$element.removeClass('ui-selected');
2826 selectee.selected = false;
2827
2828 selectee.$element.addClass('ui-unselecting');
2829 selectee.unselecting = true;
2830 // selectable UNSELECTING callback
2831 self._trigger("unselecting", event, {
2832 unselecting: selectee.element
2833 });
2834 }
2835 }
2836 }
2837 });
2838
2839 return false;
2840 },
2841
2842 _mouseStop: function(event) {
2843 var self = this;
2844
2845 this.dragged = false;
2846
2847 var options = this.options;
2848
2849 $('.ui-unselecting', this.element[0]).each(function() {
2850 var selectee = $.data(this, "selectable-item");
2851 selectee.$element.removeClass('ui-unselecting');
2852 selectee.unselecting = false;
2853 selectee.startselected = false;
2854 self._trigger("unselected", event, {
2855 unselected: selectee.element
2856 });
2857 });
2858 $('.ui-selecting', this.element[0]).each(function() {
2859 var selectee = $.data(this, "selectable-item");
2860 selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
2861 selectee.selecting = false;
2862 selectee.selected = true;
2863 selectee.startselected = true;
2864 self._trigger("selected", event, {
2865 selected: selectee.element
2866 });
2867 });
2868 this._trigger("stop", event);
2869
2870 this.helper.remove();
2871
2872 return false;
2873 }
2874
2875});
2876
2877$.extend($.ui.selectable, {
2878 version: "1.8.7"
2879});
2880
2881})(jQuery);
2882/*
2883 * jQuery UI Sortable 1.8.7
2884 *
2885 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
2886 * Dual licensed under the MIT or GPL Version 2 licenses.
2887 * http://jquery.org/license
2888 *
2889 * http://docs.jquery.com/UI/Sortables
2890 *
2891 * Depends:
2892 * jquery.ui.core.js
2893 * jquery.ui.mouse.js
2894 * jquery.ui.widget.js
2895 */
2896(function( $, undefined ) {
2897
2898$.widget("ui.sortable", $.ui.mouse, {
2899 widgetEventPrefix: "sort",
2900 options: {
2901 appendTo: "parent",
2902 axis: false,
2903 connectWith: false,
2904 containment: false,
2905 cursor: 'auto',
2906 cursorAt: false,
2907 dropOnEmpty: true,
2908 forcePlaceholderSize: false,
2909 forceHelperSize: false,
2910 grid: false,
2911 handle: false,
2912 helper: "original",
2913 items: '> *',
2914 opacity: false,
2915 placeholder: false,
2916 revert: false,
2917 scroll: true,
2918 scrollSensitivity: 20,
2919 scrollSpeed: 20,
2920 scope: "default",
2921 tolerance: "intersect",
2922 zIndex: 1000
2923 },
2924 _create: function() {
2925
2926 var o = this.options;
2927 this.containerCache = {};
2928 this.element.addClass("ui-sortable");
2929
2930 //Get the items
2931 this.refresh();
2932
2933 //Let's determine if the items are floating
2934 this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;
2935
2936 //Let's determine the parent's offset
2937 this.offset = this.element.offset();
2938
2939 //Initialize mouse events for interaction
2940 this._mouseInit();
2941
2942 },
2943
2944 destroy: function() {
2945 this.element
2946 .removeClass("ui-sortable ui-sortable-disabled")
2947 .removeData("sortable")
2948 .unbind(".sortable");
2949 this._mouseDestroy();
2950
2951 for ( var i = this.items.length - 1; i >= 0; i-- )
2952 this.items[i].item.removeData("sortable-item");
2953
2954 return this;
2955 },
2956
2957 _setOption: function(key, value){
2958 if ( key === "disabled" ) {
2959 this.options[ key ] = value;
2960
2961 this.widget()
2962 [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
2963 } else {
2964 // Don't call widget base _setOption for disable as it adds ui-state-disabled class
2965 $.Widget.prototype._setOption.apply(this, arguments);
2966 }
2967 },
2968
2969 _mouseCapture: function(event, overrideHandle) {
2970
2971 if (this.reverting) {
2972 return false;
2973 }
2974
2975 if(this.options.disabled || this.options.type == 'static') return false;
2976
2977 //We have to refresh the items data once first
2978 this._refreshItems(event);
2979
2980 //Find out if the clicked node (or one of its parents) is a actual item in this.items
2981 var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
2982 if($.data(this, 'sortable-item') == self) {
2983 currentItem = $(this);
2984 return false;
2985 }
2986 });
2987 if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
2988
2989 if(!currentItem) return false;
2990 if(this.options.handle && !overrideHandle) {
2991 var validHandle = false;
2992
2993 $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
2994 if(!validHandle) return false;
2995 }
2996
2997 this.currentItem = currentItem;
2998 this._removeCurrentsFromItems();
2999 return true;
3000
3001 },
3002
3003 _mouseStart: function(event, overrideHandle, noActivation) {
3004
3005 var o = this.options, self = this;
3006 this.currentContainer = this;
3007
3008 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
3009 this.refreshPositions();
3010
3011 //Create and append the visible helper
3012 this.helper = this._createHelper(event);
3013
3014 //Cache the helper size
3015 this._cacheHelperProportions();
3016
3017 /*
3018 * - Position generation -
3019 * This block generates everything position related - it's the core of draggables.
3020 */
3021
3022 //Cache the margins of the original element
3023 this._cacheMargins();
3024
3025 //Get the next scrolling parent
3026 this.scrollParent = this.helper.scrollParent();
3027
3028 //The element's absolute position on the page minus margins
3029 this.offset = this.currentItem.offset();
3030 this.offset = {
3031 top: this.offset.top - this.margins.top,
3032 left: this.offset.left - this.margins.left
3033 };
3034
3035 // Only after we got the offset, we can change the helper's position to absolute
3036 // TODO: Still need to figure out a way to make relative sorting possible
3037 this.helper.css("position", "absolute");
3038 this.cssPosition = this.helper.css("position");
3039
3040 $.extend(this.offset, {
3041 click: { //Where the click happened, relative to the element
3042 left: event.pageX - this.offset.left,
3043 top: event.pageY - this.offset.top
3044 },
3045 parent: this._getParentOffset(),
3046 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
3047 });
3048
3049 //Generate the original position
3050 this.originalPosition = this._generatePosition(event);
3051 this.originalPageX = event.pageX;
3052 this.originalPageY = event.pageY;
3053
3054 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
3055 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
3056
3057 //Cache the former DOM position
3058 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
3059
3060 //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
3061 if(this.helper[0] != this.currentItem[0]) {
3062 this.currentItem.hide();
3063 }
3064
3065 //Create the placeholder
3066 this._createPlaceholder();
3067
3068 //Set a containment if given in the options
3069 if(o.containment)
3070 this._setContainment();
3071
3072 if(o.cursor) { // cursor option
3073 if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
3074 $('body').css("cursor", o.cursor);
3075 }
3076
3077 if(o.opacity) { // opacity option
3078 if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
3079 this.helper.css("opacity", o.opacity);
3080 }
3081
3082 if(o.zIndex) { // zIndex option
3083 if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
3084 this.helper.css("zIndex", o.zIndex);
3085 }
3086
3087 //Prepare scrolling
3088 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
3089 this.overflowOffset = this.scrollParent.offset();
3090
3091 //Call callbacks
3092 this._trigger("start", event, this._uiHash());
3093
3094 //Recache the helper size
3095 if(!this._preserveHelperProportions)
3096 this._cacheHelperProportions();
3097
3098
3099 //Post 'activate' events to possible containers
3100 if(!noActivation) {
3101 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
3102 }
3103
3104 //Prepare possible droppables
3105 if($.ui.ddmanager)
3106 $.ui.ddmanager.current = this;
3107
3108 if ($.ui.ddmanager && !o.dropBehaviour)
3109 $.ui.ddmanager.prepareOffsets(this, event);
3110
3111 this.dragging = true;
3112
3113 this.helper.addClass("ui-sortable-helper");
3114 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
3115 return true;
3116
3117 },
3118
3119 _mouseDrag: function(event) {
3120
3121 //Compute the helpers position
3122 this.position = this._generatePosition(event);
3123 this.positionAbs = this._convertPositionTo("absolute");
3124
3125 if (!this.lastPositionAbs) {
3126 this.lastPositionAbs = this.positionAbs;
3127 }
3128
3129 //Do scrolling
3130 if(this.options.scroll) {
3131 var o = this.options, scrolled = false;
3132 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
3133
3134 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
3135 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
3136 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
3137 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
3138
3139 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
3140 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
3141 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
3142 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
3143
3144 } else {
3145
3146 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
3147 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
3148 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
3149 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
3150
3151 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
3152 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
3153 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
3154 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
3155
3156 }
3157
3158 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
3159 $.ui.ddmanager.prepareOffsets(this, event);
3160 }
3161
3162 //Regenerate the absolute position used for position checks
3163 this.positionAbs = this._convertPositionTo("absolute");
3164
3165 //Set the helper position
3166 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
3167 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
3168
3169 //Rearrange
3170 for (var i = this.items.length - 1; i >= 0; i--) {
3171
3172 //Cache variables and intersection, continue if no intersection
3173 var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
3174 if (!intersection) continue;
3175
3176 if(itemElement != this.currentItem[0] //cannot intersect with itself
3177 && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
3178 && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
3179 && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
3180 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
3181 ) {
3182
3183 this.direction = intersection == 1 ? "down" : "up";
3184
3185 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
3186 this._rearrange(event, item);
3187 } else {
3188 break;
3189 }
3190
3191 this._trigger("change", event, this._uiHash());
3192 break;
3193 }
3194 }
3195
3196 //Post events to containers
3197 this._contactContainers(event);
3198
3199 //Interconnect with droppables
3200 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
3201
3202 //Call callbacks
3203 this._trigger('sort', event, this._uiHash());
3204
3205 this.lastPositionAbs = this.positionAbs;
3206 return false;
3207
3208 },
3209
3210 _mouseStop: function(event, noPropagation) {
3211
3212 if(!event) return;
3213
3214 //If we are using droppables, inform the manager about the drop
3215 if ($.ui.ddmanager && !this.options.dropBehaviour)
3216 $.ui.ddmanager.drop(this, event);
3217
3218 if(this.options.revert) {
3219 var self = this;
3220 var cur = self.placeholder.offset();
3221
3222 self.reverting = true;
3223
3224 $(this.helper).animate({
3225 left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
3226 top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
3227 }, parseInt(this.options.revert, 10) || 500, function() {
3228 self._clear(event);
3229 });
3230 } else {
3231 this._clear(event, noPropagation);
3232 }
3233
3234 return false;
3235
3236 },
3237
3238 cancel: function() {
3239
3240 var self = this;
3241
3242 if(this.dragging) {
3243
3244 this._mouseUp();
3245
3246 if(this.options.helper == "original")
3247 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3248 else
3249 this.currentItem.show();
3250
3251 //Post deactivating events to containers
3252 for (var i = this.containers.length - 1; i >= 0; i--){
3253 this.containers[i]._trigger("deactivate", null, self._uiHash(this));
3254 if(this.containers[i].containerCache.over) {
3255 this.containers[i]._trigger("out", null, self._uiHash(this));
3256 this.containers[i].containerCache.over = 0;
3257 }
3258 }
3259
3260 }
3261
3262 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3263 if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3264 if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
3265
3266 $.extend(this, {
3267 helper: null,
3268 dragging: false,
3269 reverting: false,
3270 _noFinalSort: null
3271 });
3272
3273 if(this.domPosition.prev) {
3274 $(this.domPosition.prev).after(this.currentItem);
3275 } else {
3276 $(this.domPosition.parent).prepend(this.currentItem);
3277 }
3278
3279 return this;
3280
3281 },
3282
3283 serialize: function(o) {
3284
3285 var items = this._getItemsAsjQuery(o && o.connected);
3286 var str = []; o = o || {};
3287
3288 $(items).each(function() {
3289 var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
3290 if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
3291 });
3292
3293 if(!str.length && o.key) {
3294 str.push(o.key + '=');
3295 }
3296
3297 return str.join('&');
3298
3299 },
3300
3301 toArray: function(o) {
3302
3303 var items = this._getItemsAsjQuery(o && o.connected);
3304 var ret = []; o = o || {};
3305
3306 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
3307 return ret;
3308
3309 },
3310
3311 /* Be careful with the following core functions */
3312 _intersectsWith: function(item) {
3313
3314 var x1 = this.positionAbs.left,
3315 x2 = x1 + this.helperProportions.width,
3316 y1 = this.positionAbs.top,
3317 y2 = y1 + this.helperProportions.height;
3318
3319 var l = item.left,
3320 r = l + item.width,
3321 t = item.top,
3322 b = t + item.height;
3323
3324 var dyClick = this.offset.click.top,
3325 dxClick = this.offset.click.left;
3326
3327 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
3328
3329 if( this.options.tolerance == "pointer"
3330 || this.options.forcePointerForContainers
3331 || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
3332 ) {
3333 return isOverElement;
3334 } else {
3335
3336 return (l < x1 + (this.helperProportions.width / 2) // Right Half
3337 && x2 - (this.helperProportions.width / 2) < r // Left Half
3338 && t < y1 + (this.helperProportions.height / 2) // Bottom Half
3339 && y2 - (this.helperProportions.height / 2) < b ); // Top Half
3340
3341 }
3342 },
3343
3344 _intersectsWithPointer: function(item) {
3345
3346 var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
3347 isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
3348 isOverElement = isOverElementHeight && isOverElementWidth,
3349 verticalDirection = this._getDragVerticalDirection(),
3350 horizontalDirection = this._getDragHorizontalDirection();
3351
3352 if (!isOverElement)
3353 return false;
3354
3355 return this.floating ?
3356 ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
3357 : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
3358
3359 },
3360
3361 _intersectsWithSides: function(item) {
3362
3363 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
3364 isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
3365 verticalDirection = this._getDragVerticalDirection(),
3366 horizontalDirection = this._getDragHorizontalDirection();
3367
3368 if (this.floating && horizontalDirection) {
3369 return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
3370 } else {
3371 return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
3372 }
3373
3374 },
3375
3376 _getDragVerticalDirection: function() {
3377 var delta = this.positionAbs.top - this.lastPositionAbs.top;
3378 return delta != 0 && (delta > 0 ? "down" : "up");
3379 },
3380
3381 _getDragHorizontalDirection: function() {
3382 var delta = this.positionAbs.left - this.lastPositionAbs.left;
3383 return delta != 0 && (delta > 0 ? "right" : "left");
3384 },
3385
3386 refresh: function(event) {
3387 this._refreshItems(event);
3388 this.refreshPositions();
3389 return this;
3390 },
3391
3392 _connectWith: function() {
3393 var options = this.options;
3394 return options.connectWith.constructor == String
3395 ? [options.connectWith]
3396 : options.connectWith;
3397 },
3398
3399 _getItemsAsjQuery: function(connected) {
3400
3401 var self = this;
3402 var items = [];
3403 var queries = [];
3404 var connectWith = this._connectWith();
3405
3406 if(connectWith && connected) {
3407 for (var i = connectWith.length - 1; i >= 0; i--){
3408 var cur = $(connectWith[i]);
3409 for (var j = cur.length - 1; j >= 0; j--){
3410 var inst = $.data(cur[j], 'sortable');
3411 if(inst && inst != this && !inst.options.disabled) {
3412 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]);
3413 }
3414 };
3415 };
3416 }
3417
3418 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]);
3419
3420 for (var i = queries.length - 1; i >= 0; i--){
3421 queries[i][0].each(function() {
3422 items.push(this);
3423 });
3424 };
3425
3426 return $(items);
3427
3428 },
3429
3430 _removeCurrentsFromItems: function() {
3431
3432 var list = this.currentItem.find(":data(sortable-item)");
3433
3434 for (var i=0; i < this.items.length; i++) {
3435
3436 for (var j=0; j < list.length; j++) {
3437 if(list[j] == this.items[i].item[0])
3438 this.items.splice(i,1);
3439 };
3440
3441 };
3442
3443 },
3444
3445 _refreshItems: function(event) {
3446
3447 this.items = [];
3448 this.containers = [this];
3449 var items = this.items;
3450 var self = this;
3451 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
3452 var connectWith = this._connectWith();
3453
3454 if(connectWith) {
3455 for (var i = connectWith.length - 1; i >= 0; i--){
3456 var cur = $(connectWith[i]);
3457 for (var j = cur.length - 1; j >= 0; j--){
3458 var inst = $.data(cur[j], 'sortable');
3459 if(inst && inst != this && !inst.options.disabled) {
3460 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
3461 this.containers.push(inst);
3462 }
3463 };
3464 };
3465 }
3466
3467 for (var i = queries.length - 1; i >= 0; i--) {
3468 var targetData = queries[i][1];
3469 var _queries = queries[i][0];
3470
3471 for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
3472 var item = $(_queries[j]);
3473
3474 item.data('sortable-item', targetData); // Data for target checking (mouse manager)
3475
3476 items.push({
3477 item: item,
3478 instance: targetData,
3479 width: 0, height: 0,
3480 left: 0, top: 0
3481 });
3482 };
3483 };
3484
3485 },
3486
3487 refreshPositions: function(fast) {
3488
3489 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
3490 if(this.offsetParent && this.helper) {
3491 this.offset.parent = this._getParentOffset();
3492 }
3493
3494 for (var i = this.items.length - 1; i >= 0; i--){
3495 var item = this.items[i];
3496
3497 var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
3498
3499 if (!fast) {
3500 item.width = t.outerWidth();
3501 item.height = t.outerHeight();
3502 }
3503
3504 var p = t.offset();
3505 item.left = p.left;
3506 item.top = p.top;
3507 };
3508
3509 if(this.options.custom && this.options.custom.refreshContainers) {
3510 this.options.custom.refreshContainers.call(this);
3511 } else {
3512 for (var i = this.containers.length - 1; i >= 0; i--){
3513 var p = this.containers[i].element.offset();
3514 this.containers[i].containerCache.left = p.left;
3515 this.containers[i].containerCache.top = p.top;
3516 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
3517 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
3518 };
3519 }
3520
3521 return this;
3522 },
3523
3524 _createPlaceholder: function(that) {
3525
3526 var self = that || this, o = self.options;
3527
3528 if(!o.placeholder || o.placeholder.constructor == String) {
3529 var className = o.placeholder;
3530 o.placeholder = {
3531 element: function() {
3532
3533 var el = $(document.createElement(self.currentItem[0].nodeName))
3534 .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
3535 .removeClass("ui-sortable-helper")[0];
3536
3537 if(!className)
3538 el.style.visibility = "hidden";
3539
3540 return el;
3541 },
3542 update: function(container, p) {
3543
3544 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
3545 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
3546 if(className && !o.forcePlaceholderSize) return;
3547
3548 //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
3549 if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
3550 if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
3551 }
3552 };
3553 }
3554
3555 //Create the placeholder
3556 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
3557
3558 //Append it after the actual current item
3559 self.currentItem.after(self.placeholder);
3560
3561 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
3562 o.placeholder.update(self, self.placeholder);
3563
3564 },
3565
3566 _contactContainers: function(event) {
3567
3568 // get innermost container that intersects with item
3569 var innermostContainer = null, innermostIndex = null;
3570
3571
3572 for (var i = this.containers.length - 1; i >= 0; i--){
3573
3574 // never consider a container that's located within the item itself
3575 if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
3576 continue;
3577
3578 if(this._intersectsWith(this.containers[i].containerCache)) {
3579
3580 // if we've already found a container and it's more "inner" than this, then continue
3581 if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
3582 continue;
3583
3584 innermostContainer = this.containers[i];
3585 innermostIndex = i;
3586
3587 } else {
3588 // container doesn't intersect. trigger "out" event if necessary
3589 if(this.containers[i].containerCache.over) {
3590 this.containers[i]._trigger("out", event, this._uiHash(this));
3591 this.containers[i].containerCache.over = 0;
3592 }
3593 }
3594
3595 }
3596
3597 // if no intersecting containers found, return
3598 if(!innermostContainer) return;
3599
3600 // move the item into the container if it's not there already
3601 if(this.containers.length === 1) {
3602 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3603 this.containers[innermostIndex].containerCache.over = 1;
3604 } else if(this.currentContainer != this.containers[innermostIndex]) {
3605
3606 //When entering a new container, we will find the item with the least distance and append our item near it
3607 var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
3608 for (var j = this.items.length - 1; j >= 0; j--) {
3609 if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
3610 var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top'];
3611 if(Math.abs(cur - base) < dist) {
3612 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
3613 }
3614 }
3615
3616 if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
3617 return;
3618
3619 this.currentContainer = this.containers[innermostIndex];
3620 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
3621 this._trigger("change", event, this._uiHash());
3622 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
3623
3624 //Update the placeholder
3625 this.options.placeholder.update(this.currentContainer, this.placeholder);
3626
3627 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3628 this.containers[innermostIndex].containerCache.over = 1;
3629 }
3630
3631
3632 },
3633
3634 _createHelper: function(event) {
3635
3636 var o = this.options;
3637 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
3638
3639 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
3640 $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
3641
3642 if(helper[0] == this.currentItem[0])
3643 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") };
3644
3645 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
3646 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
3647
3648 return helper;
3649
3650 },
3651
3652 _adjustOffsetFromHelper: function(obj) {
3653 if (typeof obj == 'string') {
3654 obj = obj.split(' ');
3655 }
3656 if ($.isArray(obj)) {
3657 obj = {left: +obj[0], top: +obj[1] || 0};
3658 }
3659 if ('left' in obj) {
3660 this.offset.click.left = obj.left + this.margins.left;
3661 }
3662 if ('right' in obj) {
3663 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
3664 }
3665 if ('top' in obj) {
3666 this.offset.click.top = obj.top + this.margins.top;
3667 }
3668 if ('bottom' in obj) {
3669 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
3670 }
3671 },
3672
3673 _getParentOffset: function() {
3674
3675
3676 //Get the offsetParent and cache its position
3677 this.offsetParent = this.helper.offsetParent();
3678 var po = this.offsetParent.offset();
3679
3680 // This is a special case where we need to modify a offset calculated on start, since the following happened:
3681 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
3682 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
3683 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
3684 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
3685 po.left += this.scrollParent.scrollLeft();
3686 po.top += this.scrollParent.scrollTop();
3687 }
3688
3689 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
3690 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
3691 po = { top: 0, left: 0 };
3692
3693 return {
3694 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
3695 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
3696 };
3697
3698 },
3699
3700 _getRelativeOffset: function() {
3701
3702 if(this.cssPosition == "relative") {
3703 var p = this.currentItem.position();
3704 return {
3705 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
3706 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
3707 };
3708 } else {
3709 return { top: 0, left: 0 };
3710 }
3711
3712 },
3713
3714 _cacheMargins: function() {
3715 this.margins = {
3716 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
3717 top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
3718 };
3719 },
3720
3721 _cacheHelperProportions: function() {
3722 this.helperProportions = {
3723 width: this.helper.outerWidth(),
3724 height: this.helper.outerHeight()
3725 };
3726 },
3727
3728 _setContainment: function() {
3729
3730 var o = this.options;
3731 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
3732 if(o.containment == 'document' || o.containment == 'window') this.containment = [
3733 0 - this.offset.relative.left - this.offset.parent.left,
3734 0 - this.offset.relative.top - this.offset.parent.top,
3735 $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
3736 ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
3737 ];
3738
3739 if(!(/^(document|window|parent)$/).test(o.containment)) {
3740 var ce = $(o.containment)[0];
3741 var co = $(o.containment).offset();
3742 var over = ($(ce).css("overflow") != 'hidden');
3743
3744 this.containment = [
3745 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
3746 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
3747 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,
3748 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
3749 ];
3750 }
3751
3752 },
3753
3754 _convertPositionTo: function(d, pos) {
3755
3756 if(!pos) pos = this.position;
3757 var mod = d == "absolute" ? 1 : -1;
3758 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);
3759
3760 return {
3761 top: (
3762 pos.top // The absolute mouse position
3763 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
3764 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
3765 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
3766 ),
3767 left: (
3768 pos.left // The absolute mouse position
3769 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
3770 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
3771 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
3772 )
3773 };
3774
3775 },
3776
3777 _generatePosition: function(event) {
3778
3779 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);
3780
3781 // This is another very weird special case that only happens for relative elements:
3782 // 1. If the css position is relative
3783 // 2. and the scroll parent is the document or similar to the offset parent
3784 // we have to refresh the relative offset during the scroll so there are no jumps
3785 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
3786 this.offset.relative = this._getRelativeOffset();
3787 }
3788
3789 var pageX = event.pageX;
3790 var pageY = event.pageY;
3791
3792 /*
3793 * - Position constraining -
3794 * Constrain the position to a mix of grid, containment.
3795 */
3796
3797 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
3798
3799 if(this.containment) {
3800 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
3801 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
3802 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
3803 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
3804 }
3805
3806 if(o.grid) {
3807 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
3808 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;
3809
3810 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
3811 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;
3812 }
3813
3814 }
3815
3816 return {
3817 top: (
3818 pageY // The absolute mouse position
3819 - this.offset.click.top // Click offset (relative to the element)
3820 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
3821 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
3822 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
3823 ),
3824 left: (
3825 pageX // The absolute mouse position
3826 - this.offset.click.left // Click offset (relative to the element)
3827 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
3828 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
3829 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
3830 )
3831 };
3832
3833 },
3834
3835 _rearrange: function(event, i, a, hardRefresh) {
3836
3837 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));
3838
3839 //Various things done here to improve the performance:
3840 // 1. we create a setTimeout, that calls refreshPositions
3841 // 2. on the instance, we have a counter variable, that get's higher after every append
3842 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
3843 // 4. this lets only the last addition to the timeout stack through
3844 this.counter = this.counter ? ++this.counter : 1;
3845 var self = this, counter = this.counter;
3846
3847 window.setTimeout(function() {
3848 if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
3849 },0);
3850
3851 },
3852
3853 _clear: function(event, noPropagation) {
3854
3855 this.reverting = false;
3856 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
3857 // everything else normalized again
3858 var delayedTriggers = [], self = this;
3859
3860 // We first have to update the dom position of the actual currentItem
3861 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
3862 if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
3863 this._noFinalSort = null;
3864
3865 if(this.helper[0] == this.currentItem[0]) {
3866 for(var i in this._storedCSS) {
3867 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
3868 }
3869 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3870 } else {
3871 this.currentItem.show();
3872 }
3873
3874 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
3875 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
3876 if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
3877 if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
3878 for (var i = this.containers.length - 1; i >= 0; i--){
3879 if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
3880 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
3881 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
3882 }
3883 };
3884 };
3885
3886 //Post events to containers
3887 for (var i = this.containers.length - 1; i >= 0; i--){
3888 if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
3889 if(this.containers[i].containerCache.over) {
3890 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
3891 this.containers[i].containerCache.over = 0;
3892 }
3893 }
3894
3895 //Do what was originally in plugins
3896 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
3897 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
3898 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
3899
3900 this.dragging = false;
3901 if(this.cancelHelperRemoval) {
3902 if(!noPropagation) {
3903 this._trigger("beforeStop", event, this._uiHash());
3904 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
3905 this._trigger("stop", event, this._uiHash());
3906 }
3907 return false;
3908 }
3909
3910 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
3911
3912 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3913 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3914
3915 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
3916
3917 if(!noPropagation) {
3918 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
3919 this._trigger("stop", event, this._uiHash());
3920 }
3921
3922 this.fromOutside = false;
3923 return true;
3924
3925 },
3926
3927 _trigger: function() {
3928 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
3929 this.cancel();
3930 }
3931 },
3932
3933 _uiHash: function(inst) {
3934 var self = inst || this;
3935 return {
3936 helper: self.helper,
3937 placeholder: self.placeholder || $([]),
3938 position: self.position,
3939 originalPosition: self.originalPosition,
3940 offset: self.positionAbs,
3941 item: self.currentItem,
3942 sender: inst ? inst.element : null
3943 };
3944 }
3945
3946});
3947
3948$.extend($.ui.sortable, {
3949 version: "1.8.7"
3950});
3951
3952})(jQuery);
3953/*
3954 * jQuery UI Effects 1.8.7
3955 *
3956 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
3957 * Dual licensed under the MIT or GPL Version 2 licenses.
3958 * http://jquery.org/license
3959 *
3960 * http://docs.jquery.com/UI/Effects/
3961 */
3962;jQuery.effects || (function($, undefined) {
3963
3964$.effects = {};
3965
3966
3967
3968/******************************************************************************/
3969/****************************** COLOR ANIMATIONS ******************************/
3970/******************************************************************************/
3971
3972// override the animation for color styles
3973$.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
3974 'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
3975function(i, attr) {
3976 $.fx.step[attr] = function(fx) {
3977 if (!fx.colorInit) {
3978 fx.start = getColor(fx.elem, attr);
3979 fx.end = getRGB(fx.end);
3980 fx.colorInit = true;
3981 }
3982
3983 fx.elem.style[attr] = 'rgb(' +
3984 Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
3985 Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
3986 Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
3987 };
3988});
3989
3990// Color Conversion functions from highlightFade
3991// By Blair Mitchelmore
3992// http://jquery.offput.ca/highlightFade/
3993
3994// Parse strings looking for color tuples [255,255,255]
3995function getRGB(color) {
3996 var result;
3997
3998 // Check if we're already dealing with an array of colors
3999 if ( color && color.constructor == Array && color.length == 3 )
4000 return color;
4001
4002 // Look for rgb(num,num,num)
4003 if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
4004 return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
4005
4006 // Look for rgb(num%,num%,num%)
4007 if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
4008 return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
4009
4010 // Look for #a0b1c2
4011 if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
4012 return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
4013
4014 // Look for #fff
4015 if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
4016 return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
4017
4018 // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
4019 if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
4020 return colors['transparent'];
4021
4022 // Otherwise, we're most likely dealing with a named color
4023 return colors[$.trim(color).toLowerCase()];
4024}
4025
4026function getColor(elem, attr) {
4027 var color;
4028
4029 do {
4030 color = $.curCSS(elem, attr);
4031
4032 // Keep going until we find an element that has color, or we hit the body
4033 if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
4034 break;
4035
4036 attr = "backgroundColor";
4037 } while ( elem = elem.parentNode );
4038
4039 return getRGB(color);
4040};
4041
4042// Some named colors to work with
4043// From Interface by Stefan Petre
4044// http://interface.eyecon.ro/
4045
4046var colors = {
4047 aqua:[0,255,255],
4048 azure:[240,255,255],
4049 beige:[245,245,220],
4050 black:[0,0,0],
4051 blue:[0,0,255],
4052 brown:[165,42,42],
4053 cyan:[0,255,255],
4054 darkblue:[0,0,139],
4055 darkcyan:[0,139,139],
4056 darkgrey:[169,169,169],
4057 darkgreen:[0,100,0],
4058 darkkhaki:[189,183,107],
4059 darkmagenta:[139,0,139],
4060 darkolivegreen:[85,107,47],
4061 darkorange:[255,140,0],
4062 darkorchid:[153,50,204],
4063 darkred:[139,0,0],
4064 darksalmon:[233,150,122],
4065 darkviolet:[148,0,211],
4066 fuchsia:[255,0,255],
4067 gold:[255,215,0],
4068 green:[0,128,0],
4069 indigo:[75,0,130],
4070 khaki:[240,230,140],
4071 lightblue:[173,216,230],
4072 lightcyan:[224,255,255],
4073 lightgreen:[144,238,144],
4074 lightgrey:[211,211,211],
4075 lightpink:[255,182,193],
4076 lightyellow:[255,255,224],
4077 lime:[0,255,0],
4078 magenta:[255,0,255],
4079 maroon:[128,0,0],
4080 navy:[0,0,128],
4081 olive:[128,128,0],
4082 orange:[255,165,0],
4083 pink:[255,192,203],
4084 purple:[128,0,128],
4085 violet:[128,0,128],
4086 red:[255,0,0],
4087 silver:[192,192,192],
4088 white:[255,255,255],
4089 yellow:[255,255,0],
4090 transparent: [255,255,255]
4091};
4092
4093
4094
4095/******************************************************************************/
4096/****************************** CLASS ANIMATIONS ******************************/
4097/******************************************************************************/
4098
4099var classAnimationActions = ['add', 'remove', 'toggle'],
4100 shorthandStyles = {
4101 border: 1,
4102 borderBottom: 1,
4103 borderColor: 1,
4104 borderLeft: 1,
4105 borderRight: 1,
4106 borderTop: 1,
4107 borderWidth: 1,
4108 margin: 1,
4109 padding: 1
4110 };
4111
4112function getElementStyles() {
4113 var style = document.defaultView
4114 ? document.defaultView.getComputedStyle(this, null)
4115 : this.currentStyle,
4116 newStyle = {},
4117 key,
4118 camelCase;
4119
4120 // webkit enumerates style porperties
4121 if (style && style.length && style[0] && style[style[0]]) {
4122 var len = style.length;
4123 while (len--) {
4124 key = style[len];
4125 if (typeof style[key] == 'string') {
4126 camelCase = key.replace(/\-(\w)/g, function(all, letter){
4127 return letter.toUpperCase();
4128 });
4129 newStyle[camelCase] = style[key];
4130 }
4131 }
4132 } else {
4133 for (key in style) {
4134 if (typeof style[key] === 'string') {
4135 newStyle[key] = style[key];
4136 }
4137 }
4138 }
4139
4140 return newStyle;
4141}
4142
4143function filterStyles(styles) {
4144 var name, value;
4145 for (name in styles) {
4146 value = styles[name];
4147 if (
4148 // ignore null and undefined values
4149 value == null ||
4150 // ignore functions (when does this occur?)
4151 $.isFunction(value) ||
4152 // shorthand styles that need to be expanded
4153 name in shorthandStyles ||
4154 // ignore scrollbars (break in IE)
4155 (/scrollbar/).test(name) ||
4156
4157 // only colors or values that can be converted to numbers
4158 (!(/color/i).test(name) && isNaN(parseFloat(value)))
4159 ) {
4160 delete styles[name];
4161 }
4162 }
4163
4164 return styles;
4165}
4166
4167function styleDifference(oldStyle, newStyle) {
4168 var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
4169 name;
4170
4171 for (name in newStyle) {
4172 if (oldStyle[name] != newStyle[name]) {
4173 diff[name] = newStyle[name];
4174 }
4175 }
4176
4177 return diff;
4178}
4179
4180$.effects.animateClass = function(value, duration, easing, callback) {
4181 if ($.isFunction(easing)) {
4182 callback = easing;
4183 easing = null;
4184 }
4185
4186 return this.each(function() {
4187 $.queue(this, 'fx', function() {
4188 var that = $(this),
4189 originalStyleAttr = that.attr('style') || ' ',
4190 originalStyle = filterStyles(getElementStyles.call(this)),
4191 newStyle,
4192 className = that.attr('className');
4193
4194 $.each(classAnimationActions, function(i, action) {
4195 if (value[action]) {
4196 that[action + 'Class'](value[action]);
4197 }
4198 });
4199 newStyle = filterStyles(getElementStyles.call(this));
4200 that.attr('className', className);
4201
4202 that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
4203 $.each(classAnimationActions, function(i, action) {
4204 if (value[action]) { that[action + 'Class'](value[action]); }
4205 });
4206 // work around bug in IE by clearing the cssText before setting it
4207 if (typeof that.attr('style') == 'object') {
4208 that.attr('style').cssText = '';
4209 that.attr('style').cssText = originalStyleAttr;
4210 } else {
4211 that.attr('style', originalStyleAttr);
4212 }
4213 if (callback) { callback.apply(this, arguments); }
4214 });
4215
4216 // $.animate adds a function to the end of the queue
4217 // but we want it at the front
4218 var queue = $.queue(this),
4219 anim = queue.splice(queue.length - 1, 1)[0];
4220 queue.splice(1, 0, anim);
4221 $.dequeue(this);
4222 });
4223 });
4224};
4225
4226$.fn.extend({
4227 _addClass: $.fn.addClass,
4228 addClass: function(classNames, speed, easing, callback) {
4229 return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
4230 },
4231
4232 _removeClass: $.fn.removeClass,
4233 removeClass: function(classNames,speed,easing,callback) {
4234 return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
4235 },
4236
4237 _toggleClass: $.fn.toggleClass,
4238 toggleClass: function(classNames, force, speed, easing, callback) {
4239 if ( typeof force == "boolean" || force === undefined ) {
4240 if ( !speed ) {
4241 // without speed parameter;
4242 return this._toggleClass(classNames, force);
4243 } else {
4244 return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
4245 }
4246 } else {
4247 // without switch parameter;
4248 return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
4249 }
4250 },
4251
4252 switchClass: function(remove,add,speed,easing,callback) {
4253 return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
4254 }
4255});
4256
4257
4258
4259/******************************************************************************/
4260/*********************************** EFFECTS **********************************/
4261/******************************************************************************/
4262
4263$.extend($.effects, {
4264 version: "1.8.7",
4265
4266 // Saves a set of properties in a data storage
4267 save: function(element, set) {
4268 for(var i=0; i < set.length; i++) {
4269 if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
4270 }
4271 },
4272
4273 // Restores a set of previously saved properties from a data storage
4274 restore: function(element, set) {
4275 for(var i=0; i < set.length; i++) {
4276 if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
4277 }
4278 },
4279
4280 setMode: function(el, mode) {
4281 if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
4282 return mode;
4283 },
4284
4285 getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
4286 // this should be a little more flexible in the future to handle a string & hash
4287 var y, x;
4288 switch (origin[0]) {
4289 case 'top': y = 0; break;
4290 case 'middle': y = 0.5; break;
4291 case 'bottom': y = 1; break;
4292 default: y = origin[0] / original.height;
4293 };
4294 switch (origin[1]) {
4295 case 'left': x = 0; break;
4296 case 'center': x = 0.5; break;
4297 case 'right': x = 1; break;
4298 default: x = origin[1] / original.width;
4299 };
4300 return {x: x, y: y};
4301 },
4302
4303 // Wraps the element around a wrapper that copies position properties
4304 createWrapper: function(element) {
4305
4306 // if the element is already wrapped, return it
4307 if (element.parent().is('.ui-effects-wrapper')) {
4308 return element.parent();
4309 }
4310
4311 // wrap the element
4312 var props = {
4313 width: element.outerWidth(true),
4314 height: element.outerHeight(true),
4315 'float': element.css('float')
4316 },
4317 wrapper = $('<div></div>')
4318 .addClass('ui-effects-wrapper')
4319 .css({
4320 fontSize: '100%',
4321 background: 'transparent',
4322 border: 'none',
4323 margin: 0,
4324 padding: 0
4325 });
4326
4327 element.wrap(wrapper);
4328 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
4329
4330 // transfer positioning properties to the wrapper
4331 if (element.css('position') == 'static') {
4332 wrapper.css({ position: 'relative' });
4333 element.css({ position: 'relative' });
4334 } else {
4335 $.extend(props, {
4336 position: element.css('position'),
4337 zIndex: element.css('z-index')
4338 });
4339 $.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
4340 props[pos] = element.css(pos);
4341 if (isNaN(parseInt(props[pos], 10))) {
4342 props[pos] = 'auto';
4343 }
4344 });
4345 element.css({position: 'relative', top: 0, left: 0 });
4346 }
4347
4348 return wrapper.css(props).show();
4349 },
4350
4351 removeWrapper: function(element) {
4352 if (element.parent().is('.ui-effects-wrapper'))
4353 return element.parent().replaceWith(element);
4354 return element;
4355 },
4356
4357 setTransition: function(element, list, factor, value) {
4358 value = value || {};
4359 $.each(list, function(i, x){
4360 unit = element.cssUnit(x);
4361 if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
4362 });
4363 return value;
4364 }
4365});
4366
4367
4368function _normalizeArguments(effect, options, speed, callback) {
4369 // shift params for method overloading
4370 if (typeof effect == 'object') {
4371 callback = options;
4372 speed = null;
4373 options = effect;
4374 effect = options.effect;
4375 }
4376 if ($.isFunction(options)) {
4377 callback = options;
4378 speed = null;
4379 options = {};
4380 }
4381 if (typeof options == 'number' || $.fx.speeds[options]) {
4382 callback = speed;
4383 speed = options;
4384 options = {};
4385 }
4386 if ($.isFunction(speed)) {
4387 callback = speed;
4388 speed = null;
4389 }
4390
4391 options = options || {};
4392
4393 speed = speed || options.duration;
4394 speed = $.fx.off ? 0 : typeof speed == 'number'
4395 ? speed : speed in $.fx.speeds ? $.fx.speeds[speed] : $.fx.speeds._default;
4396
4397 callback = callback || options.complete;
4398
4399 return [effect, options, speed, callback];
4400}
4401
4402function standardSpeed( speed ) {
4403 // valid standard speeds
4404 if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
4405 return true;
4406 }
4407
4408 // invalid strings - treat as "normal" speed
4409 if ( typeof speed === "string" && !$.effects[ speed ] ) {
4410 return true;
4411 }
4412
4413 return false;
4414}
4415
4416$.fn.extend({
4417 effect: function(effect, options, speed, callback) {
4418 var args = _normalizeArguments.apply(this, arguments),
4419 // TODO: make effects take actual parameters instead of a hash
4420 args2 = {
4421 options: args[1],
4422 duration: args[2],
4423 callback: args[3]
4424 },
4425 mode = args2.options.mode,
4426 effectMethod = $.effects[effect];
4427
4428 if ( $.fx.off || !effectMethod ) {
4429 // delegate to the original method (e.g., .show()) if possible
4430 if ( mode ) {
4431 return this[ mode ]( args2.duration, args2.callback );
4432 } else {
4433 return this.each(function() {
4434 if ( args2.callback ) {
4435 args2.callback.call( this );
4436 }
4437 });
4438 }
4439 }
4440
4441 return effectMethod.call(this, args2);
4442 },
4443
4444 _show: $.fn.show,
4445 show: function(speed) {
4446 if ( standardSpeed( speed ) ) {
4447 return this._show.apply(this, arguments);
4448 } else {
4449 var args = _normalizeArguments.apply(this, arguments);
4450 args[1].mode = 'show';
4451 return this.effect.apply(this, args);
4452 }
4453 },
4454
4455 _hide: $.fn.hide,
4456 hide: function(speed) {
4457 if ( standardSpeed( speed ) ) {
4458 return this._hide.apply(this, arguments);
4459 } else {
4460 var args = _normalizeArguments.apply(this, arguments);
4461 args[1].mode = 'hide';
4462 return this.effect.apply(this, args);
4463 }
4464 },
4465
4466 // jQuery core overloads toggle and creates _toggle
4467 __toggle: $.fn.toggle,
4468 toggle: function(speed) {
4469 if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
4470 return this.__toggle.apply(this, arguments);
4471 } else {
4472 var args = _normalizeArguments.apply(this, arguments);
4473 args[1].mode = 'toggle';
4474 return this.effect.apply(this, args);
4475 }
4476 },
4477
4478 // helper functions
4479 cssUnit: function(key) {
4480 var style = this.css(key), val = [];
4481 $.each( ['em','px','%','pt'], function(i, unit){
4482 if(style.indexOf(unit) > 0)
4483 val = [parseFloat(style), unit];
4484 });
4485 return val;
4486 }
4487});
4488
4489
4490
4491/******************************************************************************/
4492/*********************************** EASING ***********************************/
4493/******************************************************************************/
4494
4495/*
4496 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
4497 *
4498 * Uses the built in easing capabilities added In jQuery 1.1
4499 * to offer multiple easing options
4500 *
4501 * TERMS OF USE - jQuery Easing
4502 *
4503 * Open source under the BSD License.
4504 *
4505 * Copyright 2008 George McGinley Smith
4506 * All rights reserved.
4507 *
4508 * Redistribution and use in source and binary forms, with or without modification,
4509 * are permitted provided that the following conditions are met:
4510 *
4511 * Redistributions of source code must retain the above copyright notice, this list of
4512 * conditions and the following disclaimer.
4513 * Redistributions in binary form must reproduce the above copyright notice, this list
4514 * of conditions and the following disclaimer in the documentation and/or other materials
4515 * provided with the distribution.
4516 *
4517 * Neither the name of the author nor the names of contributors may be used to endorse
4518 * or promote products derived from this software without specific prior written permission.
4519 *
4520 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
4521 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
4522 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
4523 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4524 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
4525 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
4526 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4527 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
4528 * OF THE POSSIBILITY OF SUCH DAMAGE.
4529 *
4530*/
4531
4532// t: current time, b: begInnIng value, c: change In value, d: duration
4533$.easing.jswing = $.easing.swing;
4534
4535$.extend($.easing,
4536{
4537 def: 'easeOutQuad',
4538 swing: function (x, t, b, c, d) {
4539 //alert($.easing.default);
4540 return $.easing[$.easing.def](x, t, b, c, d);
4541 },
4542 easeInQuad: function (x, t, b, c, d) {
4543 return c*(t/=d)*t + b;
4544 },
4545 easeOutQuad: function (x, t, b, c, d) {
4546 return -c *(t/=d)*(t-2) + b;
4547 },
4548 easeInOutQuad: function (x, t, b, c, d) {
4549 if ((t/=d/2) < 1) return c/2*t*t + b;
4550 return -c/2 * ((--t)*(t-2) - 1) + b;
4551 },
4552 easeInCubic: function (x, t, b, c, d) {
4553 return c*(t/=d)*t*t + b;
4554 },
4555 easeOutCubic: function (x, t, b, c, d) {
4556 return c*((t=t/d-1)*t*t + 1) + b;
4557 },
4558 easeInOutCubic: function (x, t, b, c, d) {
4559 if ((t/=d/2) < 1) return c/2*t*t*t + b;
4560 return c/2*((t-=2)*t*t + 2) + b;
4561 },
4562 easeInQuart: function (x, t, b, c, d) {
4563 return c*(t/=d)*t*t*t + b;
4564 },
4565 easeOutQuart: function (x, t, b, c, d) {
4566 return -c * ((t=t/d-1)*t*t*t - 1) + b;
4567 },
4568 easeInOutQuart: function (x, t, b, c, d) {
4569 if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
4570 return -c/2 * ((t-=2)*t*t*t - 2) + b;
4571 },
4572 easeInQuint: function (x, t, b, c, d) {
4573 return c*(t/=d)*t*t*t*t + b;
4574 },
4575 easeOutQuint: function (x, t, b, c, d) {
4576 return c*((t=t/d-1)*t*t*t*t + 1) + b;
4577 },
4578 easeInOutQuint: function (x, t, b, c, d) {
4579 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
4580 return c/2*((t-=2)*t*t*t*t + 2) + b;
4581 },
4582 easeInSine: function (x, t, b, c, d) {
4583 return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
4584 },
4585 easeOutSine: function (x, t, b, c, d) {
4586 return c * Math.sin(t/d * (Math.PI/2)) + b;
4587 },
4588 easeInOutSine: function (x, t, b, c, d) {
4589 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
4590 },
4591 easeInExpo: function (x, t, b, c, d) {
4592 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
4593 },
4594 easeOutExpo: function (x, t, b, c, d) {
4595 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
4596 },
4597 easeInOutExpo: function (x, t, b, c, d) {
4598 if (t==0) return b;
4599 if (t==d) return b+c;
4600 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
4601 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
4602 },
4603 easeInCirc: function (x, t, b, c, d) {
4604 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
4605 },
4606 easeOutCirc: function (x, t, b, c, d) {
4607 return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
4608 },
4609 easeInOutCirc: function (x, t, b, c, d) {
4610 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
4611 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
4612 },
4613 easeInElastic: function (x, t, b, c, d) {
4614 var s=1.70158;var p=0;var a=c;
4615 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
4616 if (a < Math.abs(c)) { a=c; var s=p/4; }
4617 else var s = p/(2*Math.PI) * Math.asin (c/a);
4618 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
4619 },
4620 easeOutElastic: function (x, t, b, c, d) {
4621 var s=1.70158;var p=0;var a=c;
4622 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
4623 if (a < Math.abs(c)) { a=c; var s=p/4; }
4624 else var s = p/(2*Math.PI) * Math.asin (c/a);
4625 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
4626 },
4627 easeInOutElastic: function (x, t, b, c, d) {
4628 var s=1.70158;var p=0;var a=c;
4629 if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
4630 if (a < Math.abs(c)) { a=c; var s=p/4; }
4631 else var s = p/(2*Math.PI) * Math.asin (c/a);
4632 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
4633 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
4634 },
4635 easeInBack: function (x, t, b, c, d, s) {
4636 if (s == undefined) s = 1.70158;
4637 return c*(t/=d)*t*((s+1)*t - s) + b;
4638 },
4639 easeOutBack: function (x, t, b, c, d, s) {
4640 if (s == undefined) s = 1.70158;
4641 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
4642 },
4643 easeInOutBack: function (x, t, b, c, d, s) {
4644 if (s == undefined) s = 1.70158;
4645 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
4646 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
4647 },
4648 easeInBounce: function (x, t, b, c, d) {
4649 return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
4650 },
4651 easeOutBounce: function (x, t, b, c, d) {
4652 if ((t/=d) < (1/2.75)) {
4653 return c*(7.5625*t*t) + b;
4654 } else if (t < (2/2.75)) {
4655 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
4656 } else if (t < (2.5/2.75)) {
4657 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
4658 } else {
4659 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
4660 }
4661 },
4662 easeInOutBounce: function (x, t, b, c, d) {
4663 if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
4664 return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
4665 }
4666});
4667
4668/*
4669 *
4670 * TERMS OF USE - EASING EQUATIONS
4671 *
4672 * Open source under the BSD License.
4673 *
4674 * Copyright 2001 Robert Penner
4675 * All rights reserved.
4676 *
4677 * Redistribution and use in source and binary forms, with or without modification,
4678 * are permitted provided that the following conditions are met:
4679 *
4680 * Redistributions of source code must retain the above copyright notice, this list of
4681 * conditions and the following disclaimer.
4682 * Redistributions in binary form must reproduce the above copyright notice, this list
4683 * of conditions and the following disclaimer in the documentation and/or other materials
4684 * provided with the distribution.
4685 *
4686 * Neither the name of the author nor the names of contributors may be used to endorse
4687 * or promote products derived from this software without specific prior written permission.
4688 *
4689 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
4690 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
4691 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
4692 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
4693 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
4694 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
4695 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4696 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
4697 * OF THE POSSIBILITY OF SUCH DAMAGE.
4698 *
4699 */
4700
4701})(jQuery);
4702/*
4703 * jQuery UI Effects Blind 1.8.7
4704 *
4705 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
4706 * Dual licensed under the MIT or GPL Version 2 licenses.
4707 * http://jquery.org/license
4708 *
4709 * http://docs.jquery.com/UI/Effects/Blind
4710 *
4711 * Depends:
4712 * jquery.effects.core.js
4713 */
4714(function( $, undefined ) {
4715
4716$.effects.blind = function(o) {
4717
4718 return this.queue(function() {
4719
4720 // Create element
4721 var el = $(this), props = ['position','top','left'];
4722
4723 // Set options
4724 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
4725 var direction = o.options.direction || 'vertical'; // Default direction
4726
4727 // Adjust
4728 $.effects.save(el, props); el.show(); // Save & Show
4729 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
4730 var ref = (direction == 'vertical') ? 'height' : 'width';
4731 var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
4732 if(mode == 'show') wrapper.css(ref, 0); // Shift
4733
4734 // Animation
4735 var animation = {};
4736 animation[ref] = mode == 'show' ? distance : 0;
4737
4738 // Animate
4739 wrapper.animate(animation, o.duration, o.options.easing, function() {
4740 if(mode == 'hide') el.hide(); // Hide
4741 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
4742 if(o.callback) o.callback.apply(el[0], arguments); // Callback
4743 el.dequeue();
4744 });
4745
4746 });
4747
4748};
4749
4750})(jQuery);
4751/*
4752 * jQuery UI Effects Bounce 1.8.7
4753 *
4754 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
4755 * Dual licensed under the MIT or GPL Version 2 licenses.
4756 * http://jquery.org/license
4757 *
4758 * http://docs.jquery.com/UI/Effects/Bounce
4759 *
4760 * Depends:
4761 * jquery.effects.core.js
4762 */
4763(function( $, undefined ) {
4764
4765$.effects.bounce = function(o) {
4766
4767 return this.queue(function() {
4768
4769 // Create element
4770 var el = $(this), props = ['position','top','left'];
4771
4772 // Set options
4773 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
4774 var direction = o.options.direction || 'up'; // Default direction
4775 var distance = o.options.distance || 20; // Default distance
4776 var times = o.options.times || 5; // Default # of times
4777 var speed = o.duration || 250; // Default speed per bounce
4778 if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
4779
4780 // Adjust
4781 $.effects.save(el, props); el.show(); // Save & Show
4782 $.effects.createWrapper(el); // Create Wrapper
4783 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
4784 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
4785 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
4786 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
4787 if (mode == 'hide') distance = distance / (times * 2);
4788 if (mode != 'hide') times--;
4789
4790 // Animate
4791 if (mode == 'show') { // Show Bounce
4792 var animation = {opacity: 1};
4793 animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
4794 el.animate(animation, speed / 2, o.options.easing);
4795 distance = distance / 2;
4796 times--;
4797 };
4798 for (var i = 0; i < times; i++) { // Bounces
4799 var animation1 = {}, animation2 = {};
4800 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
4801 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
4802 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
4803 distance = (mode == 'hide') ? distance * 2 : distance / 2;
4804 };
4805 if (mode == 'hide') { // Last Bounce
4806 var animation = {opacity: 0};
4807 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
4808 el.animate(animation, speed / 2, o.options.easing, function(){
4809 el.hide(); // Hide
4810 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
4811 if(o.callback) o.callback.apply(this, arguments); // Callback
4812 });
4813 } else {
4814 var animation1 = {}, animation2 = {};
4815 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
4816 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
4817 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
4818 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
4819 if(o.callback) o.callback.apply(this, arguments); // Callback
4820 });
4821 };
4822 el.queue('fx', function() { el.dequeue(); });
4823 el.dequeue();
4824 });
4825
4826};
4827
4828})(jQuery);
4829/*
4830 * jQuery UI Effects Clip 1.8.7
4831 *
4832 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
4833 * Dual licensed under the MIT or GPL Version 2 licenses.
4834 * http://jquery.org/license
4835 *
4836 * http://docs.jquery.com/UI/Effects/Clip
4837 *
4838 * Depends:
4839 * jquery.effects.core.js
4840 */
4841(function( $, undefined ) {
4842
4843$.effects.clip = function(o) {
4844
4845 return this.queue(function() {
4846
4847 // Create element
4848 var el = $(this), props = ['position','top','left','height','width'];
4849
4850 // Set options
4851 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
4852 var direction = o.options.direction || 'vertical'; // Default direction
4853
4854 // Adjust
4855 $.effects.save(el, props); el.show(); // Save & Show
4856 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
4857 var animate = el[0].tagName == 'IMG' ? wrapper : el;
4858 var ref = {
4859 size: (direction == 'vertical') ? 'height' : 'width',
4860 position: (direction == 'vertical') ? 'top' : 'left'
4861 };
4862 var distance = (direction == 'vertical') ? animate.height() : animate.width();
4863 if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
4864
4865 // Animation
4866 var animation = {};
4867 animation[ref.size] = mode == 'show' ? distance : 0;
4868 animation[ref.position] = mode == 'show' ? 0 : distance / 2;
4869
4870 // Animate
4871 animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
4872 if(mode == 'hide') el.hide(); // Hide
4873 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
4874 if(o.callback) o.callback.apply(el[0], arguments); // Callback
4875 el.dequeue();
4876 }});
4877
4878 });
4879
4880};
4881
4882})(jQuery);
4883/*
4884 * jQuery UI Effects Drop 1.8.7
4885 *
4886 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
4887 * Dual licensed under the MIT or GPL Version 2 licenses.
4888 * http://jquery.org/license
4889 *
4890 * http://docs.jquery.com/UI/Effects/Drop
4891 *
4892 * Depends:
4893 * jquery.effects.core.js
4894 */
4895(function( $, undefined ) {
4896
4897$.effects.drop = function(o) {
4898
4899 return this.queue(function() {
4900
4901 // Create element
4902 var el = $(this), props = ['position','top','left','opacity'];
4903
4904 // Set options
4905 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
4906 var direction = o.options.direction || 'left'; // Default Direction
4907
4908 // Adjust
4909 $.effects.save(el, props); el.show(); // Save & Show
4910 $.effects.createWrapper(el); // Create Wrapper
4911 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
4912 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
4913 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
4914 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
4915
4916 // Animation
4917 var animation = {opacity: mode == 'show' ? 1 : 0};
4918 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
4919
4920 // Animate
4921 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
4922 if(mode == 'hide') el.hide(); // Hide
4923 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
4924 if(o.callback) o.callback.apply(this, arguments); // Callback
4925 el.dequeue();
4926 }});
4927
4928 });
4929
4930};
4931
4932})(jQuery);
4933/*
4934 * jQuery UI Effects Explode 1.8.7
4935 *
4936 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
4937 * Dual licensed under the MIT or GPL Version 2 licenses.
4938 * http://jquery.org/license
4939 *
4940 * http://docs.jquery.com/UI/Effects/Explode
4941 *
4942 * Depends:
4943 * jquery.effects.core.js
4944 */
4945(function( $, undefined ) {
4946
4947$.effects.explode = function(o) {
4948
4949 return this.queue(function() {
4950
4951 var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
4952 var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
4953
4954 o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
4955 var el = $(this).show().css('visibility', 'hidden');
4956 var offset = el.offset();
4957
4958 //Substract the margins - not fixing the problem yet.
4959 offset.top -= parseInt(el.css("marginTop"),10) || 0;
4960 offset.left -= parseInt(el.css("marginLeft"),10) || 0;
4961
4962 var width = el.outerWidth(true);
4963 var height = el.outerHeight(true);
4964
4965 for(var i=0;i<rows;i++) { // =
4966 for(var j=0;j<cells;j++) { // ||
4967 el
4968 .clone()
4969 .appendTo('body')
4970 .wrap('<div></div>')
4971 .css({
4972 position: 'absolute',
4973 visibility: 'visible',
4974 left: -j*(width/cells),
4975 top: -i*(height/rows)
4976 })
4977 .parent()
4978 .addClass('ui-effects-explode')
4979 .css({
4980 position: 'absolute',
4981 overflow: 'hidden',
4982 width: width/cells,
4983 height: height/rows,
4984 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
4985 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
4986 opacity: o.options.mode == 'show' ? 0 : 1
4987 }).animate({
4988 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
4989 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
4990 opacity: o.options.mode == 'show' ? 1 : 0
4991 }, o.duration || 500);
4992 }
4993 }
4994
4995 // Set a timeout, to call the callback approx. when the other animations have finished
4996 setTimeout(function() {
4997
4998 o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
4999 if(o.callback) o.callback.apply(el[0]); // Callback
5000 el.dequeue();
5001
5002 $('div.ui-effects-explode').remove();
5003
5004 }, o.duration || 500);
5005
5006
5007 });
5008
5009};
5010
5011})(jQuery);
5012/*
5013 * jQuery UI Effects Fade 1.8.7
5014 *
5015 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5016 * Dual licensed under the MIT or GPL Version 2 licenses.
5017 * http://jquery.org/license
5018 *
5019 * http://docs.jquery.com/UI/Effects/Fade
5020 *
5021 * Depends:
5022 * jquery.effects.core.js
5023 */
5024(function( $, undefined ) {
5025
5026$.effects.fade = function(o) {
5027 return this.queue(function() {
5028 var elem = $(this),
5029 mode = $.effects.setMode(elem, o.options.mode || 'hide');
5030
5031 elem.animate({ opacity: mode }, {
5032 queue: false,
5033 duration: o.duration,
5034 easing: o.options.easing,
5035 complete: function() {
5036 (o.callback && o.callback.apply(this, arguments));
5037 elem.dequeue();
5038 }
5039 });
5040 });
5041};
5042
5043})(jQuery);
5044/*
5045 * jQuery UI Effects Fold 1.8.7
5046 *
5047 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5048 * Dual licensed under the MIT or GPL Version 2 licenses.
5049 * http://jquery.org/license
5050 *
5051 * http://docs.jquery.com/UI/Effects/Fold
5052 *
5053 * Depends:
5054 * jquery.effects.core.js
5055 */
5056(function( $, undefined ) {
5057
5058$.effects.fold = function(o) {
5059
5060 return this.queue(function() {
5061
5062 // Create element
5063 var el = $(this), props = ['position','top','left'];
5064
5065 // Set options
5066 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
5067 var size = o.options.size || 15; // Default fold size
5068 var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
5069 var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
5070
5071 // Adjust
5072 $.effects.save(el, props); el.show(); // Save & Show
5073 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
5074 var widthFirst = ((mode == 'show') != horizFirst);
5075 var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
5076 var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
5077 var percent = /([0-9]+)%/.exec(size);
5078 if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
5079 if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
5080
5081 // Animation
5082 var animation1 = {}, animation2 = {};
5083 animation1[ref[0]] = mode == 'show' ? distance[0] : size;
5084 animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
5085
5086 // Animate
5087 wrapper.animate(animation1, duration, o.options.easing)
5088 .animate(animation2, duration, o.options.easing, function() {
5089 if(mode == 'hide') el.hide(); // Hide
5090 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
5091 if(o.callback) o.callback.apply(el[0], arguments); // Callback
5092 el.dequeue();
5093 });
5094
5095 });
5096
5097};
5098
5099})(jQuery);
5100/*
5101 * jQuery UI Effects Highlight 1.8.7
5102 *
5103 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5104 * Dual licensed under the MIT or GPL Version 2 licenses.
5105 * http://jquery.org/license
5106 *
5107 * http://docs.jquery.com/UI/Effects/Highlight
5108 *
5109 * Depends:
5110 * jquery.effects.core.js
5111 */
5112(function( $, undefined ) {
5113
5114$.effects.highlight = function(o) {
5115 return this.queue(function() {
5116 var elem = $(this),
5117 props = ['backgroundImage', 'backgroundColor', 'opacity'],
5118 mode = $.effects.setMode(elem, o.options.mode || 'show'),
5119 animation = {
5120 backgroundColor: elem.css('backgroundColor')
5121 };
5122
5123 if (mode == 'hide') {
5124 animation.opacity = 0;
5125 }
5126
5127 $.effects.save(elem, props);
5128 elem
5129 .show()
5130 .css({
5131 backgroundImage: 'none',
5132 backgroundColor: o.options.color || '#ffff99'
5133 })
5134 .animate(animation, {
5135 queue: false,
5136 duration: o.duration,
5137 easing: o.options.easing,
5138 complete: function() {
5139 (mode == 'hide' && elem.hide());
5140 $.effects.restore(elem, props);
5141 (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
5142 (o.callback && o.callback.apply(this, arguments));
5143 elem.dequeue();
5144 }
5145 });
5146 });
5147};
5148
5149})(jQuery);
5150/*
5151 * jQuery UI Effects Pulsate 1.8.7
5152 *
5153 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5154 * Dual licensed under the MIT or GPL Version 2 licenses.
5155 * http://jquery.org/license
5156 *
5157 * http://docs.jquery.com/UI/Effects/Pulsate
5158 *
5159 * Depends:
5160 * jquery.effects.core.js
5161 */
5162(function( $, undefined ) {
5163
5164$.effects.pulsate = function(o) {
5165 return this.queue(function() {
5166 var elem = $(this),
5167 mode = $.effects.setMode(elem, o.options.mode || 'show');
5168 times = ((o.options.times || 5) * 2) - 1;
5169 duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
5170 isVisible = elem.is(':visible'),
5171 animateTo = 0;
5172
5173 if (!isVisible) {
5174 elem.css('opacity', 0).show();
5175 animateTo = 1;
5176 }
5177
5178 if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
5179 times--;
5180 }
5181
5182 for (var i = 0; i < times; i++) {
5183 elem.animate({ opacity: animateTo }, duration, o.options.easing);
5184 animateTo = (animateTo + 1) % 2;
5185 }
5186
5187 elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
5188 if (animateTo == 0) {
5189 elem.hide();
5190 }
5191 (o.callback && o.callback.apply(this, arguments));
5192 });
5193
5194 elem
5195 .queue('fx', function() { elem.dequeue(); })
5196 .dequeue();
5197 });
5198};
5199
5200})(jQuery);
5201/*
5202 * jQuery UI Effects Scale 1.8.7
5203 *
5204 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5205 * Dual licensed under the MIT or GPL Version 2 licenses.
5206 * http://jquery.org/license
5207 *
5208 * http://docs.jquery.com/UI/Effects/Scale
5209 *
5210 * Depends:
5211 * jquery.effects.core.js
5212 */
5213(function( $, undefined ) {
5214
5215$.effects.puff = function(o) {
5216 return this.queue(function() {
5217 var elem = $(this),
5218 mode = $.effects.setMode(elem, o.options.mode || 'hide'),
5219 percent = parseInt(o.options.percent, 10) || 150,
5220 factor = percent / 100,
5221 original = { height: elem.height(), width: elem.width() };
5222
5223 $.extend(o.options, {
5224 fade: true,
5225 mode: mode,
5226 percent: mode == 'hide' ? percent : 100,
5227 from: mode == 'hide'
5228 ? original
5229 : {
5230 height: original.height * factor,
5231 width: original.width * factor
5232 }
5233 });
5234
5235 elem.effect('scale', o.options, o.duration, o.callback);
5236 elem.dequeue();
5237 });
5238};
5239
5240$.effects.scale = function(o) {
5241
5242 return this.queue(function() {
5243
5244 // Create element
5245 var el = $(this);
5246
5247 // Set options
5248 var options = $.extend(true, {}, o.options);
5249 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
5250 var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
5251 var direction = o.options.direction || 'both'; // Set default axis
5252 var origin = o.options.origin; // The origin of the scaling
5253 if (mode != 'effect') { // Set default origin and restore for show/hide
5254 options.origin = origin || ['middle','center'];
5255 options.restore = true;
5256 }
5257 var original = {height: el.height(), width: el.width()}; // Save original
5258 el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
5259
5260 // Adjust
5261 var factor = { // Set scaling factor
5262 y: direction != 'horizontal' ? (percent / 100) : 1,
5263 x: direction != 'vertical' ? (percent / 100) : 1
5264 };
5265 el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
5266
5267 if (o.options.fade) { // Fade option to support puff
5268 if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
5269 if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
5270 };
5271
5272 // Animation
5273 options.from = el.from; options.to = el.to; options.mode = mode;
5274
5275 // Animate
5276 el.effect('size', options, o.duration, o.callback);
5277 el.dequeue();
5278 });
5279
5280};
5281
5282$.effects.size = function(o) {
5283
5284 return this.queue(function() {
5285
5286 // Create element
5287 var el = $(this), props = ['position','top','left','width','height','overflow','opacity'];
5288 var props1 = ['position','top','left','overflow','opacity']; // Always restore
5289 var props2 = ['width','height','overflow']; // Copy for children
5290 var cProps = ['fontSize'];
5291 var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
5292 var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
5293
5294 // Set options
5295 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
5296 var restore = o.options.restore || false; // Default restore
5297 var scale = o.options.scale || 'both'; // Default scale mode
5298 var origin = o.options.origin; // The origin of the sizing
5299 var original = {height: el.height(), width: el.width()}; // Save original
5300 el.from = o.options.from || original; // Default from state
5301 el.to = o.options.to || original; // Default to state
5302 // Adjust
5303 if (origin) { // Calculate baseline shifts
5304 var baseline = $.effects.getBaseline(origin, original);
5305 el.from.top = (original.height - el.from.height) * baseline.y;
5306 el.from.left = (original.width - el.from.width) * baseline.x;
5307 el.to.top = (original.height - el.to.height) * baseline.y;
5308 el.to.left = (original.width - el.to.width) * baseline.x;
5309 };
5310 var factor = { // Set scaling factor
5311 from: {y: el.from.height / original.height, x: el.from.width / original.width},
5312 to: {y: el.to.height / original.height, x: el.to.width / original.width}
5313 };
5314 if (scale == 'box' || scale == 'both') { // Scale the css box
5315 if (factor.from.y != factor.to.y) { // Vertical props scaling
5316 props = props.concat(vProps);
5317 el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
5318 el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
5319 };
5320 if (factor.from.x != factor.to.x) { // Horizontal props scaling
5321 props = props.concat(hProps);
5322 el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
5323 el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
5324 };
5325 };
5326 if (scale == 'content' || scale == 'both') { // Scale the content
5327 if (factor.from.y != factor.to.y) { // Vertical props scaling
5328 props = props.concat(cProps);
5329 el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
5330 el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
5331 };
5332 };
5333 $.effects.save(el, restore ? props : props1); el.show(); // Save & Show
5334 $.effects.createWrapper(el); // Create Wrapper
5335 el.css('overflow','hidden').css(el.from); // Shift
5336
5337 // Animate
5338 if (scale == 'content' || scale == 'both') { // Scale the children
5339 vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
5340 hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
5341 props2 = props.concat(vProps).concat(hProps); // Concat
5342 el.find("*[width]").each(function(){
5343 child = $(this);
5344 if (restore) $.effects.save(child, props2);
5345 var c_original = {height: child.height(), width: child.width()}; // Save original
5346 child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
5347 child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
5348 if (factor.from.y != factor.to.y) { // Vertical props scaling
5349 child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
5350 child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
5351 };
5352 if (factor.from.x != factor.to.x) { // Horizontal props scaling
5353 child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
5354 child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
5355 };
5356 child.css(child.from); // Shift children
5357 child.animate(child.to, o.duration, o.options.easing, function(){
5358 if (restore) $.effects.restore(child, props2); // Restore children
5359 }); // Animate children
5360 });
5361 };
5362
5363 // Animate
5364 el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
5365 if (el.to.opacity === 0) {
5366 el.css('opacity', el.from.opacity);
5367 }
5368 if(mode == 'hide') el.hide(); // Hide
5369 $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
5370 if(o.callback) o.callback.apply(this, arguments); // Callback
5371 el.dequeue();
5372 }});
5373
5374 });
5375
5376};
5377
5378})(jQuery);
5379/*
5380 * jQuery UI Effects Shake 1.8.7
5381 *
5382 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5383 * Dual licensed under the MIT or GPL Version 2 licenses.
5384 * http://jquery.org/license
5385 *
5386 * http://docs.jquery.com/UI/Effects/Shake
5387 *
5388 * Depends:
5389 * jquery.effects.core.js
5390 */
5391(function( $, undefined ) {
5392
5393$.effects.shake = function(o) {
5394
5395 return this.queue(function() {
5396
5397 // Create element
5398 var el = $(this), props = ['position','top','left'];
5399
5400 // Set options
5401 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
5402 var direction = o.options.direction || 'left'; // Default direction
5403 var distance = o.options.distance || 20; // Default distance
5404 var times = o.options.times || 3; // Default # of times
5405 var speed = o.duration || o.options.duration || 140; // Default speed per shake
5406
5407 // Adjust
5408 $.effects.save(el, props); el.show(); // Save & Show
5409 $.effects.createWrapper(el); // Create Wrapper
5410 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
5411 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
5412
5413 // Animation
5414 var animation = {}, animation1 = {}, animation2 = {};
5415 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
5416 animation1[ref] = (motion == 'pos' ? '+=' : '-=') + distance * 2;
5417 animation2[ref] = (motion == 'pos' ? '-=' : '+=') + distance * 2;
5418
5419 // Animate
5420 el.animate(animation, speed, o.options.easing);
5421 for (var i = 1; i < times; i++) { // Shakes
5422 el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
5423 };
5424 el.animate(animation1, speed, o.options.easing).
5425 animate(animation, speed / 2, o.options.easing, function(){ // Last shake
5426 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
5427 if(o.callback) o.callback.apply(this, arguments); // Callback
5428 });
5429 el.queue('fx', function() { el.dequeue(); });
5430 el.dequeue();
5431 });
5432
5433};
5434
5435})(jQuery);
5436/*
5437 * jQuery UI Effects Slide 1.8.7
5438 *
5439 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5440 * Dual licensed under the MIT or GPL Version 2 licenses.
5441 * http://jquery.org/license
5442 *
5443 * http://docs.jquery.com/UI/Effects/Slide
5444 *
5445 * Depends:
5446 * jquery.effects.core.js
5447 */
5448(function( $, undefined ) {
5449
5450$.effects.slide = function(o) {
5451
5452 return this.queue(function() {
5453
5454 // Create element
5455 var el = $(this), props = ['position','top','left'];
5456
5457 // Set options
5458 var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
5459 var direction = o.options.direction || 'left'; // Default Direction
5460
5461 // Adjust
5462 $.effects.save(el, props); el.show(); // Save & Show
5463 $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
5464 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
5465 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
5466 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
5467 if (mode == 'show') el.css(ref, motion == 'pos' ? (isNaN(distance) ? "-" + distance : -distance) : distance); // Shift
5468
5469 // Animation
5470 var animation = {};
5471 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
5472
5473 // Animate
5474 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
5475 if(mode == 'hide') el.hide(); // Hide
5476 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
5477 if(o.callback) o.callback.apply(this, arguments); // Callback
5478 el.dequeue();
5479 }});
5480
5481 });
5482
5483};
5484
5485})(jQuery);
5486/*
5487 * jQuery UI Effects Transfer 1.8.7
5488 *
5489 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5490 * Dual licensed under the MIT or GPL Version 2 licenses.
5491 * http://jquery.org/license
5492 *
5493 * http://docs.jquery.com/UI/Effects/Transfer
5494 *
5495 * Depends:
5496 * jquery.effects.core.js
5497 */
5498(function( $, undefined ) {
5499
5500$.effects.transfer = function(o) {
5501 return this.queue(function() {
5502 var elem = $(this),
5503 target = $(o.options.to),
5504 endPosition = target.offset(),
5505 animation = {
5506 top: endPosition.top,
5507 left: endPosition.left,
5508 height: target.innerHeight(),
5509 width: target.innerWidth()
5510 },
5511 startPosition = elem.offset(),
5512 transfer = $('<div class="ui-effects-transfer"></div>')
5513 .appendTo(document.body)
5514 .addClass(o.options.className)
5515 .css({
5516 top: startPosition.top,
5517 left: startPosition.left,
5518 height: elem.innerHeight(),
5519 width: elem.innerWidth(),
5520 position: 'absolute'
5521 })
5522 .animate(animation, o.duration, o.options.easing, function() {
5523 transfer.remove();
5524 (o.callback && o.callback.apply(elem[0], arguments));
5525 elem.dequeue();
5526 });
5527 });
5528};
5529
5530})(jQuery);
5531/*
5532 * jQuery UI Accordion 1.8.7
5533 *
5534 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5535 * Dual licensed under the MIT or GPL Version 2 licenses.
5536 * http://jquery.org/license
5537 *
5538 * http://docs.jquery.com/UI/Accordion
5539 *
5540 * Depends:
5541 * jquery.ui.core.js
5542 * jquery.ui.widget.js
5543 */
5544(function( $, undefined ) {
5545
5546$.widget( "ui.accordion", {
5547 options: {
5548 active: 0,
5549 animated: "slide",
5550 autoHeight: true,
5551 clearStyle: false,
5552 collapsible: false,
5553 event: "click",
5554 fillSpace: false,
5555 header: "> li > :first-child,> :not(li):even",
5556 icons: {
5557 header: "ui-icon-triangle-1-e",
5558 headerSelected: "ui-icon-triangle-1-s"
5559 },
5560 navigation: false,
5561 navigationFilter: function() {
5562 return this.href.toLowerCase() === location.href.toLowerCase();
5563 }
5564 },
5565
5566 _create: function() {
5567 var self = this,
5568 options = self.options;
5569
5570 self.running = 0;
5571
5572 self.element
5573 .addClass( "ui-accordion ui-widget ui-helper-reset" )
5574 // in lack of child-selectors in CSS
5575 // we need to mark top-LIs in a UL-accordion for some IE-fix
5576 .children( "li" )
5577 .addClass( "ui-accordion-li-fix" );
5578
5579 self.headers = self.element.find( options.header )
5580 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
5581 .bind( "mouseenter.accordion", function() {
5582 if ( options.disabled ) {
5583 return;
5584 }
5585 $( this ).addClass( "ui-state-hover" );
5586 })
5587 .bind( "mouseleave.accordion", function() {
5588 if ( options.disabled ) {
5589 return;
5590 }
5591 $( this ).removeClass( "ui-state-hover" );
5592 })
5593 .bind( "focus.accordion", function() {
5594 if ( options.disabled ) {
5595 return;
5596 }
5597 $( this ).addClass( "ui-state-focus" );
5598 })
5599 .bind( "blur.accordion", function() {
5600 if ( options.disabled ) {
5601 return;
5602 }
5603 $( this ).removeClass( "ui-state-focus" );
5604 });
5605
5606 self.headers.next()
5607 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
5608
5609 if ( options.navigation ) {
5610 var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
5611 if ( current.length ) {
5612 var header = current.closest( ".ui-accordion-header" );
5613 if ( header.length ) {
5614 // anchor within header
5615 self.active = header;
5616 } else {
5617 // anchor within content
5618 self.active = current.closest( ".ui-accordion-content" ).prev();
5619 }
5620 }
5621 }
5622
5623 self.active = self._findActive( self.active || options.active )
5624 .addClass( "ui-state-default ui-state-active" )
5625 .toggleClass( "ui-corner-all" )
5626 .toggleClass( "ui-corner-top" );
5627 self.active.next().addClass( "ui-accordion-content-active" );
5628
5629 self._createIcons();
5630 self.resize();
5631
5632 // ARIA
5633 self.element.attr( "role", "tablist" );
5634
5635 self.headers
5636 .attr( "role", "tab" )
5637 .bind( "keydown.accordion", function( event ) {
5638 return self._keydown( event );
5639 })
5640 .next()
5641 .attr( "role", "tabpanel" );
5642
5643 self.headers
5644 .not( self.active || "" )
5645 .attr({
5646 "aria-expanded": "false",
5647 tabIndex: -1
5648 })
5649 .next()
5650 .hide();
5651
5652 // make sure at least one header is in the tab order
5653 if ( !self.active.length ) {
5654 self.headers.eq( 0 ).attr( "tabIndex", 0 );
5655 } else {
5656 self.active
5657 .attr({
5658 "aria-expanded": "true",
5659 tabIndex: 0
5660 });
5661 }
5662
5663 // only need links in tab order for Safari
5664 if ( !$.browser.safari ) {
5665 self.headers.find( "a" ).attr( "tabIndex", -1 );
5666 }
5667
5668 if ( options.event ) {
5669 self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
5670 self._clickHandler.call( self, event, this );
5671 event.preventDefault();
5672 });
5673 }
5674 },
5675
5676 _createIcons: function() {
5677 var options = this.options;
5678 if ( options.icons ) {
5679 $( "<span></span>" )
5680 .addClass( "ui-icon " + options.icons.header )
5681 .prependTo( this.headers );
5682 this.active.children( ".ui-icon" )
5683 .toggleClass(options.icons.header)
5684 .toggleClass(options.icons.headerSelected);
5685 this.element.addClass( "ui-accordion-icons" );
5686 }
5687 },
5688
5689 _destroyIcons: function() {
5690 this.headers.children( ".ui-icon" ).remove();
5691 this.element.removeClass( "ui-accordion-icons" );
5692 },
5693
5694 destroy: function() {
5695 var options = this.options;
5696
5697 this.element
5698 .removeClass( "ui-accordion ui-widget ui-helper-reset" )
5699 .removeAttr( "role" );
5700
5701 this.headers
5702 .unbind( ".accordion" )
5703 .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" )
5704 .removeAttr( "role" )
5705 .removeAttr( "aria-expanded" )
5706 .removeAttr( "tabIndex" );
5707
5708 this.headers.find( "a" ).removeAttr( "tabIndex" );
5709 this._destroyIcons();
5710 var contents = this.headers.next()
5711 .css( "display", "" )
5712 .removeAttr( "role" )
5713 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
5714 if ( options.autoHeight || options.fillHeight ) {
5715 contents.css( "height", "" );
5716 }
5717
5718 return $.Widget.prototype.destroy.call( this );
5719 },
5720
5721 _setOption: function( key, value ) {
5722 $.Widget.prototype._setOption.apply( this, arguments );
5723
5724 if ( key == "active" ) {
5725 this.activate( value );
5726 }
5727 if ( key == "icons" ) {
5728 this._destroyIcons();
5729 if ( value ) {
5730 this._createIcons();
5731 }
5732 }
5733 // #5332 - opacity doesn't cascade to positioned elements in IE
5734 // so we need to add the disabled class to the headers and panels
5735 if ( key == "disabled" ) {
5736 this.headers.add(this.headers.next())
5737 [ value ? "addClass" : "removeClass" ](
5738 "ui-accordion-disabled ui-state-disabled" );
5739 }
5740 },
5741
5742 _keydown: function( event ) {
5743 if ( this.options.disabled || event.altKey || event.ctrlKey ) {
5744 return;
5745 }
5746
5747 var keyCode = $.ui.keyCode,
5748 length = this.headers.length,
5749 currentIndex = this.headers.index( event.target ),
5750 toFocus = false;
5751
5752 switch ( event.keyCode ) {
5753 case keyCode.RIGHT:
5754 case keyCode.DOWN:
5755 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
5756 break;
5757 case keyCode.LEFT:
5758 case keyCode.UP:
5759 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
5760 break;
5761 case keyCode.SPACE:
5762 case keyCode.ENTER:
5763 this._clickHandler( { target: event.target }, event.target );
5764 event.preventDefault();
5765 }
5766
5767 if ( toFocus ) {
5768 $( event.target ).attr( "tabIndex", -1 );
5769 $( toFocus ).attr( "tabIndex", 0 );
5770 toFocus.focus();
5771 return false;
5772 }
5773
5774 return true;
5775 },
5776
5777 resize: function() {
5778 var options = this.options,
5779 maxHeight;
5780
5781 if ( options.fillSpace ) {
5782 if ( $.browser.msie ) {
5783 var defOverflow = this.element.parent().css( "overflow" );
5784 this.element.parent().css( "overflow", "hidden");
5785 }
5786 maxHeight = this.element.parent().height();
5787 if ($.browser.msie) {
5788 this.element.parent().css( "overflow", defOverflow );
5789 }
5790
5791 this.headers.each(function() {
5792 maxHeight -= $( this ).outerHeight( true );
5793 });
5794
5795 this.headers.next()
5796 .each(function() {
5797 $( this ).height( Math.max( 0, maxHeight -
5798 $( this ).innerHeight() + $( this ).height() ) );
5799 })
5800 .css( "overflow", "auto" );
5801 } else if ( options.autoHeight ) {
5802 maxHeight = 0;
5803 this.headers.next()
5804 .each(function() {
5805 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
5806 })
5807 .height( maxHeight );
5808 }
5809
5810 return this;
5811 },
5812
5813 activate: function( index ) {
5814 // TODO this gets called on init, changing the option without an explicit call for that
5815 this.options.active = index;
5816 // call clickHandler with custom event
5817 var active = this._findActive( index )[ 0 ];
5818 this._clickHandler( { target: active }, active );
5819
5820 return this;
5821 },
5822
5823 _findActive: function( selector ) {
5824 return selector
5825 ? typeof selector === "number"
5826 ? this.headers.filter( ":eq(" + selector + ")" )
5827 : this.headers.not( this.headers.not( selector ) )
5828 : selector === false
5829 ? $( [] )
5830 : this.headers.filter( ":eq(0)" );
5831 },
5832
5833 // TODO isn't event.target enough? why the separate target argument?
5834 _clickHandler: function( event, target ) {
5835 var options = this.options;
5836 if ( options.disabled ) {
5837 return;
5838 }
5839
5840 // called only when using activate(false) to close all parts programmatically
5841 if ( !event.target ) {
5842 if ( !options.collapsible ) {
5843 return;
5844 }
5845 this.active
5846 .removeClass( "ui-state-active ui-corner-top" )
5847 .addClass( "ui-state-default ui-corner-all" )
5848 .children( ".ui-icon" )
5849 .removeClass( options.icons.headerSelected )
5850 .addClass( options.icons.header );
5851 this.active.next().addClass( "ui-accordion-content-active" );
5852 var toHide = this.active.next(),
5853 data = {
5854 options: options,
5855 newHeader: $( [] ),
5856 oldHeader: options.active,
5857 newContent: $( [] ),
5858 oldContent: toHide
5859 },
5860 toShow = ( this.active = $( [] ) );
5861 this._toggle( toShow, toHide, data );
5862 return;
5863 }
5864
5865 // get the click target
5866 var clicked = $( event.currentTarget || target ),
5867 clickedIsActive = clicked[0] === this.active[0];
5868
5869 // TODO the option is changed, is that correct?
5870 // TODO if it is correct, shouldn't that happen after determining that the click is valid?
5871 options.active = options.collapsible && clickedIsActive ?
5872 false :
5873 this.headers.index( clicked );
5874
5875 // if animations are still active, or the active header is the target, ignore click
5876 if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
5877 return;
5878 }
5879
5880 // switch classes
5881 this.active
5882 .removeClass( "ui-state-active ui-corner-top" )
5883 .addClass( "ui-state-default ui-corner-all" )
5884 .children( ".ui-icon" )
5885 .removeClass( options.icons.headerSelected )
5886 .addClass( options.icons.header );
5887 if ( !clickedIsActive ) {
5888 clicked
5889 .removeClass( "ui-state-default ui-corner-all" )
5890 .addClass( "ui-state-active ui-corner-top" )
5891 .children( ".ui-icon" )
5892 .removeClass( options.icons.header )
5893 .addClass( options.icons.headerSelected );
5894 clicked
5895 .next()
5896 .addClass( "ui-accordion-content-active" );
5897 }
5898
5899 // find elements to show and hide
5900 var toShow = clicked.next(),
5901 toHide = this.active.next(),
5902 data = {
5903 options: options,
5904 newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
5905 oldHeader: this.active,
5906 newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
5907 oldContent: toHide
5908 },
5909 down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
5910
5911 this.active = clickedIsActive ? $([]) : clicked;
5912 this._toggle( toShow, toHide, data, clickedIsActive, down );
5913
5914 return;
5915 },
5916
5917 _toggle: function( toShow, toHide, data, clickedIsActive, down ) {
5918 var self = this,
5919 options = self.options;
5920
5921 self.toShow = toShow;
5922 self.toHide = toHide;
5923 self.data = data;
5924
5925 var complete = function() {
5926 if ( !self ) {
5927 return;
5928 }
5929 return self._completed.apply( self, arguments );
5930 };
5931
5932 // trigger changestart event
5933 self._trigger( "changestart", null, self.data );
5934
5935 // count elements to animate
5936 self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
5937
5938 if ( options.animated ) {
5939 var animOptions = {};
5940
5941 if ( options.collapsible && clickedIsActive ) {
5942 animOptions = {
5943 toShow: $( [] ),
5944 toHide: toHide,
5945 complete: complete,
5946 down: down,
5947 autoHeight: options.autoHeight || options.fillSpace
5948 };
5949 } else {
5950 animOptions = {
5951 toShow: toShow,
5952 toHide: toHide,
5953 complete: complete,
5954 down: down,
5955 autoHeight: options.autoHeight || options.fillSpace
5956 };
5957 }
5958
5959 if ( !options.proxied ) {
5960 options.proxied = options.animated;
5961 }
5962
5963 if ( !options.proxiedDuration ) {
5964 options.proxiedDuration = options.duration;
5965 }
5966
5967 options.animated = $.isFunction( options.proxied ) ?
5968 options.proxied( animOptions ) :
5969 options.proxied;
5970
5971 options.duration = $.isFunction( options.proxiedDuration ) ?
5972 options.proxiedDuration( animOptions ) :
5973 options.proxiedDuration;
5974
5975 var animations = $.ui.accordion.animations,
5976 duration = options.duration,
5977 easing = options.animated;
5978
5979 if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
5980 easing = "slide";
5981 }
5982 if ( !animations[ easing ] ) {
5983 animations[ easing ] = function( options ) {
5984 this.slide( options, {
5985 easing: easing,
5986 duration: duration || 700
5987 });
5988 };
5989 }
5990
5991 animations[ easing ]( animOptions );
5992 } else {
5993 if ( options.collapsible && clickedIsActive ) {
5994 toShow.toggle();
5995 } else {
5996 toHide.hide();
5997 toShow.show();
5998 }
5999
6000 complete( true );
6001 }
6002
6003 // TODO assert that the blur and focus triggers are really necessary, remove otherwise
6004 toHide.prev()
6005 .attr({
6006 "aria-expanded": "false",
6007 tabIndex: -1
6008 })
6009 .blur();
6010 toShow.prev()
6011 .attr({
6012 "aria-expanded": "true",
6013 tabIndex: 0
6014 })
6015 .focus();
6016 },
6017
6018 _completed: function( cancel ) {
6019 this.running = cancel ? 0 : --this.running;
6020 if ( this.running ) {
6021 return;
6022 }
6023
6024 if ( this.options.clearStyle ) {
6025 this.toShow.add( this.toHide ).css({
6026 height: "",
6027 overflow: ""
6028 });
6029 }
6030
6031 // other classes are removed before the animation; this one needs to stay until completed
6032 this.toHide.removeClass( "ui-accordion-content-active" );
6033
6034 this._trigger( "change", null, this.data );
6035 }
6036});
6037
6038$.extend( $.ui.accordion, {
6039 version: "1.8.7",
6040 animations: {
6041 slide: function( options, additions ) {
6042 options = $.extend({
6043 easing: "swing",
6044 duration: 300
6045 }, options, additions );
6046 if ( !options.toHide.size() ) {
6047 options.toShow.animate({
6048 height: "show",
6049 paddingTop: "show",
6050 paddingBottom: "show"
6051 }, options );
6052 return;
6053 }
6054 if ( !options.toShow.size() ) {
6055 options.toHide.animate({
6056 height: "hide",
6057 paddingTop: "hide",
6058 paddingBottom: "hide"
6059 }, options );
6060 return;
6061 }
6062 var overflow = options.toShow.css( "overflow" ),
6063 percentDone = 0,
6064 showProps = {},
6065 hideProps = {},
6066 fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
6067 originalWidth;
6068 // fix width before calculating height of hidden element
6069 var s = options.toShow;
6070 originalWidth = s[0].style.width;
6071 s.width( parseInt( s.parent().width(), 10 )
6072 - parseInt( s.css( "paddingLeft" ), 10 )
6073 - parseInt( s.css( "paddingRight" ), 10 )
6074 - ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
6075 - ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
6076
6077 $.each( fxAttrs, function( i, prop ) {
6078 hideProps[ prop ] = "hide";
6079
6080 var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
6081 showProps[ prop ] = {
6082 value: parts[ 1 ],
6083 unit: parts[ 2 ] || "px"
6084 };
6085 });
6086 options.toShow.css({ height: 0, overflow: "hidden" }).show();
6087 options.toHide
6088 .filter( ":hidden" )
6089 .each( options.complete )
6090 .end()
6091 .filter( ":visible" )
6092 .animate( hideProps, {
6093 step: function( now, settings ) {
6094 // only calculate the percent when animating height
6095 // IE gets very inconsistent results when animating elements
6096 // with small values, which is common for padding
6097 if ( settings.prop == "height" ) {
6098 percentDone = ( settings.end - settings.start === 0 ) ? 0 :
6099 ( settings.now - settings.start ) / ( settings.end - settings.start );
6100 }
6101
6102 options.toShow[ 0 ].style[ settings.prop ] =
6103 ( percentDone * showProps[ settings.prop ].value )
6104 + showProps[ settings.prop ].unit;
6105 },
6106 duration: options.duration,
6107 easing: options.easing,
6108 complete: function() {
6109 if ( !options.autoHeight ) {
6110 options.toShow.css( "height", "" );
6111 }
6112 options.toShow.css({
6113 width: originalWidth,
6114 overflow: overflow
6115 });
6116 options.complete();
6117 }
6118 });
6119 },
6120 bounceslide: function( options ) {
6121 this.slide( options, {
6122 easing: options.down ? "easeOutBounce" : "swing",
6123 duration: options.down ? 1000 : 200
6124 });
6125 }
6126 }
6127});
6128
6129})( jQuery );
6130/*
6131 * jQuery UI Autocomplete 1.8.7
6132 *
6133 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
6134 * Dual licensed under the MIT or GPL Version 2 licenses.
6135 * http://jquery.org/license
6136 *
6137 * http://docs.jquery.com/UI/Autocomplete
6138 *
6139 * Depends:
6140 * jquery.ui.core.js
6141 * jquery.ui.widget.js
6142 * jquery.ui.position.js
6143 */
6144(function( $, undefined ) {
6145
6146$.widget( "ui.autocomplete", {
6147 options: {
6148 appendTo: "body",
6149 delay: 300,
6150 minLength: 1,
6151 position: {
6152 my: "left top",
6153 at: "left bottom",
6154 collision: "none"
6155 },
6156 source: null
6157 },
6158 _create: function() {
6159 var self = this,
6160 doc = this.element[ 0 ].ownerDocument,
6161 suppressKeyPress;
6162
6163 this.element
6164 .addClass( "ui-autocomplete-input" )
6165 .attr( "autocomplete", "off" )
6166 // TODO verify these actually work as intended
6167 .attr({
6168 role: "textbox",
6169 "aria-autocomplete": "list",
6170 "aria-haspopup": "true"
6171 })
6172 .bind( "keydown.autocomplete", function( event ) {
6173 if ( self.options.disabled || self.element.attr( "readonly" ) ) {
6174 return;
6175 }
6176
6177 suppressKeyPress = false;
6178 var keyCode = $.ui.keyCode;
6179 switch( event.keyCode ) {
6180 case keyCode.PAGE_UP:
6181 self._move( "previousPage", event );
6182 break;
6183 case keyCode.PAGE_DOWN:
6184 self._move( "nextPage", event );
6185 break;
6186 case keyCode.UP:
6187 self._move( "previous", event );
6188 // prevent moving cursor to beginning of text field in some browsers
6189 event.preventDefault();
6190 break;
6191 case keyCode.DOWN:
6192 self._move( "next", event );
6193 // prevent moving cursor to end of text field in some browsers
6194 event.preventDefault();
6195 break;
6196 case keyCode.ENTER:
6197 case keyCode.NUMPAD_ENTER:
6198 // when menu is open and has focus
6199 if ( self.menu.active ) {
6200 // #6055 - Opera still allows the keypress to occur
6201 // which causes forms to submit
6202 suppressKeyPress = true;
6203 event.preventDefault();
6204 }
6205 //passthrough - ENTER and TAB both select the current element
6206 case keyCode.TAB:
6207 if ( !self.menu.active ) {
6208 return;
6209 }
6210 self.menu.select( event );
6211 break;
6212 case keyCode.ESCAPE:
6213 self.element.val( self.term );
6214 self.close( event );
6215 break;
6216 default:
6217 // keypress is triggered before the input value is changed
6218 clearTimeout( self.searching );
6219 self.searching = setTimeout(function() {
6220 // only search if the value has changed
6221 if ( self.term != self.element.val() ) {
6222 self.selectedItem = null;
6223 self.search( null, event );
6224 }
6225 }, self.options.delay );
6226 break;
6227 }
6228 })
6229 .bind( "keypress.autocomplete", function( event ) {
6230 if ( suppressKeyPress ) {
6231 suppressKeyPress = false;
6232 event.preventDefault();
6233 }
6234 })
6235 .bind( "focus.autocomplete", function() {
6236 if ( self.options.disabled ) {
6237 return;
6238 }
6239
6240 self.selectedItem = null;
6241 self.previous = self.element.val();
6242 })
6243 .bind( "blur.autocomplete", function( event ) {
6244 if ( self.options.disabled ) {
6245 return;
6246 }
6247
6248 clearTimeout( self.searching );
6249 // clicks on the menu (or a button to trigger a search) will cause a blur event
6250 self.closing = setTimeout(function() {
6251 self.close( event );
6252 self._change( event );
6253 }, 150 );
6254 });
6255 this._initSource();
6256 this.response = function() {
6257 return self._response.apply( self, arguments );
6258 };
6259 this.menu = $( "<ul></ul>" )
6260 .addClass( "ui-autocomplete" )
6261 .appendTo( $( this.options.appendTo || "body", doc )[0] )
6262 // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
6263 .mousedown(function( event ) {
6264 // clicking on the scrollbar causes focus to shift to the body
6265 // but we can't detect a mouseup or a click immediately afterward
6266 // so we have to track the next mousedown and close the menu if
6267 // the user clicks somewhere outside of the autocomplete
6268 var menuElement = self.menu.element[ 0 ];
6269 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
6270 setTimeout(function() {
6271 $( document ).one( 'mousedown', function( event ) {
6272 if ( event.target !== self.element[ 0 ] &&
6273 event.target !== menuElement &&
6274 !$.ui.contains( menuElement, event.target ) ) {
6275 self.close();
6276 }
6277 });
6278 }, 1 );
6279 }
6280
6281 // use another timeout to make sure the blur-event-handler on the input was already triggered
6282 setTimeout(function() {
6283 clearTimeout( self.closing );
6284 }, 13);
6285 })
6286 .menu({
6287 focus: function( event, ui ) {
6288 var item = ui.item.data( "item.autocomplete" );
6289 if ( false !== self._trigger( "focus", event, { item: item } ) ) {
6290 // use value to match what will end up in the input, if it was a key event
6291 if ( /^key/.test(event.originalEvent.type) ) {
6292 self.element.val( item.value );
6293 }
6294 }
6295 },
6296 selected: function( event, ui ) {
6297 var item = ui.item.data( "item.autocomplete" ),
6298 previous = self.previous;
6299
6300 // only trigger when focus was lost (click on menu)
6301 if ( self.element[0] !== doc.activeElement ) {
6302 self.element.focus();
6303 self.previous = previous;
6304 // #6109 - IE triggers two focus events and the second
6305 // is asynchronous, so we need to reset the previous
6306 // term synchronously and asynchronously :-(
6307 setTimeout(function() {
6308 self.previous = previous;
6309 self.selectedItem = item;
6310 }, 1);
6311 }
6312
6313 if ( false !== self._trigger( "select", event, { item: item } ) ) {
6314 self.element.val( item.value );
6315 }
6316 // reset the term after the select event
6317 // this allows custom select handling to work properly
6318 self.term = self.element.val();
6319
6320 self.close( event );
6321 self.selectedItem = item;
6322 },
6323 blur: function( event, ui ) {
6324 // don't set the value of the text field if it's already correct
6325 // this prevents moving the cursor unnecessarily
6326 if ( self.menu.element.is(":visible") &&
6327 ( self.element.val() !== self.term ) ) {
6328 self.element.val( self.term );
6329 }
6330 }
6331 })
6332 .zIndex( this.element.zIndex() + 1 )
6333 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
6334 .css({ top: 0, left: 0 })
6335 .hide()
6336 .data( "menu" );
6337 if ( $.fn.bgiframe ) {
6338 this.menu.element.bgiframe();
6339 }
6340 },
6341
6342 destroy: function() {
6343 this.element
6344 .removeClass( "ui-autocomplete-input" )
6345 .removeAttr( "autocomplete" )
6346 .removeAttr( "role" )
6347 .removeAttr( "aria-autocomplete" )
6348 .removeAttr( "aria-haspopup" );
6349 this.menu.element.remove();
6350 $.Widget.prototype.destroy.call( this );
6351 },
6352
6353 _setOption: function( key, value ) {
6354 $.Widget.prototype._setOption.apply( this, arguments );
6355 if ( key === "source" ) {
6356 this._initSource();
6357 }
6358 if ( key === "appendTo" ) {
6359 this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
6360 }
6361 },
6362
6363 _initSource: function() {
6364 var self = this,
6365 array,
6366 url;
6367 if ( $.isArray(this.options.source) ) {
6368 array = this.options.source;
6369 this.source = function( request, response ) {
6370 response( $.ui.autocomplete.filter(array, request.term) );
6371 };
6372 } else if ( typeof this.options.source === "string" ) {
6373 url = this.options.source;
6374 this.source = function( request, response ) {
6375 if (self.xhr) {
6376 self.xhr.abort();
6377 }
6378 self.xhr = $.ajax({
6379 url: url,
6380 data: request,
6381 dataType: "json",
6382 success: function( data, status, xhr ) {
6383 if ( xhr === self.xhr ) {
6384 response( data );
6385 }
6386 self.xhr = null;
6387 },
6388 error: function( xhr ) {
6389 if ( xhr === self.xhr ) {
6390 response( [] );
6391 }
6392 self.xhr = null;
6393 }
6394 });
6395 };
6396 } else {
6397 this.source = this.options.source;
6398 }
6399 },
6400
6401 search: function( value, event ) {
6402 value = value != null ? value : this.element.val();
6403
6404 // always save the actual value, not the one passed as an argument
6405 this.term = this.element.val();
6406
6407 if ( value.length < this.options.minLength ) {
6408 return this.close( event );
6409 }
6410
6411 clearTimeout( this.closing );
6412 if ( this._trigger( "search", event ) === false ) {
6413 return;
6414 }
6415
6416 return this._search( value );
6417 },
6418
6419 _search: function( value ) {
6420 this.element.addClass( "ui-autocomplete-loading" );
6421
6422 this.source( { term: value }, this.response );
6423 },
6424
6425 _response: function( content ) {
6426 if ( content && content.length ) {
6427 content = this._normalize( content );
6428 this._suggest( content );
6429 this._trigger( "open" );
6430 } else {
6431 this.close();
6432 }
6433 this.element.removeClass( "ui-autocomplete-loading" );
6434 },
6435
6436 close: function( event ) {
6437 clearTimeout( this.closing );
6438 if ( this.menu.element.is(":visible") ) {
6439 this.menu.element.hide();
6440 this.menu.deactivate();
6441 this._trigger( "close", event );
6442 }
6443 },
6444
6445 _change: function( event ) {
6446 if ( this.previous !== this.element.val() ) {
6447 this._trigger( "change", event, { item: this.selectedItem } );
6448 }
6449 },
6450
6451 _normalize: function( items ) {
6452 // assume all items have the right format when the first item is complete
6453 if ( items.length && items[0].label && items[0].value ) {
6454 return items;
6455 }
6456 return $.map( items, function(item) {
6457 if ( typeof item === "string" ) {
6458 return {
6459 label: item,
6460 value: item
6461 };
6462 }
6463 return $.extend({
6464 label: item.label || item.value,
6465 value: item.value || item.label
6466 }, item );
6467 });
6468 },
6469
6470 _suggest: function( items ) {
6471 var ul = this.menu.element
6472 .empty()
6473 .zIndex( this.element.zIndex() + 1 );
6474 this._renderMenu( ul, items );
6475 // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
6476 this.menu.deactivate();
6477 this.menu.refresh();
6478
6479 // size and position menu
6480 ul.show();
6481 this._resizeMenu();
6482 ul.position( $.extend({
6483 of: this.element
6484 }, this.options.position ));
6485 },
6486
6487 _resizeMenu: function() {
6488 var ul = this.menu.element;
6489 ul.outerWidth( Math.max(
6490 ul.width( "" ).outerWidth(),
6491 this.element.outerWidth()
6492 ) );
6493 },
6494
6495 _renderMenu: function( ul, items ) {
6496 var self = this;
6497 $.each( items, function( index, item ) {
6498 self._renderItem( ul, item );
6499 });
6500 },
6501
6502 _renderItem: function( ul, item) {
6503 return $( "<li></li>" )
6504 .data( "item.autocomplete", item )
6505 .append( $( "<a></a>" ).text( item.label ) )
6506 .appendTo( ul );
6507 },
6508
6509 _move: function( direction, event ) {
6510 if ( !this.menu.element.is(":visible") ) {
6511 this.search( null, event );
6512 return;
6513 }
6514 if ( this.menu.first() && /^previous/.test(direction) ||
6515 this.menu.last() && /^next/.test(direction) ) {
6516 this.element.val( this.term );
6517 this.menu.deactivate();
6518 return;
6519 }
6520 this.menu[ direction ]( event );
6521 },
6522
6523 widget: function() {
6524 return this.menu.element;
6525 }
6526});
6527
6528$.extend( $.ui.autocomplete, {
6529 escapeRegex: function( value ) {
6530 return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
6531 },
6532 filter: function(array, term) {
6533 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
6534 return $.grep( array, function(value) {
6535 return matcher.test( value.label || value.value || value );
6536 });
6537 }
6538});
6539
6540}( jQuery ));
6541
6542/*
6543 * jQuery UI Menu (not officially released)
6544 *
6545 * This widget isn't yet finished and the API is subject to change. We plan to finish
6546 * it for the next release. You're welcome to give it a try anyway and give us feedback,
6547 * as long as you're okay with migrating your code later on. We can help with that, too.
6548 *
6549 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
6550 * Dual licensed under the MIT or GPL Version 2 licenses.
6551 * http://jquery.org/license
6552 *
6553 * http://docs.jquery.com/UI/Menu
6554 *
6555 * Depends:
6556 * jquery.ui.core.js
6557 * jquery.ui.widget.js
6558 */
6559(function($) {
6560
6561$.widget("ui.menu", {
6562 _create: function() {
6563 var self = this;
6564 this.element
6565 .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
6566 .attr({
6567 role: "listbox",
6568 "aria-activedescendant": "ui-active-menuitem"
6569 })
6570 .click(function( event ) {
6571 if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
6572 return;
6573 }
6574 // temporary
6575 event.preventDefault();
6576 self.select( event );
6577 });
6578 this.refresh();
6579 },
6580
6581 refresh: function() {
6582 var self = this;
6583
6584 // don't refresh list items that are already adapted
6585 var items = this.element.children("li:not(.ui-menu-item):has(a)")
6586 .addClass("ui-menu-item")
6587 .attr("role", "menuitem");
6588
6589 items.children("a")
6590 .addClass("ui-corner-all")
6591 .attr("tabindex", -1)
6592 // mouseenter doesn't work with event delegation
6593 .mouseenter(function( event ) {
6594 self.activate( event, $(this).parent() );
6595 })
6596 .mouseleave(function() {
6597 self.deactivate();
6598 });
6599 },
6600
6601 activate: function( event, item ) {
6602 this.deactivate();
6603 if (this.hasScroll()) {
6604 var offset = item.offset().top - this.element.offset().top,
6605 scroll = this.element.attr("scrollTop"),
6606 elementHeight = this.element.height();
6607 if (offset < 0) {
6608 this.element.attr("scrollTop", scroll + offset);
6609 } else if (offset >= elementHeight) {
6610 this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
6611 }
6612 }
6613 this.active = item.eq(0)
6614 .children("a")
6615 .addClass("ui-state-hover")
6616 .attr("id", "ui-active-menuitem")
6617 .end();
6618 this._trigger("focus", event, { item: item });
6619 },
6620
6621 deactivate: function() {
6622 if (!this.active) { return; }
6623
6624 this.active.children("a")
6625 .removeClass("ui-state-hover")
6626 .removeAttr("id");
6627 this._trigger("blur");
6628 this.active = null;
6629 },
6630
6631 next: function(event) {
6632 this.move("next", ".ui-menu-item:first", event);
6633 },
6634
6635 previous: function(event) {
6636 this.move("prev", ".ui-menu-item:last", event);
6637 },
6638
6639 first: function() {
6640 return this.active && !this.active.prevAll(".ui-menu-item").length;
6641 },
6642
6643 last: function() {
6644 return this.active && !this.active.nextAll(".ui-menu-item").length;
6645 },
6646
6647 move: function(direction, edge, event) {
6648 if (!this.active) {
6649 this.activate(event, this.element.children(edge));
6650 return;
6651 }
6652 var next = this.active[direction + "All"](".ui-menu-item").eq(0);
6653 if (next.length) {
6654 this.activate(event, next);
6655 } else {
6656 this.activate(event, this.element.children(edge));
6657 }
6658 },
6659
6660 // TODO merge with previousPage
6661 nextPage: function(event) {
6662 if (this.hasScroll()) {
6663 // TODO merge with no-scroll-else
6664 if (!this.active || this.last()) {
6665 this.activate(event, this.element.children(".ui-menu-item:first"));
6666 return;
6667 }
6668 var base = this.active.offset().top,
6669 height = this.element.height(),
6670 result = this.element.children(".ui-menu-item").filter(function() {
6671 var close = $(this).offset().top - base - height + $(this).height();
6672 // TODO improve approximation
6673 return close < 10 && close > -10;
6674 });
6675
6676 // TODO try to catch this earlier when scrollTop indicates the last page anyway
6677 if (!result.length) {
6678 result = this.element.children(".ui-menu-item:last");
6679 }
6680 this.activate(event, result);
6681 } else {
6682 this.activate(event, this.element.children(".ui-menu-item")
6683 .filter(!this.active || this.last() ? ":first" : ":last"));
6684 }
6685 },
6686
6687 // TODO merge with nextPage
6688 previousPage: function(event) {
6689 if (this.hasScroll()) {
6690 // TODO merge with no-scroll-else
6691 if (!this.active || this.first()) {
6692 this.activate(event, this.element.children(".ui-menu-item:last"));
6693 return;
6694 }
6695
6696 var base = this.active.offset().top,
6697 height = this.element.height();
6698 result = this.element.children(".ui-menu-item").filter(function() {
6699 var close = $(this).offset().top - base + height - $(this).height();
6700 // TODO improve approximation
6701 return close < 10 && close > -10;
6702 });
6703
6704 // TODO try to catch this earlier when scrollTop indicates the last page anyway
6705 if (!result.length) {
6706 result = this.element.children(".ui-menu-item:first");
6707 }
6708 this.activate(event, result);
6709 } else {
6710 this.activate(event, this.element.children(".ui-menu-item")
6711 .filter(!this.active || this.first() ? ":last" : ":first"));
6712 }
6713 },
6714
6715 hasScroll: function() {
6716 return this.element.height() < this.element.attr("scrollHeight");
6717 },
6718
6719 select: function( event ) {
6720 this._trigger("selected", event, { item: this.active });
6721 }
6722});
6723
6724}(jQuery));
6725/*
6726 * jQuery UI Button 1.8.7
6727 *
6728 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
6729 * Dual licensed under the MIT or GPL Version 2 licenses.
6730 * http://jquery.org/license
6731 *
6732 * http://docs.jquery.com/UI/Button
6733 *
6734 * Depends:
6735 * jquery.ui.core.js
6736 * jquery.ui.widget.js
6737 */
6738(function( $, undefined ) {
6739
6740var lastActive,
6741 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
6742 stateClasses = "ui-state-hover ui-state-active ",
6743 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",
6744 formResetHandler = function( event ) {
6745 $( ":ui-button", event.target.form ).each(function() {
6746 var inst = $( this ).data( "button" );
6747 setTimeout(function() {
6748 inst.refresh();
6749 }, 1 );
6750 });
6751 },
6752 radioGroup = function( radio ) {
6753 var name = radio.name,
6754 form = radio.form,
6755 radios = $( [] );
6756 if ( name ) {
6757 if ( form ) {
6758 radios = $( form ).find( "[name='" + name + "']" );
6759 } else {
6760 radios = $( "[name='" + name + "']", radio.ownerDocument )
6761 .filter(function() {
6762 return !this.form;
6763 });
6764 }
6765 }
6766 return radios;
6767 };
6768
6769$.widget( "ui.button", {
6770 options: {
6771 disabled: null,
6772 text: true,
6773 label: null,
6774 icons: {
6775 primary: null,
6776 secondary: null
6777 }
6778 },
6779 _create: function() {
6780 this.element.closest( "form" )
6781 .unbind( "reset.button" )
6782 .bind( "reset.button", formResetHandler );
6783
6784 if ( typeof this.options.disabled !== "boolean" ) {
6785 this.options.disabled = this.element.attr( "disabled" );
6786 }
6787
6788 this._determineButtonType();
6789 this.hasTitle = !!this.buttonElement.attr( "title" );
6790
6791 var self = this,
6792 options = this.options,
6793 toggleButton = this.type === "checkbox" || this.type === "radio",
6794 hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
6795 focusClass = "ui-state-focus";
6796
6797 if ( options.label === null ) {
6798 options.label = this.buttonElement.html();
6799 }
6800
6801 if ( this.element.is( ":disabled" ) ) {
6802 options.disabled = true;
6803 }
6804
6805 this.buttonElement
6806 .addClass( baseClasses )
6807 .attr( "role", "button" )
6808 .bind( "mouseenter.button", function() {
6809 if ( options.disabled ) {
6810 return;
6811 }
6812 $( this ).addClass( "ui-state-hover" );
6813 if ( this === lastActive ) {
6814 $( this ).addClass( "ui-state-active" );
6815 }
6816 })
6817 .bind( "mouseleave.button", function() {
6818 if ( options.disabled ) {
6819 return;
6820 }
6821 $( this ).removeClass( hoverClass );
6822 })
6823 .bind( "focus.button", function() {
6824 // no need to check disabled, focus won't be triggered anyway
6825 $( this ).addClass( focusClass );
6826 })
6827 .bind( "blur.button", function() {
6828 $( this ).removeClass( focusClass );
6829 });
6830
6831 if ( toggleButton ) {
6832 this.element.bind( "change.button", function() {
6833 self.refresh();
6834 });
6835 }
6836
6837 if ( this.type === "checkbox" ) {
6838 this.buttonElement.bind( "click.button", function() {
6839 if ( options.disabled ) {
6840 return false;
6841 }
6842 $( this ).toggleClass( "ui-state-active" );
6843 self.buttonElement.attr( "aria-pressed", self.element[0].checked );
6844 });
6845 } else if ( this.type === "radio" ) {
6846 this.buttonElement.bind( "click.button", function() {
6847 if ( options.disabled ) {
6848 return false;
6849 }
6850 $( this ).addClass( "ui-state-active" );
6851 self.buttonElement.attr( "aria-pressed", true );
6852
6853 var radio = self.element[ 0 ];
6854 radioGroup( radio )
6855 .not( radio )
6856 .map(function() {
6857 return $( this ).button( "widget" )[ 0 ];
6858 })
6859 .removeClass( "ui-state-active" )
6860 .attr( "aria-pressed", false );
6861 });
6862 } else {
6863 this.buttonElement
6864 .bind( "mousedown.button", function() {
6865 if ( options.disabled ) {
6866 return false;
6867 }
6868 $( this ).addClass( "ui-state-active" );
6869 lastActive = this;
6870 $( document ).one( "mouseup", function() {
6871 lastActive = null;
6872 });
6873 })
6874 .bind( "mouseup.button", function() {
6875 if ( options.disabled ) {
6876 return false;
6877 }
6878 $( this ).removeClass( "ui-state-active" );
6879 })
6880 .bind( "keydown.button", function(event) {
6881 if ( options.disabled ) {
6882 return false;
6883 }
6884 if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
6885 $( this ).addClass( "ui-state-active" );
6886 }
6887 })
6888 .bind( "keyup.button", function() {
6889 $( this ).removeClass( "ui-state-active" );
6890 });
6891
6892 if ( this.buttonElement.is("a") ) {
6893 this.buttonElement.keyup(function(event) {
6894 if ( event.keyCode === $.ui.keyCode.SPACE ) {
6895 // TODO pass through original event correctly (just as 2nd argument doesn't work)
6896 $( this ).click();
6897 }
6898 });
6899 }
6900 }
6901
6902 // TODO: pull out $.Widget's handling for the disabled option into
6903 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
6904 // be overridden by individual plugins
6905 this._setOption( "disabled", options.disabled );
6906 },
6907
6908 _determineButtonType: function() {
6909
6910 if ( this.element.is(":checkbox") ) {
6911 this.type = "checkbox";
6912 } else {
6913 if ( this.element.is(":radio") ) {
6914 this.type = "radio";
6915 } else {
6916 if ( this.element.is("input") ) {
6917 this.type = "input";
6918 } else {
6919 this.type = "button";
6920 }
6921 }
6922 }
6923
6924 if ( this.type === "checkbox" || this.type === "radio" ) {
6925 // we don't search against the document in case the element
6926 // is disconnected from the DOM
6927 this.buttonElement = this.element.parents().last()
6928 .find( "label[for=" + this.element.attr("id") + "]" );
6929 this.element.addClass( "ui-helper-hidden-accessible" );
6930
6931 var checked = this.element.is( ":checked" );
6932 if ( checked ) {
6933 this.buttonElement.addClass( "ui-state-active" );
6934 }
6935 this.buttonElement.attr( "aria-pressed", checked );
6936 } else {
6937 this.buttonElement = this.element;
6938 }
6939 },
6940
6941 widget: function() {
6942 return this.buttonElement;
6943 },
6944
6945 destroy: function() {
6946 this.element
6947 .removeClass( "ui-helper-hidden-accessible" );
6948 this.buttonElement
6949 .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
6950 .removeAttr( "role" )
6951 .removeAttr( "aria-pressed" )
6952 .html( this.buttonElement.find(".ui-button-text").html() );
6953
6954 if ( !this.hasTitle ) {
6955 this.buttonElement.removeAttr( "title" );
6956 }
6957
6958 $.Widget.prototype.destroy.call( this );
6959 },
6960
6961 _setOption: function( key, value ) {
6962 $.Widget.prototype._setOption.apply( this, arguments );
6963 if ( key === "disabled" ) {
6964 if ( value ) {
6965 this.element.attr( "disabled", true );
6966 } else {
6967 this.element.removeAttr( "disabled" );
6968 }
6969 }
6970 this._resetButton();
6971 },
6972
6973 refresh: function() {
6974 var isDisabled = this.element.is( ":disabled" );
6975 if ( isDisabled !== this.options.disabled ) {
6976 this._setOption( "disabled", isDisabled );
6977 }
6978 if ( this.type === "radio" ) {
6979 radioGroup( this.element[0] ).each(function() {
6980 if ( $( this ).is( ":checked" ) ) {
6981 $( this ).button( "widget" )
6982 .addClass( "ui-state-active" )
6983 .attr( "aria-pressed", true );
6984 } else {
6985 $( this ).button( "widget" )
6986 .removeClass( "ui-state-active" )
6987 .attr( "aria-pressed", false );
6988 }
6989 });
6990 } else if ( this.type === "checkbox" ) {
6991 if ( this.element.is( ":checked" ) ) {
6992 this.buttonElement
6993 .addClass( "ui-state-active" )
6994 .attr( "aria-pressed", true );
6995 } else {
6996 this.buttonElement
6997 .removeClass( "ui-state-active" )
6998 .attr( "aria-pressed", false );
6999 }
7000 }
7001 },
7002
7003 _resetButton: function() {
7004 if ( this.type === "input" ) {
7005 if ( this.options.label ) {
7006 this.element.val( this.options.label );
7007 }
7008 return;
7009 }
7010 var buttonElement = this.buttonElement.removeClass( typeClasses ),
7011 buttonText = $( "<span></span>" )
7012 .addClass( "ui-button-text" )
7013 .html( this.options.label )
7014 .appendTo( buttonElement.empty() )
7015 .text(),
7016 icons = this.options.icons,
7017 multipleIcons = icons.primary && icons.secondary;
7018 if ( icons.primary || icons.secondary ) {
7019 buttonElement.addClass( "ui-button-text-icon" +
7020 ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
7021 if ( icons.primary ) {
7022 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
7023 }
7024 if ( icons.secondary ) {
7025 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
7026 }
7027 if ( !this.options.text ) {
7028 buttonElement
7029 .addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
7030 .removeClass( "ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary" );
7031 if ( !this.hasTitle ) {
7032 buttonElement.attr( "title", buttonText );
7033 }
7034 }
7035 } else {
7036 buttonElement.addClass( "ui-button-text-only" );
7037 }
7038 }
7039});
7040
7041$.widget( "ui.buttonset", {
7042 options: {
7043 items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
7044 },
7045
7046 _create: function() {
7047 this.element.addClass( "ui-buttonset" );
7048 },
7049
7050 _init: function() {
7051 this.refresh();
7052 },
7053
7054 _setOption: function( key, value ) {
7055 if ( key === "disabled" ) {
7056 this.buttons.button( "option", key, value );
7057 }
7058
7059 $.Widget.prototype._setOption.apply( this, arguments );
7060 },
7061
7062 refresh: function() {
7063 this.buttons = this.element.find( this.options.items )
7064 .filter( ":ui-button" )
7065 .button( "refresh" )
7066 .end()
7067 .not( ":ui-button" )
7068 .button()
7069 .end()
7070 .map(function() {
7071 return $( this ).button( "widget" )[ 0 ];
7072 })
7073 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
7074 .filter( ":first" )
7075 .addClass( "ui-corner-left" )
7076 .end()
7077 .filter( ":last" )
7078 .addClass( "ui-corner-right" )
7079 .end()
7080 .end();
7081 },
7082
7083 destroy: function() {
7084 this.element.removeClass( "ui-buttonset" );
7085 this.buttons
7086 .map(function() {
7087 return $( this ).button( "widget" )[ 0 ];
7088 })
7089 .removeClass( "ui-corner-left ui-corner-right" )
7090 .end()
7091 .button( "destroy" );
7092
7093 $.Widget.prototype.destroy.call( this );
7094 }
7095});
7096
7097}( jQuery ) );
7098/*
7099 * jQuery UI Datepicker 1.8.7
7100 *
7101 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
7102 * Dual licensed under the MIT or GPL Version 2 licenses.
7103 * http://jquery.org/license
7104 *
7105 * http://docs.jquery.com/UI/Datepicker
7106 *
7107 * Depends:
7108 * jquery.ui.core.js
7109 */
7110(function( $, undefined ) {
7111
7112$.extend($.ui, { datepicker: { version: "1.8.7" } });
7113
7114var PROP_NAME = 'datepicker';
7115var dpuuid = new Date().getTime();
7116
7117/* Date picker manager.
7118 Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7119 Settings for (groups of) date pickers are maintained in an instance object,
7120 allowing multiple different settings on the same page. */
7121
7122function Datepicker() {
7123 this.debug = false; // Change this to true to start debugging
7124 this._curInst = null; // The current instance in use
7125 this._keyEvent = false; // If the last event was a key event
7126 this._disabledInputs = []; // List of date picker inputs that have been disabled
7127 this._datepickerShowing = false; // True if the popup picker is showing , false if not
7128 this._inDialog = false; // True if showing within a "dialog", false if not
7129 this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
7130 this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
7131 this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
7132 this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
7133 this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
7134 this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
7135 this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
7136 this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
7137 this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
7138 this.regional = []; // Available regional settings, indexed by language code
7139 this.regional[''] = { // Default regional settings
7140 closeText: 'Done', // Display text for close link
7141 prevText: 'Prev', // Display text for previous month link
7142 nextText: 'Next', // Display text for next month link
7143 currentText: 'Today', // Display text for current month link
7144 monthNames: ['January','February','March','April','May','June',
7145 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
7146 monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
7147 dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
7148 dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
7149 dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
7150 weekHeader: 'Wk', // Column header for week of the year
7151 dateFormat: 'mm/dd/yy', // See format options on parseDate
7152 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7153 isRTL: false, // True if right-to-left language, false if left-to-right
7154 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7155 yearSuffix: '' // Additional text to append to the year in the month headers
7156 };
7157 this._defaults = { // Global defaults for all the date picker instances
7158 showOn: 'focus', // 'focus' for popup on focus,
7159 // 'button' for trigger button, or 'both' for either
7160 showAnim: 'fadeIn', // Name of jQuery animation for popup
7161 showOptions: {}, // Options for enhanced animations
7162 defaultDate: null, // Used when field is blank: actual date,
7163 // +/-number for offset from today, null for today
7164 appendText: '', // Display text following the input box, e.g. showing the format
7165 buttonText: '...', // Text for trigger button
7166 buttonImage: '', // URL for trigger button image
7167 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7168 hideIfNoPrevNext: false, // True to hide next/previous month links
7169 // if not applicable, false to just disable them
7170 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7171 gotoCurrent: false, // True if today link goes back to current selection instead
7172 changeMonth: false, // True if month can be selected directly, false if only prev/next
7173 changeYear: false, // True if year can be selected directly, false if only prev/next
7174 yearRange: 'c-10:c+10', // Range of years to display in drop-down,
7175 // either relative to today's year (-nn:+nn), relative to currently displayed year
7176 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7177 showOtherMonths: false, // True to show dates in other months, false to leave blank
7178 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7179 showWeek: false, // True to show week of the year, false to not show it
7180 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7181 // takes a Date and returns the number of the week for it
7182 shortYearCutoff: '+10', // Short year values < this are in the current century,
7183 // > this are in the previous century,
7184 // string value starting with '+' for current year + value
7185 minDate: null, // The earliest selectable date, or null for no limit
7186 maxDate: null, // The latest selectable date, or null for no limit
7187 duration: 'fast', // Duration of display/closure
7188 beforeShowDay: null, // Function that takes a date and returns an array with
7189 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
7190 // [2] = cell title (optional), e.g. $.datepicker.noWeekends
7191 beforeShow: null, // Function that takes an input field and
7192 // returns a set of custom settings for the date picker
7193 onSelect: null, // Define a callback function when a date is selected
7194 onChangeMonthYear: null, // Define a callback function when the month or year is changed
7195 onClose: null, // Define a callback function when the datepicker is closed
7196 numberOfMonths: 1, // Number of months to show at a time
7197 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7198 stepMonths: 1, // Number of months to step back/forward
7199 stepBigMonths: 12, // Number of months to step back/forward for the big links
7200 altField: '', // Selector for an alternate field to store selected dates into
7201 altFormat: '', // The date format to use for the alternate field
7202 constrainInput: true, // The input is constrained by the current date format
7203 showButtonPanel: false, // True to show button panel, false to not show it
7204 autoSize: false // True to size the input for the date format, false to leave as is
7205 };
7206 $.extend(this._defaults, this.regional['']);
7207 this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>');
7208}
7209
7210$.extend(Datepicker.prototype, {
7211 /* Class name added to elements to indicate already configured with a date picker. */
7212 markerClassName: 'hasDatepicker',
7213
7214 /* Debug logging (if enabled). */
7215 log: function () {
7216 if (this.debug)
7217 console.log.apply('', arguments);
7218 },
7219
7220 // TODO rename to "widget" when switching to widget factory
7221 _widgetDatepicker: function() {
7222 return this.dpDiv;
7223 },
7224
7225 /* Override the default settings for all instances of the date picker.
7226 @param settings object - the new settings to use as defaults (anonymous object)
7227 @return the manager object */
7228 setDefaults: function(settings) {
7229 extendRemove(this._defaults, settings || {});
7230 return this;
7231 },
7232
7233 /* Attach the date picker to a jQuery selection.
7234 @param target element - the target input field or division or span
7235 @param settings object - the new settings to use for this date picker instance (anonymous) */
7236 _attachDatepicker: function(target, settings) {
7237 // check for settings on the control itself - in namespace 'date:'
7238 var inlineSettings = null;
7239 for (var attrName in this._defaults) {
7240 var attrValue = target.getAttribute('date:' + attrName);
7241 if (attrValue) {
7242 inlineSettings = inlineSettings || {};
7243 try {
7244 inlineSettings[attrName] = eval(attrValue);
7245 } catch (err) {
7246 inlineSettings[attrName] = attrValue;
7247 }
7248 }
7249 }
7250 var nodeName = target.nodeName.toLowerCase();
7251 var inline = (nodeName == 'div' || nodeName == 'span');
7252 if (!target.id) {
7253 this.uuid += 1;
7254 target.id = 'dp' + this.uuid;
7255 }
7256 var inst = this._newInst($(target), inline);
7257 inst.settings = $.extend({}, settings || {}, inlineSettings || {});
7258 if (nodeName == 'input') {
7259 this._connectDatepicker(target, inst);
7260 } else if (inline) {
7261 this._inlineDatepicker(target, inst);
7262 }
7263 },
7264
7265 /* Create a new instance object. */
7266 _newInst: function(target, inline) {
7267 var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
7268 return {id: id, input: target, // associated target
7269 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7270 drawMonth: 0, drawYear: 0, // month being drawn
7271 inline: inline, // is datepicker inline or not
7272 dpDiv: (!inline ? this.dpDiv : // presentation div
7273 $('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
7274 },
7275
7276 /* Attach the date picker to an input field. */
7277 _connectDatepicker: function(target, inst) {
7278 var input = $(target);
7279 inst.append = $([]);
7280 inst.trigger = $([]);
7281 if (input.hasClass(this.markerClassName))
7282 return;
7283 this._attachments(input, inst);
7284 input.addClass(this.markerClassName).keydown(this._doKeyDown).
7285 keypress(this._doKeyPress).keyup(this._doKeyUp).
7286 bind("setData.datepicker", function(event, key, value) {
7287 inst.settings[key] = value;
7288 }).bind("getData.datepicker", function(event, key) {
7289 return this._get(inst, key);
7290 });
7291 this._autoSize(inst);
7292 $.data(target, PROP_NAME, inst);
7293 },
7294
7295 /* Make attachments based on settings. */
7296 _attachments: function(input, inst) {
7297 var appendText = this._get(inst, 'appendText');
7298 var isRTL = this._get(inst, 'isRTL');
7299 if (inst.append)
7300 inst.append.remove();
7301 if (appendText) {
7302 inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
7303 input[isRTL ? 'before' : 'after'](inst.append);
7304 }
7305 input.unbind('focus', this._showDatepicker);
7306 if (inst.trigger)
7307 inst.trigger.remove();
7308 var showOn = this._get(inst, 'showOn');
7309 if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
7310 input.focus(this._showDatepicker);
7311 if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
7312 var buttonText = this._get(inst, 'buttonText');
7313 var buttonImage = this._get(inst, 'buttonImage');
7314 inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
7315 $('<img/>').addClass(this._triggerClass).
7316 attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
7317 $('<button type="button"></button>').addClass(this._triggerClass).
7318 html(buttonImage == '' ? buttonText : $('<img/>').attr(
7319 { src:buttonImage, alt:buttonText, title:buttonText })));
7320 input[isRTL ? 'before' : 'after'](inst.trigger);
7321 inst.trigger.click(function() {
7322 if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
7323 $.datepicker._hideDatepicker();
7324 else
7325 $.datepicker._showDatepicker(input[0]);
7326 return false;
7327 });
7328 }
7329 },
7330
7331 /* Apply the maximum length for the date format. */
7332 _autoSize: function(inst) {
7333 if (this._get(inst, 'autoSize') && !inst.inline) {
7334 var date = new Date(2009, 12 - 1, 20); // Ensure double digits
7335 var dateFormat = this._get(inst, 'dateFormat');
7336 if (dateFormat.match(/[DM]/)) {
7337 var findMax = function(names) {
7338 var max = 0;
7339 var maxI = 0;
7340 for (var i = 0; i < names.length; i++) {
7341 if (names[i].length > max) {
7342 max = names[i].length;
7343 maxI = i;
7344 }
7345 }
7346 return maxI;
7347 };
7348 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
7349 'monthNames' : 'monthNamesShort'))));
7350 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
7351 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
7352 }
7353 inst.input.attr('size', this._formatDate(inst, date).length);
7354 }
7355 },
7356
7357 /* Attach an inline date picker to a div. */
7358 _inlineDatepicker: function(target, inst) {
7359 var divSpan = $(target);
7360 if (divSpan.hasClass(this.markerClassName))
7361 return;
7362 divSpan.addClass(this.markerClassName).append(inst.dpDiv).
7363 bind("setData.datepicker", function(event, key, value){
7364 inst.settings[key] = value;
7365 }).bind("getData.datepicker", function(event, key){
7366 return this._get(inst, key);
7367 });
7368 $.data(target, PROP_NAME, inst);
7369 this._setDate(inst, this._getDefaultDate(inst), true);
7370 this._updateDatepicker(inst);
7371 this._updateAlternate(inst);
7372 inst.dpDiv.show();
7373 },
7374
7375 /* Pop-up the date picker in a "dialog" box.
7376 @param input element - ignored
7377 @param date string or Date - the initial date to display
7378 @param onSelect function - the function to call when a date is selected
7379 @param settings object - update the dialog date picker instance's settings (anonymous object)
7380 @param pos int[2] - coordinates for the dialog's position within the screen or
7381 event - with x/y coordinates or
7382 leave empty for default (screen centre)
7383 @return the manager object */
7384 _dialogDatepicker: function(input, date, onSelect, settings, pos) {
7385 var inst = this._dialogInst; // internal instance
7386 if (!inst) {
7387 this.uuid += 1;
7388 var id = 'dp' + this.uuid;
7389 this._dialogInput = $('<input type="text" id="' + id +
7390 '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
7391 this._dialogInput.keydown(this._doKeyDown);
7392 $('body').append(this._dialogInput);
7393 inst = this._dialogInst = this._newInst(this._dialogInput, false);
7394 inst.settings = {};
7395 $.data(this._dialogInput[0], PROP_NAME, inst);
7396 }
7397 extendRemove(inst.settings, settings || {});
7398 date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
7399 this._dialogInput.val(date);
7400
7401 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
7402 if (!this._pos) {
7403 var browserWidth = document.documentElement.clientWidth;
7404 var browserHeight = document.documentElement.clientHeight;
7405 var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7406 var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7407 this._pos = // should use actual width/height below
7408 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
7409 }
7410
7411 // move input on screen for focus, but hidden behind dialog
7412 this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
7413 inst.settings.onSelect = onSelect;
7414 this._inDialog = true;
7415 this.dpDiv.addClass(this._dialogClass);
7416 this._showDatepicker(this._dialogInput[0]);
7417 if ($.blockUI)
7418 $.blockUI(this.dpDiv);
7419 $.data(this._dialogInput[0], PROP_NAME, inst);
7420 return this;
7421 },
7422
7423 /* Detach a datepicker from its control.
7424 @param target element - the target input field or division or span */
7425 _destroyDatepicker: function(target) {
7426 var $target = $(target);
7427 var inst = $.data(target, PROP_NAME);
7428 if (!$target.hasClass(this.markerClassName)) {
7429 return;
7430 }
7431 var nodeName = target.nodeName.toLowerCase();
7432 $.removeData(target, PROP_NAME);
7433 if (nodeName == 'input') {
7434 inst.append.remove();
7435 inst.trigger.remove();
7436 $target.removeClass(this.markerClassName).
7437 unbind('focus', this._showDatepicker).
7438 unbind('keydown', this._doKeyDown).
7439 unbind('keypress', this._doKeyPress).
7440 unbind('keyup', this._doKeyUp);
7441 } else if (nodeName == 'div' || nodeName == 'span')
7442 $target.removeClass(this.markerClassName).empty();
7443 },
7444
7445 /* Enable the date picker to a jQuery selection.
7446 @param target element - the target input field or division or span */
7447 _enableDatepicker: function(target) {
7448 var $target = $(target);
7449 var inst = $.data(target, PROP_NAME);
7450 if (!$target.hasClass(this.markerClassName)) {
7451 return;
7452 }
7453 var nodeName = target.nodeName.toLowerCase();
7454 if (nodeName == 'input') {
7455 target.disabled = false;
7456 inst.trigger.filter('button').
7457 each(function() { this.disabled = false; }).end().
7458 filter('img').css({opacity: '1.0', cursor: ''});
7459 }
7460 else if (nodeName == 'div' || nodeName == 'span') {
7461 var inline = $target.children('.' + this._inlineClass);
7462 inline.children().removeClass('ui-state-disabled');
7463 }
7464 this._disabledInputs = $.map(this._disabledInputs,
7465 function(value) { return (value == target ? null : value); }); // delete entry
7466 },
7467
7468 /* Disable the date picker to a jQuery selection.
7469 @param target element - the target input field or division or span */
7470 _disableDatepicker: function(target) {
7471 var $target = $(target);
7472 var inst = $.data(target, PROP_NAME);
7473 if (!$target.hasClass(this.markerClassName)) {
7474 return;
7475 }
7476 var nodeName = target.nodeName.toLowerCase();
7477 if (nodeName == 'input') {
7478 target.disabled = true;
7479 inst.trigger.filter('button').
7480 each(function() { this.disabled = true; }).end().
7481 filter('img').css({opacity: '0.5', cursor: 'default'});
7482 }
7483 else if (nodeName == 'div' || nodeName == 'span') {
7484 var inline = $target.children('.' + this._inlineClass);
7485 inline.children().addClass('ui-state-disabled');
7486 }
7487 this._disabledInputs = $.map(this._disabledInputs,
7488 function(value) { return (value == target ? null : value); }); // delete entry
7489 this._disabledInputs[this._disabledInputs.length] = target;
7490 },
7491
7492 /* Is the first field in a jQuery collection disabled as a datepicker?
7493 @param target element - the target input field or division or span
7494 @return boolean - true if disabled, false if enabled */
7495 _isDisabledDatepicker: function(target) {
7496 if (!target) {
7497 return false;
7498 }
7499 for (var i = 0; i < this._disabledInputs.length; i++) {
7500 if (this._disabledInputs[i] == target)
7501 return true;
7502 }
7503 return false;
7504 },
7505
7506 /* Retrieve the instance data for the target control.
7507 @param target element - the target input field or division or span
7508 @return object - the associated instance data
7509 @throws error if a jQuery problem getting data */
7510 _getInst: function(target) {
7511 try {
7512 return $.data(target, PROP_NAME);
7513 }
7514 catch (err) {
7515 throw 'Missing instance data for this datepicker';
7516 }
7517 },
7518
7519 /* Update or retrieve the settings for a date picker attached to an input field or division.
7520 @param target element - the target input field or division or span
7521 @param name object - the new settings to update or
7522 string - the name of the setting to change or retrieve,
7523 when retrieving also 'all' for all instance settings or
7524 'defaults' for all global defaults
7525 @param value any - the new value for the setting
7526 (omit if above is an object or to retrieve a value) */
7527 _optionDatepicker: function(target, name, value) {
7528 var inst = this._getInst(target);
7529 if (arguments.length == 2 && typeof name == 'string') {
7530 return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
7531 (inst ? (name == 'all' ? $.extend({}, inst.settings) :
7532 this._get(inst, name)) : null));
7533 }
7534 var settings = name || {};
7535 if (typeof name == 'string') {
7536 settings = {};
7537 settings[name] = value;
7538 }
7539 if (inst) {
7540 if (this._curInst == inst) {
7541 this._hideDatepicker();
7542 }
7543 var date = this._getDateDatepicker(target, true);
7544 extendRemove(inst.settings, settings);
7545 this._attachments($(target), inst);
7546 this._autoSize(inst);
7547 this._setDateDatepicker(target, date);
7548 this._updateDatepicker(inst);
7549 }
7550 },
7551
7552 // change method deprecated
7553 _changeDatepicker: function(target, name, value) {
7554 this._optionDatepicker(target, name, value);
7555 },
7556
7557 /* Redraw the date picker attached to an input field or division.
7558 @param target element - the target input field or division or span */
7559 _refreshDatepicker: function(target) {
7560 var inst = this._getInst(target);
7561 if (inst) {
7562 this._updateDatepicker(inst);
7563 }
7564 },
7565
7566 /* Set the dates for a jQuery selection.
7567 @param target element - the target input field or division or span
7568 @param date Date - the new date */
7569 _setDateDatepicker: function(target, date) {
7570 var inst = this._getInst(target);
7571 if (inst) {
7572 this._setDate(inst, date);
7573 this._updateDatepicker(inst);
7574 this._updateAlternate(inst);
7575 }
7576 },
7577
7578 /* Get the date(s) for the first entry in a jQuery selection.
7579 @param target element - the target input field or division or span
7580 @param noDefault boolean - true if no default date is to be used
7581 @return Date - the current date */
7582 _getDateDatepicker: function(target, noDefault) {
7583 var inst = this._getInst(target);
7584 if (inst && !inst.inline)
7585 this._setDateFromField(inst, noDefault);
7586 return (inst ? this._getDate(inst) : null);
7587 },
7588
7589 /* Handle keystrokes. */
7590 _doKeyDown: function(event) {
7591 var inst = $.datepicker._getInst(event.target);
7592 var handled = true;
7593 var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
7594 inst._keyEvent = true;
7595 if ($.datepicker._datepickerShowing)
7596 switch (event.keyCode) {
7597 case 9: $.datepicker._hideDatepicker();
7598 handled = false;
7599 break; // hide on tab out
7600 case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' +
7601 $.datepicker._currentClass + ')', inst.dpDiv);
7602 if (sel[0])
7603 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
7604 else
7605 $.datepicker._hideDatepicker();
7606 return false; // don't submit the form
7607 break; // select the value on enter
7608 case 27: $.datepicker._hideDatepicker();
7609 break; // hide on escape
7610 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7611 -$.datepicker._get(inst, 'stepBigMonths') :
7612 -$.datepicker._get(inst, 'stepMonths')), 'M');
7613 break; // previous month/year on page up/+ ctrl
7614 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7615 +$.datepicker._get(inst, 'stepBigMonths') :
7616 +$.datepicker._get(inst, 'stepMonths')), 'M');
7617 break; // next month/year on page down/+ ctrl
7618 case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
7619 handled = event.ctrlKey || event.metaKey;
7620 break; // clear on ctrl or command +end
7621 case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
7622 handled = event.ctrlKey || event.metaKey;
7623 break; // current on ctrl or command +home
7624 case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
7625 handled = event.ctrlKey || event.metaKey;
7626 // -1 day on ctrl or command +left
7627 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7628 -$.datepicker._get(inst, 'stepBigMonths') :
7629 -$.datepicker._get(inst, 'stepMonths')), 'M');
7630 // next month/year on alt +left on Mac
7631 break;
7632 case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
7633 handled = event.ctrlKey || event.metaKey;
7634 break; // -1 week on ctrl or command +up
7635 case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
7636 handled = event.ctrlKey || event.metaKey;
7637 // +1 day on ctrl or command +right
7638 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
7639 +$.datepicker._get(inst, 'stepBigMonths') :
7640 +$.datepicker._get(inst, 'stepMonths')), 'M');
7641 // next month/year on alt +right
7642 break;
7643 case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
7644 handled = event.ctrlKey || event.metaKey;
7645 break; // +1 week on ctrl or command +down
7646 default: handled = false;
7647 }
7648 else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
7649 $.datepicker._showDatepicker(this);
7650 else {
7651 handled = false;
7652 }
7653 if (handled) {
7654 event.preventDefault();
7655 event.stopPropagation();
7656 }
7657 },
7658
7659 /* Filter entered characters - based on date format. */
7660 _doKeyPress: function(event) {
7661 var inst = $.datepicker._getInst(event.target);
7662 if ($.datepicker._get(inst, 'constrainInput')) {
7663 var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
7664 var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
7665 return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
7666 }
7667 },
7668
7669 /* Synchronise manual entry and field/alternate field. */
7670 _doKeyUp: function(event) {
7671 var inst = $.datepicker._getInst(event.target);
7672 if (inst.input.val() != inst.lastVal) {
7673 try {
7674 var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
7675 (inst.input ? inst.input.val() : null),
7676 $.datepicker._getFormatConfig(inst));
7677 if (date) { // only if valid
7678 $.datepicker._setDateFromField(inst);
7679 $.datepicker._updateAlternate(inst);
7680 $.datepicker._updateDatepicker(inst);
7681 }
7682 }
7683 catch (event) {
7684 $.datepicker.log(event);
7685 }
7686 }
7687 return true;
7688 },
7689
7690 /* Pop-up the date picker for a given input field.
7691 @param input element - the input field attached to the date picker or
7692 event - if triggered by focus */
7693 _showDatepicker: function(input) {
7694 input = input.target || input;
7695 if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
7696 input = $('input', input.parentNode)[0];
7697 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
7698 return;
7699 var inst = $.datepicker._getInst(input);
7700 if ($.datepicker._curInst && $.datepicker._curInst != inst) {
7701 $.datepicker._curInst.dpDiv.stop(true, true);
7702 }
7703 var beforeShow = $.datepicker._get(inst, 'beforeShow');
7704 extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
7705 inst.lastVal = null;
7706 $.datepicker._lastInput = input;
7707 $.datepicker._setDateFromField(inst);
7708 if ($.datepicker._inDialog) // hide cursor
7709 input.value = '';
7710 if (!$.datepicker._pos) { // position below input
7711 $.datepicker._pos = $.datepicker._findPos(input);
7712 $.datepicker._pos[1] += input.offsetHeight; // add the height
7713 }
7714 var isFixed = false;
7715 $(input).parents().each(function() {
7716 isFixed |= $(this).css('position') == 'fixed';
7717 return !isFixed;
7718 });
7719 if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
7720 $.datepicker._pos[0] -= document.documentElement.scrollLeft;
7721 $.datepicker._pos[1] -= document.documentElement.scrollTop;
7722 }
7723 var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
7724 $.datepicker._pos = null;
7725 //to avoid flashes on Firefox
7726 inst.dpDiv.empty();
7727 // determine sizing offscreen
7728 inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
7729 $.datepicker._updateDatepicker(inst);
7730 // fix width for dynamic number of date pickers
7731 // and adjust position before showing
7732 offset = $.datepicker._checkOffset(inst, offset, isFixed);
7733 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
7734 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
7735 left: offset.left + 'px', top: offset.top + 'px'});
7736 if (!inst.inline) {
7737 var showAnim = $.datepicker._get(inst, 'showAnim');
7738 var duration = $.datepicker._get(inst, 'duration');
7739 var postProcess = function() {
7740 $.datepicker._datepickerShowing = true;
7741 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
7742 if( !! cover.length ){
7743 var borders = $.datepicker._getBorders(inst.dpDiv);
7744 cover.css({left: -borders[0], top: -borders[1],
7745 width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
7746 }
7747 };
7748 inst.dpDiv.zIndex($(input).zIndex()+1);
7749 if ($.effects && $.effects[showAnim])
7750 inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
7751 else
7752 inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
7753 if (!showAnim || !duration)
7754 postProcess();
7755 if (inst.input.is(':visible') && !inst.input.is(':disabled'))
7756 inst.input.focus();
7757 $.datepicker._curInst = inst;
7758 }
7759 },
7760
7761 /* Generate the date picker content. */
7762 _updateDatepicker: function(inst) {
7763 var self = this;
7764 var borders = $.datepicker._getBorders(inst.dpDiv);
7765 inst.dpDiv.empty().append(this._generateHTML(inst));
7766 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
7767 if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
7768 cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
7769 }
7770 inst.dpDiv.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
7771 .bind('mouseout', function(){
7772 $(this).removeClass('ui-state-hover');
7773 if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
7774 if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
7775 })
7776 .bind('mouseover', function(){
7777 if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
7778 $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
7779 $(this).addClass('ui-state-hover');
7780 if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
7781 if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
7782 }
7783 })
7784 .end()
7785 .find('.' + this._dayOverClass + ' a')
7786 .trigger('mouseover')
7787 .end();
7788 var numMonths = this._getNumberOfMonths(inst);
7789 var cols = numMonths[1];
7790 var width = 17;
7791 if (cols > 1)
7792 inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
7793 else
7794 inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
7795 inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
7796 'Class']('ui-datepicker-multi');
7797 inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
7798 'Class']('ui-datepicker-rtl');
7799 if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
7800 inst.input.is(':visible') && !inst.input.is(':disabled'))
7801 inst.input.focus();
7802 // deffered render of the years select (to avoid flashes on Firefox)
7803 if( inst.yearshtml ){
7804 var origyearshtml = inst.yearshtml;
7805 setTimeout(function(){
7806 //assure that inst.yearshtml didn't change.
7807 if( origyearshtml === inst.yearshtml ){
7808 inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
7809 }
7810 origyearshtml = inst.yearshtml = null;
7811 }, 0);
7812 }
7813 },
7814
7815 /* Retrieve the size of left and top borders for an element.
7816 @param elem (jQuery object) the element of interest
7817 @return (number[2]) the left and top borders */
7818 _getBorders: function(elem) {
7819 var convert = function(value) {
7820 return {thin: 1, medium: 2, thick: 3}[value] || value;
7821 };
7822 return [parseFloat(convert(elem.css('border-left-width'))),
7823 parseFloat(convert(elem.css('border-top-width')))];
7824 },
7825
7826 /* Check positioning to remain on screen. */
7827 _checkOffset: function(inst, offset, isFixed) {
7828 var dpWidth = inst.dpDiv.outerWidth();
7829 var dpHeight = inst.dpDiv.outerHeight();
7830 var inputWidth = inst.input ? inst.input.outerWidth() : 0;
7831 var inputHeight = inst.input ? inst.input.outerHeight() : 0;
7832 var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
7833 var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
7834
7835 offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
7836 offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
7837 offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
7838
7839 // now check if datepicker is showing outside window viewport - move to a better place if so.
7840 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
7841 Math.abs(offset.left + dpWidth - viewWidth) : 0);
7842 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
7843 Math.abs(dpHeight + inputHeight) : 0);
7844
7845 return offset;
7846 },
7847
7848 /* Find an object's position on the screen. */
7849 _findPos: function(obj) {
7850 var inst = this._getInst(obj);
7851 var isRTL = this._get(inst, 'isRTL');
7852 while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
7853 obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
7854 }
7855 var position = $(obj).offset();
7856 return [position.left, position.top];
7857 },
7858
7859 /* Hide the date picker from view.
7860 @param input element - the input field attached to the date picker */
7861 _hideDatepicker: function(input) {
7862 var inst = this._curInst;
7863 if (!inst || (input && inst != $.data(input, PROP_NAME)))
7864 return;
7865 if (this._datepickerShowing) {
7866 var showAnim = this._get(inst, 'showAnim');
7867 var duration = this._get(inst, 'duration');
7868 var postProcess = function() {
7869 $.datepicker._tidyDialog(inst);
7870 this._curInst = null;
7871 };
7872 if ($.effects && $.effects[showAnim])
7873 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
7874 else
7875 inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
7876 (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
7877 if (!showAnim)
7878 postProcess();
7879 var onClose = this._get(inst, 'onClose');
7880 if (onClose)
7881 onClose.apply((inst.input ? inst.input[0] : null),
7882 [(inst.input ? inst.input.val() : ''), inst]); // trigger custom callback
7883 this._datepickerShowing = false;
7884 this._lastInput = null;
7885 if (this._inDialog) {
7886 this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
7887 if ($.blockUI) {
7888 $.unblockUI();
7889 $('body').append(this.dpDiv);
7890 }
7891 }
7892 this._inDialog = false;
7893 }
7894 },
7895
7896 /* Tidy up after a dialog display. */
7897 _tidyDialog: function(inst) {
7898 inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
7899 },
7900
7901 /* Close date picker if clicked elsewhere. */
7902 _checkExternalClick: function(event) {
7903 if (!$.datepicker._curInst)
7904 return;
7905 var $target = $(event.target);
7906 if ($target[0].id != $.datepicker._mainDivId &&
7907 $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
7908 !$target.hasClass($.datepicker.markerClassName) &&
7909 !$target.hasClass($.datepicker._triggerClass) &&
7910 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
7911 $.datepicker._hideDatepicker();
7912 },
7913
7914 /* Adjust one of the date sub-fields. */
7915 _adjustDate: function(id, offset, period) {
7916 var target = $(id);
7917 var inst = this._getInst(target[0]);
7918 if (this._isDisabledDatepicker(target[0])) {
7919 return;
7920 }
7921 this._adjustInstDate(inst, offset +
7922 (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
7923 period);
7924 this._updateDatepicker(inst);
7925 },
7926
7927 /* Action for current link. */
7928 _gotoToday: function(id) {
7929 var target = $(id);
7930 var inst = this._getInst(target[0]);
7931 if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
7932 inst.selectedDay = inst.currentDay;
7933 inst.drawMonth = inst.selectedMonth = inst.currentMonth;
7934 inst.drawYear = inst.selectedYear = inst.currentYear;
7935 }
7936 else {
7937 var date = new Date();
7938 inst.selectedDay = date.getDate();
7939 inst.drawMonth = inst.selectedMonth = date.getMonth();
7940 inst.drawYear = inst.selectedYear = date.getFullYear();
7941 }
7942 this._notifyChange(inst);
7943 this._adjustDate(target);
7944 },
7945
7946 /* Action for selecting a new month/year. */
7947 _selectMonthYear: function(id, select, period) {
7948 var target = $(id);
7949 var inst = this._getInst(target[0]);
7950 inst._selectingMonthYear = false;
7951 inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
7952 inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
7953 parseInt(select.options[select.selectedIndex].value,10);
7954 this._notifyChange(inst);
7955 this._adjustDate(target);
7956 },
7957
7958 /* Restore input focus after not changing month/year. */
7959 _clickMonthYear: function(id) {
7960 var target = $(id);
7961 var inst = this._getInst(target[0]);
7962 if (inst.input && inst._selectingMonthYear) {
7963 setTimeout(function() {
7964 inst.input.focus();
7965 }, 0);
7966 }
7967 inst._selectingMonthYear = !inst._selectingMonthYear;
7968 },
7969
7970 /* Action for selecting a day. */
7971 _selectDay: function(id, month, year, td) {
7972 var target = $(id);
7973 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
7974 return;
7975 }
7976 var inst = this._getInst(target[0]);
7977 inst.selectedDay = inst.currentDay = $('a', td).html();
7978 inst.selectedMonth = inst.currentMonth = month;
7979 inst.selectedYear = inst.currentYear = year;
7980 this._selectDate(id, this._formatDate(inst,
7981 inst.currentDay, inst.currentMonth, inst.currentYear));
7982 },
7983
7984 /* Erase the input field and hide the date picker. */
7985 _clearDate: function(id) {
7986 var target = $(id);
7987 var inst = this._getInst(target[0]);
7988 this._selectDate(target, '');
7989 },
7990
7991 /* Update the input field with the selected date. */
7992 _selectDate: function(id, dateStr) {
7993 var target = $(id);
7994 var inst = this._getInst(target[0]);
7995 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
7996 if (inst.input)
7997 inst.input.val(dateStr);
7998 this._updateAlternate(inst);
7999 var onSelect = this._get(inst, 'onSelect');
8000 if (onSelect)
8001 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
8002 else if (inst.input)
8003 inst.input.trigger('change'); // fire the change event
8004 if (inst.inline)
8005 this._updateDatepicker(inst);
8006 else {
8007 this._hideDatepicker();
8008 this._lastInput = inst.input[0];
8009 if (typeof(inst.input[0]) != 'object')
8010 inst.input.focus(); // restore focus
8011 this._lastInput = null;
8012 }
8013 },
8014
8015 /* Update any alternate field to synchronise with the main field. */
8016 _updateAlternate: function(inst) {
8017 var altField = this._get(inst, 'altField');
8018 if (altField) { // update alternate field too
8019 var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
8020 var date = this._getDate(inst);
8021 var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
8022 $(altField).each(function() { $(this).val(dateStr); });
8023 }
8024 },
8025
8026 /* Set as beforeShowDay function to prevent selection of weekends.
8027 @param date Date - the date to customise
8028 @return [boolean, string] - is this date selectable?, what is its CSS class? */
8029 noWeekends: function(date) {
8030 var day = date.getDay();
8031 return [(day > 0 && day < 6), ''];
8032 },
8033
8034 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8035 @param date Date - the date to get the week for
8036 @return number - the number of the week within the year that contains this date */
8037 iso8601Week: function(date) {
8038 var checkDate = new Date(date.getTime());
8039 // Find Thursday of this week starting on Monday
8040 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
8041 var time = checkDate.getTime();
8042 checkDate.setMonth(0); // Compare with Jan 1
8043 checkDate.setDate(1);
8044 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
8045 },
8046
8047 /* Parse a string value into a date object.
8048 See formatDate below for the possible formats.
8049
8050 @param format string - the expected format of the date
8051 @param value string - the date in the above format
8052 @param settings Object - attributes include:
8053 shortYearCutoff number - the cutoff year for determining the century (optional)
8054 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8055 dayNames string[7] - names of the days from Sunday (optional)
8056 monthNamesShort string[12] - abbreviated names of the months (optional)
8057 monthNames string[12] - names of the months (optional)
8058 @return Date - the extracted date value or null if value is blank */
8059 parseDate: function (format, value, settings) {
8060 if (format == null || value == null)
8061 throw 'Invalid arguments';
8062 value = (typeof value == 'object' ? value.toString() : value + '');
8063 if (value == '')
8064 return null;
8065 var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
8066 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
8067 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
8068 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
8069 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
8070 var year = -1;
8071 var month = -1;
8072 var day = -1;
8073 var doy = -1;
8074 var literal = false;
8075 // Check whether a format character is doubled
8076 var lookAhead = function(match) {
8077 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
8078 if (matches)
8079 iFormat++;
8080 return matches;
8081 };
8082 // Extract a number from the string value
8083 var getNumber = function(match) {
8084 var isDoubled = lookAhead(match);
8085 var size = (match == '@' ? 14 : (match == '!' ? 20 :
8086 (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
8087 var digits = new RegExp('^\\d{1,' + size + '}');
8088 var num = value.substring(iValue).match(digits);
8089 if (!num)
8090 throw 'Missing number at position ' + iValue;
8091 iValue += num[0].length;
8092 return parseInt(num[0], 10);
8093 };
8094 // Extract a name from the string value and convert to an index
8095 var getName = function(match, shortNames, longNames) {
8096 var names = (lookAhead(match) ? longNames : shortNames);
8097 for (var i = 0; i < names.length; i++) {
8098 if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
8099 iValue += names[i].length;
8100 return i + 1;
8101 }
8102 }
8103 throw 'Unknown name at position ' + iValue;
8104 };
8105 // Confirm that a literal character matches the string value
8106 var checkLiteral = function() {
8107 if (value.charAt(iValue) != format.charAt(iFormat))
8108 throw 'Unexpected literal at position ' + iValue;
8109 iValue++;
8110 };
8111 var iValue = 0;
8112 for (var iFormat = 0; iFormat < format.length; iFormat++) {
8113 if (literal)
8114 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
8115 literal = false;
8116 else
8117 checkLiteral();
8118 else
8119 switch (format.charAt(iFormat)) {
8120 case 'd':
8121 day = getNumber('d');
8122 break;
8123 case 'D':
8124 getName('D', dayNamesShort, dayNames);
8125 break;
8126 case 'o':
8127 doy = getNumber('o');
8128 break;
8129 case 'm':
8130 month = getNumber('m');
8131 break;
8132 case 'M':
8133 month = getName('M', monthNamesShort, monthNames);
8134 break;
8135 case 'y':
8136 year = getNumber('y');
8137 break;
8138 case '@':
8139 var date = new Date(getNumber('@'));
8140 year = date.getFullYear();
8141 month = date.getMonth() + 1;
8142 day = date.getDate();
8143 break;
8144 case '!':
8145 var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
8146 year = date.getFullYear();
8147 month = date.getMonth() + 1;
8148 day = date.getDate();
8149 break;
8150 case "'":
8151 if (lookAhead("'"))
8152 checkLiteral();
8153 else
8154 literal = true;
8155 break;
8156 default:
8157 checkLiteral();
8158 }
8159 }
8160 if (year == -1)
8161 year = new Date().getFullYear();
8162 else if (year < 100)
8163 year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8164 (year <= shortYearCutoff ? 0 : -100);
8165 if (doy > -1) {
8166 month = 1;
8167 day = doy;
8168 do {
8169 var dim = this._getDaysInMonth(year, month - 1);
8170 if (day <= dim)
8171 break;
8172 month++;
8173 day -= dim;
8174 } while (true);
8175 }
8176 var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
8177 if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
8178 throw 'Invalid date'; // E.g. 31/02/*
8179 return date;
8180 },
8181
8182 /* Standard date formats. */
8183 ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
8184 COOKIE: 'D, dd M yy',
8185 ISO_8601: 'yy-mm-dd',
8186 RFC_822: 'D, d M y',
8187 RFC_850: 'DD, dd-M-y',
8188 RFC_1036: 'D, d M y',
8189 RFC_1123: 'D, d M yy',
8190 RFC_2822: 'D, d M yy',
8191 RSS: 'D, d M y', // RFC 822
8192 TICKS: '!',
8193 TIMESTAMP: '@',
8194 W3C: 'yy-mm-dd', // ISO 8601
8195
8196 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
8197 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
8198
8199 /* Format a date object into a string value.
8200 The format can be combinations of the following:
8201 d - day of month (no leading zero)
8202 dd - day of month (two digit)
8203 o - day of year (no leading zeros)
8204 oo - day of year (three digit)
8205 D - day name short
8206 DD - day name long
8207 m - month of year (no leading zero)
8208 mm - month of year (two digit)
8209 M - month name short
8210 MM - month name long
8211 y - year (two digit)
8212 yy - year (four digit)
8213 @ - Unix timestamp (ms since 01/01/1970)
8214 ! - Windows ticks (100ns since 01/01/0001)
8215 '...' - literal text
8216 '' - single quote
8217
8218 @param format string - the desired format of the date
8219 @param date Date - the date value to format
8220 @param settings Object - attributes include:
8221 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
8222 dayNames string[7] - names of the days from Sunday (optional)
8223 monthNamesShort string[12] - abbreviated names of the months (optional)
8224 monthNames string[12] - names of the months (optional)
8225 @return string - the date in the above format */
8226 formatDate: function (format, date, settings) {
8227 if (!date)
8228 return '';
8229 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
8230 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
8231 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
8232 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
8233 // Check whether a format character is doubled
8234 var lookAhead = function(match) {
8235 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
8236 if (matches)
8237 iFormat++;
8238 return matches;
8239 };
8240 // Format a number, with leading zero if necessary
8241 var formatNumber = function(match, value, len) {
8242 var num = '' + value;
8243 if (lookAhead(match))
8244 while (num.length < len)
8245 num = '0' + num;
8246 return num;
8247 };
8248 // Format a name, short or long as requested
8249 var formatName = function(match, value, shortNames, longNames) {
8250 return (lookAhead(match) ? longNames[value] : shortNames[value]);
8251 };
8252 var output = '';
8253 var literal = false;
8254 if (date)
8255 for (var iFormat = 0; iFormat < format.length; iFormat++) {
8256 if (literal)
8257 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
8258 literal = false;
8259 else
8260 output += format.charAt(iFormat);
8261 else
8262 switch (format.charAt(iFormat)) {
8263 case 'd':
8264 output += formatNumber('d', date.getDate(), 2);
8265 break;
8266 case 'D':
8267 output += formatName('D', date.getDay(), dayNamesShort, dayNames);
8268 break;
8269 case 'o':
8270 output += formatNumber('o',
8271 (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
8272 break;
8273 case 'm':
8274 output += formatNumber('m', date.getMonth() + 1, 2);
8275 break;
8276 case 'M':
8277 output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
8278 break;
8279 case 'y':
8280 output += (lookAhead('y') ? date.getFullYear() :
8281 (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
8282 break;
8283 case '@':
8284 output += date.getTime();
8285 break;
8286 case '!':
8287 output += date.getTime() * 10000 + this._ticksTo1970;
8288 break;
8289 case "'":
8290 if (lookAhead("'"))
8291 output += "'";
8292 else
8293 literal = true;
8294 break;
8295 default:
8296 output += format.charAt(iFormat);
8297 }
8298 }
8299 return output;
8300 },
8301
8302 /* Extract all possible characters from the date format. */
8303 _possibleChars: function (format) {
8304 var chars = '';
8305 var literal = false;
8306 // Check whether a format character is doubled
8307 var lookAhead = function(match) {
8308 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
8309 if (matches)
8310 iFormat++;
8311 return matches;
8312 };
8313 for (var iFormat = 0; iFormat < format.length; iFormat++)
8314 if (literal)
8315 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
8316 literal = false;
8317 else
8318 chars += format.charAt(iFormat);
8319 else
8320 switch (format.charAt(iFormat)) {
8321 case 'd': case 'm': case 'y': case '@':
8322 chars += '0123456789';
8323 break;
8324 case 'D': case 'M':
8325 return null; // Accept anything
8326 case "'":
8327 if (lookAhead("'"))
8328 chars += "'";
8329 else
8330 literal = true;
8331 break;
8332 default:
8333 chars += format.charAt(iFormat);
8334 }
8335 return chars;
8336 },
8337
8338 /* Get a setting value, defaulting if necessary. */
8339 _get: function(inst, name) {
8340 return inst.settings[name] !== undefined ?
8341 inst.settings[name] : this._defaults[name];
8342 },
8343
8344 /* Parse existing date and initialise date picker. */
8345 _setDateFromField: function(inst, noDefault) {
8346 if (inst.input.val() == inst.lastVal) {
8347 return;
8348 }
8349 var dateFormat = this._get(inst, 'dateFormat');
8350 var dates = inst.lastVal = inst.input ? inst.input.val() : null;
8351 var date, defaultDate;
8352 date = defaultDate = this._getDefaultDate(inst);
8353 var settings = this._getFormatConfig(inst);
8354 try {
8355 date = this.parseDate(dateFormat, dates, settings) || defaultDate;
8356 } catch (event) {
8357 this.log(event);
8358 dates = (noDefault ? '' : dates);
8359 }
8360 inst.selectedDay = date.getDate();
8361 inst.drawMonth = inst.selectedMonth = date.getMonth();
8362 inst.drawYear = inst.selectedYear = date.getFullYear();
8363 inst.currentDay = (dates ? date.getDate() : 0);
8364 inst.currentMonth = (dates ? date.getMonth() : 0);
8365 inst.currentYear = (dates ? date.getFullYear() : 0);
8366 this._adjustInstDate(inst);
8367 },
8368
8369 /* Retrieve the default date shown on opening. */
8370 _getDefaultDate: function(inst) {
8371 return this._restrictMinMax(inst,
8372 this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
8373 },
8374
8375 /* A date may be specified as an exact value or a relative one. */
8376 _determineDate: function(inst, date, defaultDate) {
8377 var offsetNumeric = function(offset) {
8378 var date = new Date();
8379 date.setDate(date.getDate() + offset);
8380 return date;
8381 };
8382 var offsetString = function(offset) {
8383 try {
8384 return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
8385 offset, $.datepicker._getFormatConfig(inst));
8386 }
8387 catch (e) {
8388 // Ignore
8389 }
8390 var date = (offset.toLowerCase().match(/^c/) ?
8391 $.datepicker._getDate(inst) : null) || new Date();
8392 var year = date.getFullYear();
8393 var month = date.getMonth();
8394 var day = date.getDate();
8395 var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
8396 var matches = pattern.exec(offset);
8397 while (matches) {
8398 switch (matches[2] || 'd') {
8399 case 'd' : case 'D' :
8400 day += parseInt(matches[1],10); break;
8401 case 'w' : case 'W' :
8402 day += parseInt(matches[1],10) * 7; break;
8403 case 'm' : case 'M' :
8404 month += parseInt(matches[1],10);
8405 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
8406 break;
8407 case 'y': case 'Y' :
8408 year += parseInt(matches[1],10);
8409 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
8410 break;
8411 }
8412 matches = pattern.exec(offset);
8413 }
8414 return new Date(year, month, day);
8415 };
8416 var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
8417 (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
8418 newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
8419 if (newDate) {
8420 newDate.setHours(0);
8421 newDate.setMinutes(0);
8422 newDate.setSeconds(0);
8423 newDate.setMilliseconds(0);
8424 }
8425 return this._daylightSavingAdjust(newDate);
8426 },
8427
8428 /* Handle switch to/from daylight saving.
8429 Hours may be non-zero on daylight saving cut-over:
8430 > 12 when midnight changeover, but then cannot generate
8431 midnight datetime, so jump to 1AM, otherwise reset.
8432 @param date (Date) the date to check
8433 @return (Date) the corrected date */
8434 _daylightSavingAdjust: function(date) {
8435 if (!date) return null;
8436 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
8437 return date;
8438 },
8439
8440 /* Set the date(s) directly. */
8441 _setDate: function(inst, date, noChange) {
8442 var clear = !date;
8443 var origMonth = inst.selectedMonth;
8444 var origYear = inst.selectedYear;
8445 var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
8446 inst.selectedDay = inst.currentDay = newDate.getDate();
8447 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
8448 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
8449 if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
8450 this._notifyChange(inst);
8451 this._adjustInstDate(inst);
8452 if (inst.input) {
8453 inst.input.val(clear ? '' : this._formatDate(inst));
8454 }
8455 },
8456
8457 /* Retrieve the date(s) directly. */
8458 _getDate: function(inst) {
8459 var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
8460 this._daylightSavingAdjust(new Date(
8461 inst.currentYear, inst.currentMonth, inst.currentDay)));
8462 return startDate;
8463 },
8464
8465 /* Generate the HTML for the current state of the date picker. */
8466 _generateHTML: function(inst) {
8467 var today = new Date();
8468 today = this._daylightSavingAdjust(
8469 new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
8470 var isRTL = this._get(inst, 'isRTL');
8471 var showButtonPanel = this._get(inst, 'showButtonPanel');
8472 var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
8473 var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
8474 var numMonths = this._getNumberOfMonths(inst);
8475 var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
8476 var stepMonths = this._get(inst, 'stepMonths');
8477 var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
8478 var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
8479 new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
8480 var minDate = this._getMinMaxDate(inst, 'min');
8481 var maxDate = this._getMinMaxDate(inst, 'max');
8482 var drawMonth = inst.drawMonth - showCurrentAtPos;
8483 var drawYear = inst.drawYear;
8484 if (drawMonth < 0) {
8485 drawMonth += 12;
8486 drawYear--;
8487 }
8488 if (maxDate) {
8489 var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
8490 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
8491 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
8492 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
8493 drawMonth--;
8494 if (drawMonth < 0) {
8495 drawMonth = 11;
8496 drawYear--;
8497 }
8498 }
8499 }
8500 inst.drawMonth = drawMonth;
8501 inst.drawYear = drawYear;
8502 var prevText = this._get(inst, 'prevText');
8503 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
8504 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
8505 this._getFormatConfig(inst)));
8506 var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
8507 '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
8508 '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
8509 ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
8510 (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>'));
8511 var nextText = this._get(inst, 'nextText');
8512 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
8513 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
8514 this._getFormatConfig(inst)));
8515 var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
8516 '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
8517 '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
8518 ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
8519 (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>'));
8520 var currentText = this._get(inst, 'currentText');
8521 var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
8522 currentText = (!navigationAsDateFormat ? currentText :
8523 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
8524 var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
8525 '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
8526 var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
8527 (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
8528 '.datepicker._gotoToday(\'#' + inst.id + '\');"' +
8529 '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
8530 var firstDay = parseInt(this._get(inst, 'firstDay'),10);
8531 firstDay = (isNaN(firstDay) ? 0 : firstDay);
8532 var showWeek = this._get(inst, 'showWeek');
8533 var dayNames = this._get(inst, 'dayNames');
8534 var dayNamesShort = this._get(inst, 'dayNamesShort');
8535 var dayNamesMin = this._get(inst, 'dayNamesMin');
8536 var monthNames = this._get(inst, 'monthNames');
8537 var monthNamesShort = this._get(inst, 'monthNamesShort');
8538 var beforeShowDay = this._get(inst, 'beforeShowDay');
8539 var showOtherMonths = this._get(inst, 'showOtherMonths');
8540 var selectOtherMonths = this._get(inst, 'selectOtherMonths');
8541 var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
8542 var defaultDate = this._getDefaultDate(inst);
8543 var html = '';
8544 for (var row = 0; row < numMonths[0]; row++) {
8545 var group = '';
8546 for (var col = 0; col < numMonths[1]; col++) {
8547 var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
8548 var cornerClass = ' ui-corner-all';
8549 var calender = '';
8550 if (isMultiMonth) {
8551 calender += '<div class="ui-datepicker-group';
8552 if (numMonths[1] > 1)
8553 switch (col) {
8554 case 0: calender += ' ui-datepicker-group-first';
8555 cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
8556 case numMonths[1]-1: calender += ' ui-datepicker-group-last';
8557 cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
8558 default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
8559 }
8560 calender += '">';
8561 }
8562 calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
8563 (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
8564 (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
8565 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
8566 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
8567 '</div><table class="ui-datepicker-calendar"><thead>' +
8568 '<tr>';
8569 var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
8570 for (var dow = 0; dow < 7; dow++) { // days of the week
8571 var day = (dow + firstDay) % 7;
8572 thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
8573 '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
8574 }
8575 calender += thead + '</tr></thead><tbody>';
8576 var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
8577 if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
8578 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
8579 var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
8580 var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
8581 var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
8582 for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
8583 calender += '<tr>';
8584 var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
8585 this._get(inst, 'calculateWeek')(printDate) + '</td>');
8586 for (var dow = 0; dow < 7; dow++) { // create date picker days
8587 var daySettings = (beforeShowDay ?
8588 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
8589 var otherMonth = (printDate.getMonth() != drawMonth);
8590 var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
8591 (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
8592 tbody += '<td class="' +
8593 ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
8594 (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
8595 ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
8596 (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
8597 // or defaultDate is current printedDate and defaultDate is selectedDate
8598 ' ' + this._dayOverClass : '') + // highlight selected day
8599 (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
8600 (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
8601 (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
8602 (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
8603 ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
8604 (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
8605 inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
8606 (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
8607 (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
8608 (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
8609 (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
8610 (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
8611 '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
8612 printDate.setDate(printDate.getDate() + 1);
8613 printDate = this._daylightSavingAdjust(printDate);
8614 }
8615 calender += tbody + '</tr>';
8616 }
8617 drawMonth++;
8618 if (drawMonth > 11) {
8619 drawMonth = 0;
8620 drawYear++;
8621 }
8622 calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
8623 ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
8624 group += calender;
8625 }
8626 html += group;
8627 }
8628 html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
8629 '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
8630 inst._keyEvent = false;
8631 return html;
8632 },
8633
8634 /* Generate the month and year header. */
8635 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
8636 secondary, monthNames, monthNamesShort) {
8637 var changeMonth = this._get(inst, 'changeMonth');
8638 var changeYear = this._get(inst, 'changeYear');
8639 var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
8640 var html = '<div class="ui-datepicker-title">';
8641 var monthHtml = '';
8642 // month selection
8643 if (secondary || !changeMonth)
8644 monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
8645 else {
8646 var inMinYear = (minDate && minDate.getFullYear() == drawYear);
8647 var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
8648 monthHtml += '<select class="ui-datepicker-month" ' +
8649 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
8650 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
8651 '>';
8652 for (var month = 0; month < 12; month++) {
8653 if ((!inMinYear || month >= minDate.getMonth()) &&
8654 (!inMaxYear || month <= maxDate.getMonth()))
8655 monthHtml += '<option value="' + month + '"' +
8656 (month == drawMonth ? ' selected="selected"' : '') +
8657 '>' + monthNamesShort[month] + '</option>';
8658 }
8659 monthHtml += '</select>';
8660 }
8661 if (!showMonthAfterYear)
8662 html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
8663 // year selection
8664 inst.yearshtml = '';
8665 if (secondary || !changeYear)
8666 html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
8667 else {
8668 // determine range of years to display
8669 var years = this._get(inst, 'yearRange').split(':');
8670 var thisYear = new Date().getFullYear();
8671 var determineYear = function(value) {
8672 var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
8673 (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
8674 parseInt(value, 10)));
8675 return (isNaN(year) ? thisYear : year);
8676 };
8677 var year = determineYear(years[0]);
8678 var endYear = Math.max(year, determineYear(years[1] || ''));
8679 year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
8680 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
8681 inst.yearshtml += '<select class="ui-datepicker-year" ' +
8682 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
8683 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
8684 '>';
8685 for (; year <= endYear; year++) {
8686 inst.yearshtml += '<option value="' + year + '"' +
8687 (year == drawYear ? ' selected="selected"' : '') +
8688 '>' + year + '</option>';
8689 }
8690 inst.yearshtml += '</select>';
8691 //when showing there is no need for later update
8692 if( ! $.browser.mozilla ){
8693 html += inst.yearshtml;
8694 inst.yearshtml = null;
8695 } else {
8696 // will be replaced later with inst.yearshtml
8697 html += '<select class="ui-datepicker-year"><option value="' + drawYear + '" selected="selected">' + drawYear + '</option></select>';
8698 }
8699 }
8700 html += this._get(inst, 'yearSuffix');
8701 if (showMonthAfterYear)
8702 html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
8703 html += '</div>'; // Close datepicker_header
8704 return html;
8705 },
8706
8707 /* Adjust one of the date sub-fields. */
8708 _adjustInstDate: function(inst, offset, period) {
8709 var year = inst.drawYear + (period == 'Y' ? offset : 0);
8710 var month = inst.drawMonth + (period == 'M' ? offset : 0);
8711 var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
8712 (period == 'D' ? offset : 0);
8713 var date = this._restrictMinMax(inst,
8714 this._daylightSavingAdjust(new Date(year, month, day)));
8715 inst.selectedDay = date.getDate();
8716 inst.drawMonth = inst.selectedMonth = date.getMonth();
8717 inst.drawYear = inst.selectedYear = date.getFullYear();
8718 if (period == 'M' || period == 'Y')
8719 this._notifyChange(inst);
8720 },
8721
8722 /* Ensure a date is within any min/max bounds. */
8723 _restrictMinMax: function(inst, date) {
8724 var minDate = this._getMinMaxDate(inst, 'min');
8725 var maxDate = this._getMinMaxDate(inst, 'max');
8726 var newDate = (minDate && date < minDate ? minDate : date);
8727 newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
8728 return newDate;
8729 },
8730
8731 /* Notify change of month/year. */
8732 _notifyChange: function(inst) {
8733 var onChange = this._get(inst, 'onChangeMonthYear');
8734 if (onChange)
8735 onChange.apply((inst.input ? inst.input[0] : null),
8736 [inst.selectedYear, inst.selectedMonth + 1, inst]);
8737 },
8738
8739 /* Determine the number of months to show. */
8740 _getNumberOfMonths: function(inst) {
8741 var numMonths = this._get(inst, 'numberOfMonths');
8742 return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
8743 },
8744
8745 /* Determine the current maximum date - ensure no time components are set. */
8746 _getMinMaxDate: function(inst, minMax) {
8747 return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
8748 },
8749
8750 /* Find the number of days in a given month. */
8751 _getDaysInMonth: function(year, month) {
8752 return 32 - new Date(year, month, 32).getDate();
8753 },
8754
8755 /* Find the day of the week of the first of a month. */
8756 _getFirstDayOfMonth: function(year, month) {
8757 return new Date(year, month, 1).getDay();
8758 },
8759
8760 /* Determines if we should allow a "next/prev" month display change. */
8761 _canAdjustMonth: function(inst, offset, curYear, curMonth) {
8762 var numMonths = this._getNumberOfMonths(inst);
8763 var date = this._daylightSavingAdjust(new Date(curYear,
8764 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
8765 if (offset < 0)
8766 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
8767 return this._isInRange(inst, date);
8768 },
8769
8770 /* Is the given date in the accepted range? */
8771 _isInRange: function(inst, date) {
8772 var minDate = this._getMinMaxDate(inst, 'min');
8773 var maxDate = this._getMinMaxDate(inst, 'max');
8774 return ((!minDate || date.getTime() >= minDate.getTime()) &&
8775 (!maxDate || date.getTime() <= maxDate.getTime()));
8776 },
8777
8778 /* Provide the configuration settings for formatting/parsing. */
8779 _getFormatConfig: function(inst) {
8780 var shortYearCutoff = this._get(inst, 'shortYearCutoff');
8781 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
8782 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
8783 return {shortYearCutoff: shortYearCutoff,
8784 dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
8785 monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
8786 },
8787
8788 /* Format the given date for display. */
8789 _formatDate: function(inst, day, month, year) {
8790 if (!day) {
8791 inst.currentDay = inst.selectedDay;
8792 inst.currentMonth = inst.selectedMonth;
8793 inst.currentYear = inst.selectedYear;
8794 }
8795 var date = (day ? (typeof day == 'object' ? day :
8796 this._daylightSavingAdjust(new Date(year, month, day))) :
8797 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
8798 return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
8799 }
8800});
8801
8802/* jQuery extend now ignores nulls! */
8803function extendRemove(target, props) {
8804 $.extend(target, props);
8805 for (var name in props)
8806 if (props[name] == null || props[name] == undefined)
8807 target[name] = props[name];
8808 return target;
8809};
8810
8811/* Determine whether an object is an array. */
8812function isArray(a) {
8813 return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
8814 (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
8815};
8816
8817/* Invoke the datepicker functionality.
8818 @param options string - a command, optionally followed by additional parameters or
8819 Object - settings for attaching new datepicker functionality
8820 @return jQuery object */
8821$.fn.datepicker = function(options){
8822
8823 /* Initialise the date picker. */
8824 if (!$.datepicker.initialized) {
8825 $(document).mousedown($.datepicker._checkExternalClick).
8826 find('body').append($.datepicker.dpDiv);
8827 $.datepicker.initialized = true;
8828 }
8829
8830 var otherArgs = Array.prototype.slice.call(arguments, 1);
8831 if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
8832 return $.datepicker['_' + options + 'Datepicker'].
8833 apply($.datepicker, [this[0]].concat(otherArgs));
8834 if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
8835 return $.datepicker['_' + options + 'Datepicker'].
8836 apply($.datepicker, [this[0]].concat(otherArgs));
8837 return this.each(function() {
8838 typeof options == 'string' ?
8839 $.datepicker['_' + options + 'Datepicker'].
8840 apply($.datepicker, [this].concat(otherArgs)) :
8841 $.datepicker._attachDatepicker(this, options);
8842 });
8843};
8844
8845$.datepicker = new Datepicker(); // singleton instance
8846$.datepicker.initialized = false;
8847$.datepicker.uuid = new Date().getTime();
8848$.datepicker.version = "1.8.7";
8849
8850// Workaround for #4055
8851// Add another global to avoid noConflict issues with inline event handlers
8852window['DP_jQuery_' + dpuuid] = $;
8853
8854})(jQuery);
8855/*
8856 * jQuery UI Dialog 1.8.7
8857 *
8858 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
8859 * Dual licensed under the MIT or GPL Version 2 licenses.
8860 * http://jquery.org/license
8861 *
8862 * http://docs.jquery.com/UI/Dialog
8863 *
8864 * Depends:
8865 * jquery.ui.core.js
8866 * jquery.ui.widget.js
8867 * jquery.ui.button.js
8868 * jquery.ui.draggable.js
8869 * jquery.ui.mouse.js
8870 * jquery.ui.position.js
8871 * jquery.ui.resizable.js
8872 */
8873(function( $, undefined ) {
8874
8875var uiDialogClasses =
8876 'ui-dialog ' +
8877 'ui-widget ' +
8878 'ui-widget-content ' +
8879 'ui-corner-all ',
8880 sizeRelatedOptions = {
8881 buttons: true,
8882 height: true,
8883 maxHeight: true,
8884 maxWidth: true,
8885 minHeight: true,
8886 minWidth: true,
8887 width: true
8888 },
8889 resizableRelatedOptions = {
8890 maxHeight: true,
8891 maxWidth: true,
8892 minHeight: true,
8893 minWidth: true
8894 };
8895
8896$.widget("ui.dialog", {
8897 options: {
8898 autoOpen: true,
8899 buttons: {},
8900 closeOnEscape: true,
8901 closeText: 'close',
8902 dialogClass: '',
8903 draggable: true,
8904 hide: null,
8905 height: 'auto',
8906 maxHeight: false,
8907 maxWidth: false,
8908 minHeight: 150,
8909 minWidth: 150,
8910 modal: false,
8911 position: {
8912 my: 'center',
8913 at: 'center',
8914 collision: 'fit',
8915 // ensure that the titlebar is never outside the document
8916 using: function(pos) {
8917 var topOffset = $(this).css(pos).offset().top;
8918 if (topOffset < 0) {
8919 $(this).css('top', pos.top - topOffset);
8920 }
8921 }
8922 },
8923 resizable: true,
8924 show: null,
8925 stack: true,
8926 title: '',
8927 width: 300,
8928 zIndex: 1000
8929 },
8930
8931 _create: function() {
8932 this.originalTitle = this.element.attr('title');
8933 // #5742 - .attr() might return a DOMElement
8934 if ( typeof this.originalTitle !== "string" ) {
8935 this.originalTitle = "";
8936 }
8937
8938 this.options.title = this.options.title || this.originalTitle;
8939 var self = this,
8940 options = self.options,
8941
8942 title = options.title || '&#160;',
8943 titleId = $.ui.dialog.getTitleId(self.element),
8944
8945 uiDialog = (self.uiDialog = $('<div></div>'))
8946 .appendTo(document.body)
8947 .hide()
8948 .addClass(uiDialogClasses + options.dialogClass)
8949 .css({
8950 zIndex: options.zIndex
8951 })
8952 // setting tabIndex makes the div focusable
8953 // setting outline to 0 prevents a border on focus in Mozilla
8954 .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
8955 if (options.closeOnEscape && event.keyCode &&
8956 event.keyCode === $.ui.keyCode.ESCAPE) {
8957
8958 self.close(event);
8959 event.preventDefault();
8960 }
8961 })
8962 .attr({
8963 role: 'dialog',
8964 'aria-labelledby': titleId
8965 })
8966 .mousedown(function(event) {
8967 self.moveToTop(false, event);
8968 }),
8969
8970 uiDialogContent = self.element
8971 .show()
8972 .removeAttr('title')
8973 .addClass(
8974 'ui-dialog-content ' +
8975 'ui-widget-content')
8976 .appendTo(uiDialog),
8977
8978 uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
8979 .addClass(
8980 'ui-dialog-titlebar ' +
8981 'ui-widget-header ' +
8982 'ui-corner-all ' +
8983 'ui-helper-clearfix'
8984 )
8985 .prependTo(uiDialog),
8986
8987 uiDialogTitlebarClose = $('<a href="#"></a>')
8988 .addClass(
8989 'ui-dialog-titlebar-close ' +
8990 'ui-corner-all'
8991 )
8992 .attr('role', 'button')
8993 .hover(
8994 function() {
8995 uiDialogTitlebarClose.addClass('ui-state-hover');
8996 },
8997 function() {
8998 uiDialogTitlebarClose.removeClass('ui-state-hover');
8999 }
9000 )
9001 .focus(function() {
9002 uiDialogTitlebarClose.addClass('ui-state-focus');
9003 })
9004 .blur(function() {
9005 uiDialogTitlebarClose.removeClass('ui-state-focus');
9006 })
9007 .click(function(event) {
9008 self.close(event);
9009 return false;
9010 })
9011 .appendTo(uiDialogTitlebar),
9012
9013 uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
9014 .addClass(
9015 'ui-icon ' +
9016 'ui-icon-closethick'
9017 )
9018 .text(options.closeText)
9019 .appendTo(uiDialogTitlebarClose),
9020
9021 uiDialogTitle = $('<span></span>')
9022 .addClass('ui-dialog-title')
9023 .attr('id', titleId)
9024 .html(title)
9025 .prependTo(uiDialogTitlebar);
9026
9027 //handling of deprecated beforeclose (vs beforeClose) option
9028 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
9029 //TODO: remove in 1.9pre
9030 if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
9031 options.beforeClose = options.beforeclose;
9032 }
9033
9034 uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
9035
9036 if (options.draggable && $.fn.draggable) {
9037 self._makeDraggable();
9038 }
9039 if (options.resizable && $.fn.resizable) {
9040 self._makeResizable();
9041 }
9042
9043 self._createButtons(options.buttons);
9044 self._isOpen = false;
9045
9046 if ($.fn.bgiframe) {
9047 uiDialog.bgiframe();
9048 }
9049 },
9050
9051 _init: function() {
9052 if ( this.options.autoOpen ) {
9053 this.open();
9054 }
9055 },
9056
9057 destroy: function() {
9058 var self = this;
9059
9060 if (self.overlay) {
9061 self.overlay.destroy();
9062 }
9063 self.uiDialog.hide();
9064 self.element
9065 .unbind('.dialog')
9066 .removeData('dialog')
9067 .removeClass('ui-dialog-content ui-widget-content')
9068 .hide().appendTo('body');
9069 self.uiDialog.remove();
9070
9071 if (self.originalTitle) {
9072 self.element.attr('title', self.originalTitle);
9073 }
9074
9075 return self;
9076 },
9077
9078 widget: function() {
9079 return this.uiDialog;
9080 },
9081
9082 close: function(event) {
9083 var self = this,
9084 maxZ, thisZ;
9085
9086 if (false === self._trigger('beforeClose', event)) {
9087 return;
9088 }
9089
9090 if (self.overlay) {
9091 self.overlay.destroy();
9092 }
9093 self.uiDialog.unbind('keypress.ui-dialog');
9094
9095 self._isOpen = false;
9096
9097 if (self.options.hide) {
9098 self.uiDialog.hide(self.options.hide, function() {
9099 self._trigger('close', event);
9100 });
9101 } else {
9102 self.uiDialog.hide();
9103 self._trigger('close', event);
9104 }
9105
9106 $.ui.dialog.overlay.resize();
9107
9108 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
9109 if (self.options.modal) {
9110 maxZ = 0;
9111 $('.ui-dialog').each(function() {
9112 if (this !== self.uiDialog[0]) {
9113 thisZ = $(this).css('z-index');
9114 if(!isNaN(thisZ)) {
9115 maxZ = Math.max(maxZ, thisZ);
9116 }
9117 }
9118 });
9119 $.ui.dialog.maxZ = maxZ;
9120 }
9121
9122 return self;
9123 },
9124
9125 isOpen: function() {
9126 return this._isOpen;
9127 },
9128
9129 // the force parameter allows us to move modal dialogs to their correct
9130 // position on open
9131 moveToTop: function(force, event) {
9132 var self = this,
9133 options = self.options,
9134 saveScroll;
9135
9136 if ((options.modal && !force) ||
9137 (!options.stack && !options.modal)) {
9138 return self._trigger('focus', event);
9139 }
9140
9141 if (options.zIndex > $.ui.dialog.maxZ) {
9142 $.ui.dialog.maxZ = options.zIndex;
9143 }
9144 if (self.overlay) {
9145 $.ui.dialog.maxZ += 1;
9146 self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
9147 }
9148
9149 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
9150 // http://ui.jquery.com/bugs/ticket/3193
9151 saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
9152 $.ui.dialog.maxZ += 1;
9153 self.uiDialog.css('z-index', $.ui.dialog.maxZ);
9154 self.element.attr(saveScroll);
9155 self._trigger('focus', event);
9156
9157 return self;
9158 },
9159
9160 open: function() {
9161 if (this._isOpen) { return; }
9162
9163 var self = this,
9164 options = self.options,
9165 uiDialog = self.uiDialog;
9166
9167 self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
9168 self._size();
9169 self._position(options.position);
9170 uiDialog.show(options.show);
9171 self.moveToTop(true);
9172
9173 // prevent tabbing out of modal dialogs
9174 if (options.modal) {
9175 uiDialog.bind('keypress.ui-dialog', function(event) {
9176 if (event.keyCode !== $.ui.keyCode.TAB) {
9177 return;
9178 }
9179
9180 var tabbables = $(':tabbable', this),
9181 first = tabbables.filter(':first'),
9182 last = tabbables.filter(':last');
9183
9184 if (event.target === last[0] && !event.shiftKey) {
9185 first.focus(1);
9186 return false;
9187 } else if (event.target === first[0] && event.shiftKey) {
9188 last.focus(1);
9189 return false;
9190 }
9191 });
9192 }
9193
9194 // set focus to the first tabbable element in the content area or the first button
9195 // if there are no tabbable elements, set focus on the dialog itself
9196 $(self.element.find(':tabbable').get().concat(
9197 uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
9198 uiDialog.get()))).eq(0).focus();
9199
9200 self._isOpen = true;
9201 self._trigger('open');
9202
9203 return self;
9204 },
9205
9206 _createButtons: function(buttons) {
9207 var self = this,
9208 hasButtons = false,
9209 uiDialogButtonPane = $('<div></div>')
9210 .addClass(
9211 'ui-dialog-buttonpane ' +
9212 'ui-widget-content ' +
9213 'ui-helper-clearfix'
9214 ),
9215 uiButtonSet = $( "<div></div>" )
9216 .addClass( "ui-dialog-buttonset" )
9217 .appendTo( uiDialogButtonPane );
9218
9219 // if we already have a button pane, remove it
9220 self.uiDialog.find('.ui-dialog-buttonpane').remove();
9221
9222 if (typeof buttons === 'object' && buttons !== null) {
9223 $.each(buttons, function() {
9224 return !(hasButtons = true);
9225 });
9226 }
9227 if (hasButtons) {
9228 $.each(buttons, function(name, props) {
9229 props = $.isFunction( props ) ?
9230 { click: props, text: name } :
9231 props;
9232 var button = $('<button type="button"></button>')
9233 .attr( props, true )
9234 .unbind('click')
9235 .click(function() {
9236 props.click.apply(self.element[0], arguments);
9237 })
9238 .appendTo(uiButtonSet);
9239 if ($.fn.button) {
9240 button.button();
9241 }
9242 });
9243 uiDialogButtonPane.appendTo(self.uiDialog);
9244 }
9245 },
9246
9247 _makeDraggable: function() {
9248 var self = this,
9249 options = self.options,
9250 doc = $(document),
9251 heightBeforeDrag;
9252
9253 function filteredUi(ui) {
9254 return {
9255 position: ui.position,
9256 offset: ui.offset
9257 };
9258 }
9259
9260 self.uiDialog.draggable({
9261 cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
9262 handle: '.ui-dialog-titlebar',
9263 containment: 'document',
9264 start: function(event, ui) {
9265 heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
9266 $(this).height($(this).height()).addClass("ui-dialog-dragging");
9267 self._trigger('dragStart', event, filteredUi(ui));
9268 },
9269 drag: function(event, ui) {
9270 self._trigger('drag', event, filteredUi(ui));
9271 },
9272 stop: function(event, ui) {
9273 options.position = [ui.position.left - doc.scrollLeft(),
9274 ui.position.top - doc.scrollTop()];
9275 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
9276 self._trigger('dragStop', event, filteredUi(ui));
9277 $.ui.dialog.overlay.resize();
9278 }
9279 });
9280 },
9281
9282 _makeResizable: function(handles) {
9283 handles = (handles === undefined ? this.options.resizable : handles);
9284 var self = this,
9285 options = self.options,
9286 // .ui-resizable has position: relative defined in the stylesheet
9287 // but dialogs have to use absolute or fixed positioning
9288 position = self.uiDialog.css('position'),
9289 resizeHandles = (typeof handles === 'string' ?
9290 handles :
9291 'n,e,s,w,se,sw,ne,nw'
9292 );
9293
9294 function filteredUi(ui) {
9295 return {
9296 originalPosition: ui.originalPosition,
9297 originalSize: ui.originalSize,
9298 position: ui.position,
9299 size: ui.size
9300 };
9301 }
9302
9303 self.uiDialog.resizable({
9304 cancel: '.ui-dialog-content',
9305 containment: 'document',
9306 alsoResize: self.element,
9307 maxWidth: options.maxWidth,
9308 maxHeight: options.maxHeight,
9309 minWidth: options.minWidth,
9310 minHeight: self._minHeight(),
9311 handles: resizeHandles,
9312 start: function(event, ui) {
9313 $(this).addClass("ui-dialog-resizing");
9314 self._trigger('resizeStart', event, filteredUi(ui));
9315 },
9316 resize: function(event, ui) {
9317 self._trigger('resize', event, filteredUi(ui));
9318 },
9319 stop: function(event, ui) {
9320 $(this).removeClass("ui-dialog-resizing");
9321 options.height = $(this).height();
9322 options.width = $(this).width();
9323 self._trigger('resizeStop', event, filteredUi(ui));
9324 $.ui.dialog.overlay.resize();
9325 }
9326 })
9327 .css('position', position)
9328 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
9329 },
9330
9331 _minHeight: function() {
9332 var options = this.options;
9333
9334 if (options.height === 'auto') {
9335 return options.minHeight;
9336 } else {
9337 return Math.min(options.minHeight, options.height);
9338 }
9339 },
9340
9341 _position: function(position) {
9342 var myAt = [],
9343 offset = [0, 0],
9344 isVisible;
9345
9346 if (position) {
9347 // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
9348 // if (typeof position == 'string' || $.isArray(position)) {
9349 // myAt = $.isArray(position) ? position : position.split(' ');
9350
9351 if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
9352 myAt = position.split ? position.split(' ') : [position[0], position[1]];
9353 if (myAt.length === 1) {
9354 myAt[1] = myAt[0];
9355 }
9356
9357 $.each(['left', 'top'], function(i, offsetPosition) {
9358 if (+myAt[i] === myAt[i]) {
9359 offset[i] = myAt[i];
9360 myAt[i] = offsetPosition;
9361 }
9362 });
9363
9364 position = {
9365 my: myAt.join(" "),
9366 at: myAt.join(" "),
9367 offset: offset.join(" ")
9368 };
9369 }
9370
9371 position = $.extend({}, $.ui.dialog.prototype.options.position, position);
9372 } else {
9373 position = $.ui.dialog.prototype.options.position;
9374 }
9375
9376 // need to show the dialog to get the actual offset in the position plugin
9377 isVisible = this.uiDialog.is(':visible');
9378 if (!isVisible) {
9379 this.uiDialog.show();
9380 }
9381 this.uiDialog
9382 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
9383 .css({ top: 0, left: 0 })
9384 .position($.extend({ of: window }, position));
9385 if (!isVisible) {
9386 this.uiDialog.hide();
9387 }
9388 },
9389
9390 _setOptions: function( options ) {
9391 var self = this,
9392 resizableOptions = {},
9393 resize = false;
9394
9395 $.each( options, function( key, value ) {
9396 self._setOption( key, value );
9397
9398 if ( key in sizeRelatedOptions ) {
9399 resize = true;
9400 }
9401 if ( key in resizableRelatedOptions ) {
9402 resizableOptions[ key ] = value;
9403 }
9404 });
9405
9406 if ( resize ) {
9407 this._size();
9408 }
9409 if ( this.uiDialog.is( ":data(resizable)" ) ) {
9410 this.uiDialog.resizable( "option", resizableOptions );
9411 }
9412 },
9413
9414 _setOption: function(key, value){
9415 var self = this,
9416 uiDialog = self.uiDialog;
9417
9418 switch (key) {
9419 //handling of deprecated beforeclose (vs beforeClose) option
9420 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
9421 //TODO: remove in 1.9pre
9422 case "beforeclose":
9423 key = "beforeClose";
9424 break;
9425 case "buttons":
9426 self._createButtons(value);
9427 break;
9428 case "closeText":
9429 // ensure that we always pass a string
9430 self.uiDialogTitlebarCloseText.text("" + value);
9431 break;
9432 case "dialogClass":
9433 uiDialog
9434 .removeClass(self.options.dialogClass)
9435 .addClass(uiDialogClasses + value);
9436 break;
9437 case "disabled":
9438 if (value) {
9439 uiDialog.addClass('ui-dialog-disabled');
9440 } else {
9441 uiDialog.removeClass('ui-dialog-disabled');
9442 }
9443 break;
9444 case "draggable":
9445 var isDraggable = uiDialog.is( ":data(draggable)" );
9446 if ( isDraggable && !value ) {
9447 uiDialog.draggable( "destroy" );
9448 }
9449
9450 if ( !isDraggable && value ) {
9451 self._makeDraggable();
9452 }
9453 break;
9454 case "position":
9455 self._position(value);
9456 break;
9457 case "resizable":
9458 // currently resizable, becoming non-resizable
9459 var isResizable = uiDialog.is( ":data(resizable)" );
9460 if (isResizable && !value) {
9461 uiDialog.resizable('destroy');
9462 }
9463
9464 // currently resizable, changing handles
9465 if (isResizable && typeof value === 'string') {
9466 uiDialog.resizable('option', 'handles', value);
9467 }
9468
9469 // currently non-resizable, becoming resizable
9470 if (!isResizable && value !== false) {
9471 self._makeResizable(value);
9472 }
9473 break;
9474 case "title":
9475 // convert whatever was passed in o a string, for html() to not throw up
9476 $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
9477 break;
9478 }
9479
9480 $.Widget.prototype._setOption.apply(self, arguments);
9481 },
9482
9483 _size: function() {
9484 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
9485 * divs will both have width and height set, so we need to reset them
9486 */
9487 var options = this.options,
9488 nonContentHeight,
9489 minContentHeight,
9490 isVisible = this.uiDialog.is( ":visible" );
9491
9492 // reset content sizing
9493 this.element.show().css({
9494 width: 'auto',
9495 minHeight: 0,
9496 height: 0
9497 });
9498
9499 if (options.minWidth > options.width) {
9500 options.width = options.minWidth;
9501 }
9502
9503 // reset wrapper sizing
9504 // determine the height of all the non-content elements
9505 nonContentHeight = this.uiDialog.css({
9506 height: 'auto',
9507 width: options.width
9508 })
9509 .height();
9510 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
9511
9512 if ( options.height === "auto" ) {
9513 // only needed for IE6 support
9514 if ( $.support.minHeight ) {
9515 this.element.css({
9516 minHeight: minContentHeight,
9517 height: "auto"
9518 });
9519 } else {
9520 this.uiDialog.show();
9521 var autoHeight = this.element.css( "height", "auto" ).height();
9522 if ( !isVisible ) {
9523 this.uiDialog.hide();
9524 }
9525 this.element.height( Math.max( autoHeight, minContentHeight ) );
9526 }
9527 } else {
9528 this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
9529 }
9530
9531 if (this.uiDialog.is(':data(resizable)')) {
9532 this.uiDialog.resizable('option', 'minHeight', this._minHeight());
9533 }
9534 }
9535});
9536
9537$.extend($.ui.dialog, {
9538 version: "1.8.7",
9539
9540 uuid: 0,
9541 maxZ: 0,
9542
9543 getTitleId: function($el) {
9544 var id = $el.attr('id');
9545 if (!id) {
9546 this.uuid += 1;
9547 id = this.uuid;
9548 }
9549 return 'ui-dialog-title-' + id;
9550 },
9551
9552 overlay: function(dialog) {
9553 this.$el = $.ui.dialog.overlay.create(dialog);
9554 }
9555});
9556
9557$.extend($.ui.dialog.overlay, {
9558 instances: [],
9559 // reuse old instances due to IE memory leak with alpha transparency (see #5185)
9560 oldInstances: [],
9561 maxZ: 0,
9562 events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
9563 function(event) { return event + '.dialog-overlay'; }).join(' '),
9564 create: function(dialog) {
9565 if (this.instances.length === 0) {
9566 // prevent use of anchors and inputs
9567 // we use a setTimeout in case the overlay is created from an
9568 // event that we're going to be cancelling (see #2804)
9569 setTimeout(function() {
9570 // handle $(el).dialog().dialog('close') (see #4065)
9571 if ($.ui.dialog.overlay.instances.length) {
9572 $(document).bind($.ui.dialog.overlay.events, function(event) {
9573 // stop events if the z-index of the target is < the z-index of the overlay
9574 // we cannot return true when we don't want to cancel the event (#3523)
9575 if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
9576 return false;
9577 }
9578 });
9579 }
9580 }, 1);
9581
9582 // allow closing by pressing the escape key
9583 $(document).bind('keydown.dialog-overlay', function(event) {
9584 if (dialog.options.closeOnEscape && event.keyCode &&
9585 event.keyCode === $.ui.keyCode.ESCAPE) {
9586
9587 dialog.close(event);
9588 event.preventDefault();
9589 }
9590 });
9591
9592 // handle window resize
9593 $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
9594 }
9595
9596 var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
9597 .appendTo(document.body)
9598 .css({
9599 width: this.width(),
9600 height: this.height()
9601 });
9602
9603 if ($.fn.bgiframe) {
9604 $el.bgiframe();
9605 }
9606
9607 this.instances.push($el);
9608 return $el;
9609 },
9610
9611 destroy: function($el) {
9612 var indexOf = $.inArray($el, this.instances);
9613 if (indexOf != -1){
9614 this.oldInstances.push(this.instances.splice(indexOf, 1)[0]);
9615 }
9616
9617 if (this.instances.length === 0) {
9618 $([document, window]).unbind('.dialog-overlay');
9619 }
9620
9621 $el.remove();
9622
9623 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
9624 var maxZ = 0;
9625 $.each(this.instances, function() {
9626 maxZ = Math.max(maxZ, this.css('z-index'));
9627 });
9628 this.maxZ = maxZ;
9629 },
9630
9631 height: function() {
9632 var scrollHeight,
9633 offsetHeight;
9634 // handle IE 6
9635 if ($.browser.msie && $.browser.version < 7) {
9636 scrollHeight = Math.max(
9637 document.documentElement.scrollHeight,
9638 document.body.scrollHeight
9639 );
9640 offsetHeight = Math.max(
9641 document.documentElement.offsetHeight,
9642 document.body.offsetHeight
9643 );
9644
9645 if (scrollHeight < offsetHeight) {
9646 return $(window).height() + 'px';
9647 } else {
9648 return scrollHeight + 'px';
9649 }
9650 // handle "good" browsers
9651 } else {
9652 return $(document).height() + 'px';
9653 }
9654 },
9655
9656 width: function() {
9657 var scrollWidth,
9658 offsetWidth;
9659 // handle IE 6
9660 if ($.browser.msie && $.browser.version < 7) {
9661 scrollWidth = Math.max(
9662 document.documentElement.scrollWidth,
9663 document.body.scrollWidth
9664 );
9665 offsetWidth = Math.max(
9666 document.documentElement.offsetWidth,
9667 document.body.offsetWidth
9668 );
9669
9670 if (scrollWidth < offsetWidth) {
9671 return $(window).width() + 'px';
9672 } else {
9673 return scrollWidth + 'px';
9674 }
9675 // handle "good" browsers
9676 } else {
9677 return $(document).width() + 'px';
9678 }
9679 },
9680
9681 resize: function() {
9682 /* If the dialog is draggable and the user drags it past the
9683 * right edge of the window, the document becomes wider so we
9684 * need to stretch the overlay. If the user then drags the
9685 * dialog back to the left, the document will become narrower,
9686 * so we need to shrink the overlay to the appropriate size.
9687 * This is handled by shrinking the overlay before setting it
9688 * to the full document size.
9689 */
9690 var $overlays = $([]);
9691 $.each($.ui.dialog.overlay.instances, function() {
9692 $overlays = $overlays.add(this);
9693 });
9694
9695 $overlays.css({
9696 width: 0,
9697 height: 0
9698 }).css({
9699 width: $.ui.dialog.overlay.width(),
9700 height: $.ui.dialog.overlay.height()
9701 });
9702 }
9703});
9704
9705$.extend($.ui.dialog.overlay.prototype, {
9706 destroy: function() {
9707 $.ui.dialog.overlay.destroy(this.$el);
9708 }
9709});
9710
9711}(jQuery));
9712/*
9713 * jQuery UI Position 1.8.7
9714 *
9715 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
9716 * Dual licensed under the MIT or GPL Version 2 licenses.
9717 * http://jquery.org/license
9718 *
9719 * http://docs.jquery.com/UI/Position
9720 */
9721(function( $, undefined ) {
9722
9723$.ui = $.ui || {};
9724
9725var horizontalPositions = /left|center|right/,
9726 verticalPositions = /top|center|bottom/,
9727 center = "center",
9728 _position = $.fn.position,
9729 _offset = $.fn.offset;
9730
9731$.fn.position = function( options ) {
9732 if ( !options || !options.of ) {
9733 return _position.apply( this, arguments );
9734 }
9735
9736 // make a copy, we don't want to modify arguments
9737 options = $.extend( {}, options );
9738
9739 var target = $( options.of ),
9740 targetElem = target[0],
9741 collision = ( options.collision || "flip" ).split( " " ),
9742 offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
9743 targetWidth,
9744 targetHeight,
9745 basePosition;
9746
9747 if ( targetElem.nodeType === 9 ) {
9748 targetWidth = target.width();
9749 targetHeight = target.height();
9750 basePosition = { top: 0, left: 0 };
9751 // TODO: use $.isWindow() in 1.9
9752 } else if ( targetElem.setTimeout ) {
9753 targetWidth = target.width();
9754 targetHeight = target.height();
9755 basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
9756 } else if ( targetElem.preventDefault ) {
9757 // force left top to allow flipping
9758 options.at = "left top";
9759 targetWidth = targetHeight = 0;
9760 basePosition = { top: options.of.pageY, left: options.of.pageX };
9761 } else {
9762 targetWidth = target.outerWidth();
9763 targetHeight = target.outerHeight();
9764 basePosition = target.offset();
9765 }
9766
9767 // force my and at to have valid horizontal and veritcal positions
9768 // if a value is missing or invalid, it will be converted to center
9769 $.each( [ "my", "at" ], function() {
9770 var pos = ( options[this] || "" ).split( " " );
9771 if ( pos.length === 1) {
9772 pos = horizontalPositions.test( pos[0] ) ?
9773 pos.concat( [center] ) :
9774 verticalPositions.test( pos[0] ) ?
9775 [ center ].concat( pos ) :
9776 [ center, center ];
9777 }
9778 pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
9779 pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
9780 options[ this ] = pos;
9781 });
9782
9783 // normalize collision option
9784 if ( collision.length === 1 ) {
9785 collision[ 1 ] = collision[ 0 ];
9786 }
9787
9788 // normalize offset option
9789 offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
9790 if ( offset.length === 1 ) {
9791 offset[ 1 ] = offset[ 0 ];
9792 }
9793 offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
9794
9795 if ( options.at[0] === "right" ) {
9796 basePosition.left += targetWidth;
9797 } else if (options.at[0] === center ) {
9798 basePosition.left += targetWidth / 2;
9799 }
9800
9801 if ( options.at[1] === "bottom" ) {
9802 basePosition.top += targetHeight;
9803 } else if ( options.at[1] === center ) {
9804 basePosition.top += targetHeight / 2;
9805 }
9806
9807 basePosition.left += offset[ 0 ];
9808 basePosition.top += offset[ 1 ];
9809
9810 return this.each(function() {
9811 var elem = $( this ),
9812 elemWidth = elem.outerWidth(),
9813 elemHeight = elem.outerHeight(),
9814 marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
9815 marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
9816 collisionWidth = elemWidth + marginLeft +
9817 parseInt( $.curCSS( this, "marginRight", true ) ) || 0,
9818 collisionHeight = elemHeight + marginTop +
9819 parseInt( $.curCSS( this, "marginBottom", true ) ) || 0,
9820 position = $.extend( {}, basePosition ),
9821 collisionPosition;
9822
9823 if ( options.my[0] === "right" ) {
9824 position.left -= elemWidth;
9825 } else if ( options.my[0] === center ) {
9826 position.left -= elemWidth / 2;
9827 }
9828
9829 if ( options.my[1] === "bottom" ) {
9830 position.top -= elemHeight;
9831 } else if ( options.my[1] === center ) {
9832 position.top -= elemHeight / 2;
9833 }
9834
9835 // prevent fractions (see #5280)
9836 position.left = Math.round( position.left );
9837 position.top = Math.round( position.top );
9838
9839 collisionPosition = {
9840 left: position.left - marginLeft,
9841 top: position.top - marginTop
9842 };
9843
9844 $.each( [ "left", "top" ], function( i, dir ) {
9845 if ( $.ui.position[ collision[i] ] ) {
9846 $.ui.position[ collision[i] ][ dir ]( position, {
9847 targetWidth: targetWidth,
9848 targetHeight: targetHeight,
9849 elemWidth: elemWidth,
9850 elemHeight: elemHeight,
9851 collisionPosition: collisionPosition,
9852 collisionWidth: collisionWidth,
9853 collisionHeight: collisionHeight,
9854 offset: offset,
9855 my: options.my,
9856 at: options.at
9857 });
9858 }
9859 });
9860
9861 if ( $.fn.bgiframe ) {
9862 elem.bgiframe();
9863 }
9864 elem.offset( $.extend( position, { using: options.using } ) );
9865 });
9866};
9867
9868$.ui.position = {
9869 fit: {
9870 left: function( position, data ) {
9871 var win = $( window ),
9872 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
9873 position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
9874 },
9875 top: function( position, data ) {
9876 var win = $( window ),
9877 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
9878 position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
9879 }
9880 },
9881
9882 flip: {
9883 left: function( position, data ) {
9884 if ( data.at[0] === center ) {
9885 return;
9886 }
9887 var win = $( window ),
9888 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
9889 myOffset = data.my[ 0 ] === "left" ?
9890 -data.elemWidth :
9891 data.my[ 0 ] === "right" ?
9892 data.elemWidth :
9893 0,
9894 atOffset = data.at[ 0 ] === "left" ?
9895 data.targetWidth :
9896 -data.targetWidth,
9897 offset = -2 * data.offset[ 0 ];
9898 position.left += data.collisionPosition.left < 0 ?
9899 myOffset + atOffset + offset :
9900 over > 0 ?
9901 myOffset + atOffset + offset :
9902 0;
9903 },
9904 top: function( position, data ) {
9905 if ( data.at[1] === center ) {
9906 return;
9907 }
9908 var win = $( window ),
9909 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
9910 myOffset = data.my[ 1 ] === "top" ?
9911 -data.elemHeight :
9912 data.my[ 1 ] === "bottom" ?
9913 data.elemHeight :
9914 0,
9915 atOffset = data.at[ 1 ] === "top" ?
9916 data.targetHeight :
9917 -data.targetHeight,
9918 offset = -2 * data.offset[ 1 ];
9919 position.top += data.collisionPosition.top < 0 ?
9920 myOffset + atOffset + offset :
9921 over > 0 ?
9922 myOffset + atOffset + offset :
9923 0;
9924 }
9925 }
9926};
9927
9928// offset setter from jQuery 1.4
9929if ( !$.offset.setOffset ) {
9930 $.offset.setOffset = function( elem, options ) {
9931 // set position first, in-case top/left are set even on static elem
9932 if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
9933 elem.style.position = "relative";
9934 }
9935 var curElem = $( elem ),
9936 curOffset = curElem.offset(),
9937 curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0,
9938 curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0,
9939 props = {
9940 top: (options.top - curOffset.top) + curTop,
9941 left: (options.left - curOffset.left) + curLeft
9942 };
9943
9944 if ( 'using' in options ) {
9945 options.using.call( elem, props );
9946 } else {
9947 curElem.css( props );
9948 }
9949 };
9950
9951 $.fn.offset = function( options ) {
9952 var elem = this[ 0 ];
9953 if ( !elem || !elem.ownerDocument ) { return null; }
9954 if ( options ) {
9955 return this.each(function() {
9956 $.offset.setOffset( this, options );
9957 });
9958 }
9959 return _offset.call( this );
9960 };
9961}
9962
9963}( jQuery ));
9964/*
9965 * jQuery UI Progressbar 1.8.7
9966 *
9967 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
9968 * Dual licensed under the MIT or GPL Version 2 licenses.
9969 * http://jquery.org/license
9970 *
9971 * http://docs.jquery.com/UI/Progressbar
9972 *
9973 * Depends:
9974 * jquery.ui.core.js
9975 * jquery.ui.widget.js
9976 */
9977(function( $, undefined ) {
9978
9979$.widget( "ui.progressbar", {
9980 options: {
9981 value: 0,
9982 max: 100
9983 },
9984
9985 min: 0,
9986
9987 _create: function() {
9988 this.element
9989 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
9990 .attr({
9991 role: "progressbar",
9992 "aria-valuemin": this.min,
9993 "aria-valuemax": this.options.max,
9994 "aria-valuenow": this._value()
9995 });
9996
9997 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
9998 .appendTo( this.element );
9999
10000 this.oldValue = this._value();
10001 this._refreshValue();
10002 },
10003
10004 destroy: function() {
10005 this.element
10006 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
10007 .removeAttr( "role" )
10008 .removeAttr( "aria-valuemin" )
10009 .removeAttr( "aria-valuemax" )
10010 .removeAttr( "aria-valuenow" );
10011
10012 this.valueDiv.remove();
10013
10014 $.Widget.prototype.destroy.apply( this, arguments );
10015 },
10016
10017 value: function( newValue ) {
10018 if ( newValue === undefined ) {
10019 return this._value();
10020 }
10021
10022 this._setOption( "value", newValue );
10023 return this;
10024 },
10025
10026 _setOption: function( key, value ) {
10027 if ( key === "value" ) {
10028 this.options.value = value;
10029 this._refreshValue();
10030 if ( this._value() === this.options.max ) {
10031 this._trigger( "complete" );
10032 }
10033 }
10034
10035 $.Widget.prototype._setOption.apply( this, arguments );
10036 },
10037
10038 _value: function() {
10039 var val = this.options.value;
10040 // normalize invalid value
10041 if ( typeof val !== "number" ) {
10042 val = 0;
10043 }
10044 return Math.min( this.options.max, Math.max( this.min, val ) );
10045 },
10046
10047 _percentage: function() {
10048 return 100 * this._value() / this.options.max;
10049 },
10050
10051 _refreshValue: function() {
10052 var value = this.value();
10053 var percentage = this._percentage();
10054
10055 if ( this.oldValue !== value ) {
10056 this.oldValue = value;
10057 this._trigger( "change" );
10058 }
10059
10060 this.valueDiv
10061 .toggleClass( "ui-corner-right", value === this.options.max )
10062 .width( percentage.toFixed(0) + "%" );
10063 this.element.attr( "aria-valuenow", value );
10064 }
10065});
10066
10067$.extend( $.ui.progressbar, {
10068 version: "1.8.7"
10069});
10070
10071})( jQuery );
10072/*
10073 * jQuery UI Slider 1.8.7
10074 *
10075 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
10076 * Dual licensed under the MIT or GPL Version 2 licenses.
10077 * http://jquery.org/license
10078 *
10079 * http://docs.jquery.com/UI/Slider
10080 *
10081 * Depends:
10082 * jquery.ui.core.js
10083 * jquery.ui.mouse.js
10084 * jquery.ui.widget.js
10085 */
10086(function( $, undefined ) {
10087
10088// number of pages in a slider
10089// (how many times can you page up/down to go through the whole range)
10090var numPages = 5;
10091
10092$.widget( "ui.slider", $.ui.mouse, {
10093
10094 widgetEventPrefix: "slide",
10095
10096 options: {
10097 animate: false,
10098 distance: 0,
10099 max: 100,
10100 min: 0,
10101 orientation: "horizontal",
10102 range: false,
10103 step: 1,
10104 value: 0,
10105 values: null
10106 },
10107
10108 _create: function() {
10109 var self = this,
10110 o = this.options;
10111
10112 this._keySliding = false;
10113 this._mouseSliding = false;
10114 this._animateOff = true;
10115 this._handleIndex = null;
10116 this._detectOrientation();
10117 this._mouseInit();
10118
10119 this.element
10120 .addClass( "ui-slider" +
10121 " ui-slider-" + this.orientation +
10122 " ui-widget" +
10123 " ui-widget-content" +
10124 " ui-corner-all" );
10125
10126 if ( o.disabled ) {
10127 this.element.addClass( "ui-slider-disabled ui-disabled" );
10128 }
10129
10130 this.range = $([]);
10131
10132 if ( o.range ) {
10133 if ( o.range === true ) {
10134 this.range = $( "<div></div>" );
10135 if ( !o.values ) {
10136 o.values = [ this._valueMin(), this._valueMin() ];
10137 }
10138 if ( o.values.length && o.values.length !== 2 ) {
10139 o.values = [ o.values[0], o.values[0] ];
10140 }
10141 } else {
10142 this.range = $( "<div></div>" );
10143 }
10144
10145 this.range
10146 .appendTo( this.element )
10147 .addClass( "ui-slider-range" );
10148
10149 if ( o.range === "min" || o.range === "max" ) {
10150 this.range.addClass( "ui-slider-range-" + o.range );
10151 }
10152
10153 // note: this isn't the most fittingly semantic framework class for this element,
10154 // but worked best visually with a variety of themes
10155 this.range.addClass( "ui-widget-header" );
10156 }
10157
10158 if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
10159 $( "<a href='#'></a>" )
10160 .appendTo( this.element )
10161 .addClass( "ui-slider-handle" );
10162 }
10163
10164 if ( o.values && o.values.length ) {
10165 while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
10166 $( "<a href='#'></a>" )
10167 .appendTo( this.element )
10168 .addClass( "ui-slider-handle" );
10169 }
10170 }
10171
10172 this.handles = $( ".ui-slider-handle", this.element )
10173 .addClass( "ui-state-default" +
10174 " ui-corner-all" );
10175
10176 this.handle = this.handles.eq( 0 );
10177
10178 this.handles.add( this.range ).filter( "a" )
10179 .click(function( event ) {
10180 event.preventDefault();
10181 })
10182 .hover(function() {
10183 if ( !o.disabled ) {
10184 $( this ).addClass( "ui-state-hover" );
10185 }
10186 }, function() {
10187 $( this ).removeClass( "ui-state-hover" );
10188 })
10189 .focus(function() {
10190 if ( !o.disabled ) {
10191 $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
10192 $( this ).addClass( "ui-state-focus" );
10193 } else {
10194 $( this ).blur();
10195 }
10196 })
10197 .blur(function() {
10198 $( this ).removeClass( "ui-state-focus" );
10199 });
10200
10201 this.handles.each(function( i ) {
10202 $( this ).data( "index.ui-slider-handle", i );
10203 });
10204
10205 this.handles
10206 .keydown(function( event ) {
10207 var ret = true,
10208 index = $( this ).data( "index.ui-slider-handle" ),
10209 allowed,
10210 curVal,
10211 newVal,
10212 step;
10213
10214 if ( self.options.disabled ) {
10215 return;
10216 }
10217
10218 switch ( event.keyCode ) {
10219 case $.ui.keyCode.HOME:
10220 case $.ui.keyCode.END:
10221 case $.ui.keyCode.PAGE_UP:
10222 case $.ui.keyCode.PAGE_DOWN:
10223 case $.ui.keyCode.UP:
10224 case $.ui.keyCode.RIGHT:
10225 case $.ui.keyCode.DOWN:
10226 case $.ui.keyCode.LEFT:
10227 ret = false;
10228 if ( !self._keySliding ) {
10229 self._keySliding = true;
10230 $( this ).addClass( "ui-state-active" );
10231 allowed = self._start( event, index );
10232 if ( allowed === false ) {
10233 return;
10234 }
10235 }
10236 break;
10237 }
10238
10239 step = self.options.step;
10240 if ( self.options.values && self.options.values.length ) {
10241 curVal = newVal = self.values( index );
10242 } else {
10243 curVal = newVal = self.value();
10244 }
10245
10246 switch ( event.keyCode ) {
10247 case $.ui.keyCode.HOME:
10248 newVal = self._valueMin();
10249 break;
10250 case $.ui.keyCode.END:
10251 newVal = self._valueMax();
10252 break;
10253 case $.ui.keyCode.PAGE_UP:
10254 newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
10255 break;
10256 case $.ui.keyCode.PAGE_DOWN:
10257 newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
10258 break;
10259 case $.ui.keyCode.UP:
10260 case $.ui.keyCode.RIGHT:
10261 if ( curVal === self._valueMax() ) {
10262 return;
10263 }
10264 newVal = self._trimAlignValue( curVal + step );
10265 break;
10266 case $.ui.keyCode.DOWN:
10267 case $.ui.keyCode.LEFT:
10268 if ( curVal === self._valueMin() ) {
10269 return;
10270 }
10271 newVal = self._trimAlignValue( curVal - step );
10272 break;
10273 }
10274
10275 self._slide( event, index, newVal );
10276
10277 return ret;
10278
10279 })
10280 .keyup(function( event ) {
10281 var index = $( this ).data( "index.ui-slider-handle" );
10282
10283 if ( self._keySliding ) {
10284 self._keySliding = false;
10285 self._stop( event, index );
10286 self._change( event, index );
10287 $( this ).removeClass( "ui-state-active" );
10288 }
10289
10290 });
10291
10292 this._refreshValue();
10293
10294 this._animateOff = false;
10295 },
10296
10297 destroy: function() {
10298 this.handles.remove();
10299 this.range.remove();
10300
10301 this.element
10302 .removeClass( "ui-slider" +
10303 " ui-slider-horizontal" +
10304 " ui-slider-vertical" +
10305 " ui-slider-disabled" +
10306 " ui-widget" +
10307 " ui-widget-content" +
10308 " ui-corner-all" )
10309 .removeData( "slider" )
10310 .unbind( ".slider" );
10311
10312 this._mouseDestroy();
10313
10314 return this;
10315 },
10316
10317 _mouseCapture: function( event ) {
10318 var o = this.options,
10319 position,
10320 normValue,
10321 distance,
10322 closestHandle,
10323 self,
10324 index,
10325 allowed,
10326 offset,
10327 mouseOverHandle;
10328
10329 if ( o.disabled ) {
10330 return false;
10331 }
10332
10333 this.elementSize = {
10334 width: this.element.outerWidth(),
10335 height: this.element.outerHeight()
10336 };
10337 this.elementOffset = this.element.offset();
10338
10339 position = { x: event.pageX, y: event.pageY };
10340 normValue = this._normValueFromMouse( position );
10341 distance = this._valueMax() - this._valueMin() + 1;
10342 self = this;
10343 this.handles.each(function( i ) {
10344 var thisDistance = Math.abs( normValue - self.values(i) );
10345 if ( distance > thisDistance ) {
10346 distance = thisDistance;
10347 closestHandle = $( this );
10348 index = i;
10349 }
10350 });
10351
10352 // workaround for bug #3736 (if both handles of a range are at 0,
10353 // the first is always used as the one with least distance,
10354 // and moving it is obviously prevented by preventing negative ranges)
10355 if( o.range === true && this.values(1) === o.min ) {
10356 index += 1;
10357 closestHandle = $( this.handles[index] );
10358 }
10359
10360 allowed = this._start( event, index );
10361 if ( allowed === false ) {
10362 return false;
10363 }
10364 this._mouseSliding = true;
10365
10366 self._handleIndex = index;
10367
10368 closestHandle
10369 .addClass( "ui-state-active" )
10370 .focus();
10371
10372 offset = closestHandle.offset();
10373 mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
10374 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
10375 left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
10376 top: event.pageY - offset.top -
10377 ( closestHandle.height() / 2 ) -
10378 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
10379 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
10380 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
10381 };
10382
10383 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
10384 this._slide( event, index, normValue );
10385 }
10386 this._animateOff = true;
10387 return true;
10388 },
10389
10390 _mouseStart: function( event ) {
10391 return true;
10392 },
10393
10394 _mouseDrag: function( event ) {
10395 var position = { x: event.pageX, y: event.pageY },
10396 normValue = this._normValueFromMouse( position );
10397
10398 this._slide( event, this._handleIndex, normValue );
10399
10400 return false;
10401 },
10402
10403 _mouseStop: function( event ) {
10404 this.handles.removeClass( "ui-state-active" );
10405 this._mouseSliding = false;
10406
10407 this._stop( event, this._handleIndex );
10408 this._change( event, this._handleIndex );
10409
10410 this._handleIndex = null;
10411 this._clickOffset = null;
10412 this._animateOff = false;
10413
10414 return false;
10415 },
10416
10417 _detectOrientation: function() {
10418 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
10419 },
10420
10421 _normValueFromMouse: function( position ) {
10422 var pixelTotal,
10423 pixelMouse,
10424 percentMouse,
10425 valueTotal,
10426 valueMouse;
10427
10428 if ( this.orientation === "horizontal" ) {
10429 pixelTotal = this.elementSize.width;
10430 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
10431 } else {
10432 pixelTotal = this.elementSize.height;
10433 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
10434 }
10435
10436 percentMouse = ( pixelMouse / pixelTotal );
10437 if ( percentMouse > 1 ) {
10438 percentMouse = 1;
10439 }
10440 if ( percentMouse < 0 ) {
10441 percentMouse = 0;
10442 }
10443 if ( this.orientation === "vertical" ) {
10444 percentMouse = 1 - percentMouse;
10445 }
10446
10447 valueTotal = this._valueMax() - this._valueMin();
10448 valueMouse = this._valueMin() + percentMouse * valueTotal;
10449
10450 return this._trimAlignValue( valueMouse );
10451 },
10452
10453 _start: function( event, index ) {
10454 var uiHash = {
10455 handle: this.handles[ index ],
10456 value: this.value()
10457 };
10458 if ( this.options.values && this.options.values.length ) {
10459 uiHash.value = this.values( index );
10460 uiHash.values = this.values();
10461 }
10462 return this._trigger( "start", event, uiHash );
10463 },
10464
10465 _slide: function( event, index, newVal ) {
10466 var otherVal,
10467 newValues,
10468 allowed;
10469
10470 if ( this.options.values && this.options.values.length ) {
10471 otherVal = this.values( index ? 0 : 1 );
10472
10473 if ( ( this.options.values.length === 2 && this.options.range === true ) &&
10474 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
10475 ) {
10476 newVal = otherVal;
10477 }
10478
10479 if ( newVal !== this.values( index ) ) {
10480 newValues = this.values();
10481 newValues[ index ] = newVal;
10482 // A slide can be canceled by returning false from the slide callback
10483 allowed = this._trigger( "slide", event, {
10484 handle: this.handles[ index ],
10485 value: newVal,
10486 values: newValues
10487 } );
10488 otherVal = this.values( index ? 0 : 1 );
10489 if ( allowed !== false ) {
10490 this.values( index, newVal, true );
10491 }
10492 }
10493 } else {
10494 if ( newVal !== this.value() ) {
10495 // A slide can be canceled by returning false from the slide callback
10496 allowed = this._trigger( "slide", event, {
10497 handle: this.handles[ index ],
10498 value: newVal
10499 } );
10500 if ( allowed !== false ) {
10501 this.value( newVal );
10502 }
10503 }
10504 }
10505 },
10506
10507 _stop: function( event, index ) {
10508 var uiHash = {
10509 handle: this.handles[ index ],
10510 value: this.value()
10511 };
10512 if ( this.options.values && this.options.values.length ) {
10513 uiHash.value = this.values( index );
10514 uiHash.values = this.values();
10515 }
10516
10517 this._trigger( "stop", event, uiHash );
10518 },
10519
10520 _change: function( event, index ) {
10521 if ( !this._keySliding && !this._mouseSliding ) {
10522 var uiHash = {
10523 handle: this.handles[ index ],
10524 value: this.value()
10525 };
10526 if ( this.options.values && this.options.values.length ) {
10527 uiHash.value = this.values( index );
10528 uiHash.values = this.values();
10529 }
10530
10531 this._trigger( "change", event, uiHash );
10532 }
10533 },
10534
10535 value: function( newValue ) {
10536 if ( arguments.length ) {
10537 this.options.value = this._trimAlignValue( newValue );
10538 this._refreshValue();
10539 this._change( null, 0 );
10540 }
10541
10542 return this._value();
10543 },
10544
10545 values: function( index, newValue ) {
10546 var vals,
10547 newValues,
10548 i;
10549
10550 if ( arguments.length > 1 ) {
10551 this.options.values[ index ] = this._trimAlignValue( newValue );
10552 this._refreshValue();
10553 this._change( null, index );
10554 }
10555
10556 if ( arguments.length ) {
10557 if ( $.isArray( arguments[ 0 ] ) ) {
10558 vals = this.options.values;
10559 newValues = arguments[ 0 ];
10560 for ( i = 0; i < vals.length; i += 1 ) {
10561 vals[ i ] = this._trimAlignValue( newValues[ i ] );
10562 this._change( null, i );
10563 }
10564 this._refreshValue();
10565 } else {
10566 if ( this.options.values && this.options.values.length ) {
10567 return this._values( index );
10568 } else {
10569 return this.value();
10570 }
10571 }
10572 } else {
10573 return this._values();
10574 }
10575 },
10576
10577 _setOption: function( key, value ) {
10578 var i,
10579 valsLength = 0;
10580
10581 if ( $.isArray( this.options.values ) ) {
10582 valsLength = this.options.values.length;
10583 }
10584
10585 $.Widget.prototype._setOption.apply( this, arguments );
10586
10587 switch ( key ) {
10588 case "disabled":
10589 if ( value ) {
10590 this.handles.filter( ".ui-state-focus" ).blur();
10591 this.handles.removeClass( "ui-state-hover" );
10592 this.handles.attr( "disabled", "disabled" );
10593 this.element.addClass( "ui-disabled" );
10594 } else {
10595 this.handles.removeAttr( "disabled" );
10596 this.element.removeClass( "ui-disabled" );
10597 }
10598 break;
10599 case "orientation":
10600 this._detectOrientation();
10601 this.element
10602 .removeClass( "ui-slider-horizontal ui-slider-vertical" )
10603 .addClass( "ui-slider-" + this.orientation );
10604 this._refreshValue();
10605 break;
10606 case "value":
10607 this._animateOff = true;
10608 this._refreshValue();
10609 this._change( null, 0 );
10610 this._animateOff = false;
10611 break;
10612 case "values":
10613 this._animateOff = true;
10614 this._refreshValue();
10615 for ( i = 0; i < valsLength; i += 1 ) {
10616 this._change( null, i );
10617 }
10618 this._animateOff = false;
10619 break;
10620 }
10621 },
10622
10623 //internal value getter
10624 // _value() returns value trimmed by min and max, aligned by step
10625 _value: function() {
10626 var val = this.options.value;
10627 val = this._trimAlignValue( val );
10628
10629 return val;
10630 },
10631
10632 //internal values getter
10633 // _values() returns array of values trimmed by min and max, aligned by step
10634 // _values( index ) returns single value trimmed by min and max, aligned by step
10635 _values: function( index ) {
10636 var val,
10637 vals,
10638 i;
10639
10640 if ( arguments.length ) {
10641 val = this.options.values[ index ];
10642 val = this._trimAlignValue( val );
10643
10644 return val;
10645 } else {
10646 // .slice() creates a copy of the array
10647 // this copy gets trimmed by min and max and then returned
10648 vals = this.options.values.slice();
10649 for ( i = 0; i < vals.length; i+= 1) {
10650 vals[ i ] = this._trimAlignValue( vals[ i ] );
10651 }
10652
10653 return vals;
10654 }
10655 },
10656
10657 // returns the step-aligned value that val is closest to, between (inclusive) min and max
10658 _trimAlignValue: function( val ) {
10659 if ( val <= this._valueMin() ) {
10660 return this._valueMin();
10661 }
10662 if ( val >= this._valueMax() ) {
10663 return this._valueMax();
10664 }
10665 var step = ( this.options.step > 0 ) ? this.options.step : 1,
10666 valModStep = (val - this._valueMin()) % step;
10667 alignValue = val - valModStep;
10668
10669 if ( Math.abs(valModStep) * 2 >= step ) {
10670 alignValue += ( valModStep > 0 ) ? step : ( -step );
10671 }
10672
10673 // Since JavaScript has problems with large floats, round
10674 // the final value to 5 digits after the decimal point (see #4124)
10675 return parseFloat( alignValue.toFixed(5) );
10676 },
10677
10678 _valueMin: function() {
10679 return this.options.min;
10680 },
10681
10682 _valueMax: function() {
10683 return this.options.max;
10684 },
10685
10686 _refreshValue: function() {
10687 var oRange = this.options.range,
10688 o = this.options,
10689 self = this,
10690 animate = ( !this._animateOff ) ? o.animate : false,
10691 valPercent,
10692 _set = {},
10693 lastValPercent,
10694 value,
10695 valueMin,
10696 valueMax;
10697
10698 if ( this.options.values && this.options.values.length ) {
10699 this.handles.each(function( i, j ) {
10700 valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
10701 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
10702 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
10703 if ( self.options.range === true ) {
10704 if ( self.orientation === "horizontal" ) {
10705 if ( i === 0 ) {
10706 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
10707 }
10708 if ( i === 1 ) {
10709 self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
10710 }
10711 } else {
10712 if ( i === 0 ) {
10713 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
10714 }
10715 if ( i === 1 ) {
10716 self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
10717 }
10718 }
10719 }
10720 lastValPercent = valPercent;
10721 });
10722 } else {
10723 value = this.value();
10724 valueMin = this._valueMin();
10725 valueMax = this._valueMax();
10726 valPercent = ( valueMax !== valueMin ) ?
10727 ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
10728 0;
10729 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
10730 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
10731
10732 if ( oRange === "min" && this.orientation === "horizontal" ) {
10733 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
10734 }
10735 if ( oRange === "max" && this.orientation === "horizontal" ) {
10736 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
10737 }
10738 if ( oRange === "min" && this.orientation === "vertical" ) {
10739 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
10740 }
10741 if ( oRange === "max" && this.orientation === "vertical" ) {
10742 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
10743 }
10744 }
10745 }
10746
10747});
10748
10749$.extend( $.ui.slider, {
10750 version: "1.8.7"
10751});
10752
10753}(jQuery));
10754/*
10755 * jQuery UI Tabs 1.8.7
10756 *
10757 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
10758 * Dual licensed under the MIT or GPL Version 2 licenses.
10759 * http://jquery.org/license
10760 *
10761 * http://docs.jquery.com/UI/Tabs
10762 *
10763 * Depends:
10764 * jquery.ui.core.js
10765 * jquery.ui.widget.js
10766 */
10767(function( $, undefined ) {
10768
10769var tabId = 0,
10770 listId = 0;
10771
10772function getNextTabId() {
10773 return ++tabId;
10774}
10775
10776function getNextListId() {
10777 return ++listId;
10778}
10779
10780$.widget( "ui.tabs", {
10781 options: {
10782 add: null,
10783 ajaxOptions: null,
10784 cache: false,
10785 cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
10786 collapsible: false,
10787 disable: null,
10788 disabled: [],
10789 enable: null,
10790 event: "click",
10791 fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
10792 idPrefix: "ui-tabs-",
10793 load: null,
10794 panelTemplate: "<div></div>",
10795 remove: null,
10796 select: null,
10797 show: null,
10798 spinner: "<em>Loading&#8230;</em>",
10799 tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
10800 },
10801
10802 _create: function() {
10803 this._tabify( true );
10804 },
10805
10806 _setOption: function( key, value ) {
10807 if ( key == "selected" ) {
10808 if (this.options.collapsible && value == this.options.selected ) {
10809 return;
10810 }
10811 this.select( value );
10812 } else {
10813 this.options[ key ] = value;
10814 this._tabify();
10815 }
10816 },
10817
10818 _tabId: function( a ) {
10819 return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
10820 this.options.idPrefix + getNextTabId();
10821 },
10822
10823 _sanitizeSelector: function( hash ) {
10824 // we need this because an id may contain a ":"
10825 return hash.replace( /:/g, "\\:" );
10826 },
10827
10828 _cookie: function() {
10829 var cookie = this.cookie ||
10830 ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
10831 return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
10832 },
10833
10834 _ui: function( tab, panel ) {
10835 return {
10836 tab: tab,
10837 panel: panel,
10838 index: this.anchors.index( tab )
10839 };
10840 },
10841
10842 _cleanup: function() {
10843 // restore all former loading tabs labels
10844 this.lis.filter( ".ui-state-processing" )
10845 .removeClass( "ui-state-processing" )
10846 .find( "span:data(label.tabs)" )
10847 .each(function() {
10848 var el = $( this );
10849 el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
10850 });
10851 },
10852
10853 _tabify: function( init ) {
10854 var self = this,
10855 o = this.options,
10856 fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
10857
10858 this.list = this.element.find( "ol,ul" ).eq( 0 );
10859 this.lis = $( " > li:has(a[href])", this.list );
10860 this.anchors = this.lis.map(function() {
10861 return $( "a", this )[ 0 ];
10862 });
10863 this.panels = $( [] );
10864
10865 this.anchors.each(function( i, a ) {
10866 var href = $( a ).attr( "href" );
10867 // For dynamically created HTML that contains a hash as href IE < 8 expands
10868 // such href to the full page url with hash and then misinterprets tab as ajax.
10869 // Same consideration applies for an added tab with a fragment identifier
10870 // since a[href=#fragment-identifier] does unexpectedly not match.
10871 // Thus normalize href attribute...
10872 var hrefBase = href.split( "#" )[ 0 ],
10873 baseEl;
10874 if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
10875 ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
10876 href = a.hash;
10877 a.href = href;
10878 }
10879
10880 // inline tab
10881 if ( fragmentId.test( href ) ) {
10882 self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) );
10883 // remote tab
10884 // prevent loading the page itself if href is just "#"
10885 } else if ( href && href !== "#" ) {
10886 // required for restore on destroy
10887 $.data( a, "href.tabs", href );
10888
10889 // TODO until #3808 is fixed strip fragment identifier from url
10890 // (IE fails to load from such url)
10891 $.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
10892
10893 var id = self._tabId( a );
10894 a.href = "#" + id;
10895 var $panel = self.element.find( "#" + id );
10896 if ( !$panel.length ) {
10897 $panel = $( o.panelTemplate )
10898 .attr( "id", id )
10899 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
10900 .insertAfter( self.panels[ i - 1 ] || self.list );
10901 $panel.data( "destroy.tabs", true );
10902 }
10903 self.panels = self.panels.add( $panel );
10904 // invalid tab href
10905 } else {
10906 o.disabled.push( i );
10907 }
10908 });
10909
10910 // initialization from scratch
10911 if ( init ) {
10912 // attach necessary classes for styling
10913 this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
10914 this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
10915 this.lis.addClass( "ui-state-default ui-corner-top" );
10916 this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
10917
10918 // Selected tab
10919 // use "selected" option or try to retrieve:
10920 // 1. from fragment identifier in url
10921 // 2. from cookie
10922 // 3. from selected class attribute on <li>
10923 if ( o.selected === undefined ) {
10924 if ( location.hash ) {
10925 this.anchors.each(function( i, a ) {
10926 if ( a.hash == location.hash ) {
10927 o.selected = i;
10928 return false;
10929 }
10930 });
10931 }
10932 if ( typeof o.selected !== "number" && o.cookie ) {
10933 o.selected = parseInt( self._cookie(), 10 );
10934 }
10935 if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
10936 o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
10937 }
10938 o.selected = o.selected || ( this.lis.length ? 0 : -1 );
10939 } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
10940 o.selected = -1;
10941 }
10942
10943 // sanity check - default to first tab...
10944 o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
10945 ? o.selected
10946 : 0;
10947
10948 // Take disabling tabs via class attribute from HTML
10949 // into account and update option properly.
10950 // A selected tab cannot become disabled.
10951 o.disabled = $.unique( o.disabled.concat(
10952 $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
10953 return self.lis.index( n );
10954 })
10955 ) ).sort();
10956
10957 if ( $.inArray( o.selected, o.disabled ) != -1 ) {
10958 o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
10959 }
10960
10961 // highlight selected tab
10962 this.panels.addClass( "ui-tabs-hide" );
10963 this.lis.removeClass( "ui-tabs-selected ui-state-active" );
10964 // check for length avoids error when initializing empty list
10965 if ( o.selected >= 0 && this.anchors.length ) {
10966 self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
10967 this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
10968
10969 // seems to be expected behavior that the show callback is fired
10970 self.element.queue( "tabs", function() {
10971 self._trigger( "show", null,
10972 self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ) ) );
10973 });
10974
10975 this.load( o.selected );
10976 }
10977
10978 // clean up to avoid memory leaks in certain versions of IE 6
10979 // TODO: namespace this event
10980 $( window ).bind( "unload", function() {
10981 self.lis.add( self.anchors ).unbind( ".tabs" );
10982 self.lis = self.anchors = self.panels = null;
10983 });
10984 // update selected after add/remove
10985 } else {
10986 o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
10987 }
10988
10989 // update collapsible
10990 // TODO: use .toggleClass()
10991 this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
10992
10993 // set or update cookie after init and add/remove respectively
10994 if ( o.cookie ) {
10995 this._cookie( o.selected, o.cookie );
10996 }
10997
10998 // disable tabs
10999 for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
11000 $( li )[ $.inArray( i, o.disabled ) != -1 &&
11001 // TODO: use .toggleClass()
11002 !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
11003 }
11004
11005 // reset cache if switching from cached to not cached
11006 if ( o.cache === false ) {
11007 this.anchors.removeData( "cache.tabs" );
11008 }
11009
11010 // remove all handlers before, tabify may run on existing tabs after add or option change
11011 this.lis.add( this.anchors ).unbind( ".tabs" );
11012
11013 if ( o.event !== "mouseover" ) {
11014 var addState = function( state, el ) {
11015 if ( el.is( ":not(.ui-state-disabled)" ) ) {
11016 el.addClass( "ui-state-" + state );
11017 }
11018 };
11019 var removeState = function( state, el ) {
11020 el.removeClass( "ui-state-" + state );
11021 };
11022 this.lis.bind( "mouseover.tabs" , function() {
11023 addState( "hover", $( this ) );
11024 });
11025 this.lis.bind( "mouseout.tabs", function() {
11026 removeState( "hover", $( this ) );
11027 });
11028 this.anchors.bind( "focus.tabs", function() {
11029 addState( "focus", $( this ).closest( "li" ) );
11030 });
11031 this.anchors.bind( "blur.tabs", function() {
11032 removeState( "focus", $( this ).closest( "li" ) );
11033 });
11034 }
11035
11036 // set up animations
11037 var hideFx, showFx;
11038 if ( o.fx ) {
11039 if ( $.isArray( o.fx ) ) {
11040 hideFx = o.fx[ 0 ];
11041 showFx = o.fx[ 1 ];
11042 } else {
11043 hideFx = showFx = o.fx;
11044 }
11045 }
11046
11047 // Reset certain styles left over from animation
11048 // and prevent IE's ClearType bug...
11049 function resetStyle( $el, fx ) {
11050 $el.css( "display", "" );
11051 if ( !$.support.opacity && fx.opacity ) {
11052 $el[ 0 ].style.removeAttribute( "filter" );
11053 }
11054 }
11055
11056 // Show a tab...
11057 var showTab = showFx
11058 ? function( clicked, $show ) {
11059 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
11060 $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
11061 .animate( showFx, showFx.duration || "normal", function() {
11062 resetStyle( $show, showFx );
11063 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
11064 });
11065 }
11066 : function( clicked, $show ) {
11067 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
11068 $show.removeClass( "ui-tabs-hide" );
11069 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
11070 };
11071
11072 // Hide a tab, $show is optional...
11073 var hideTab = hideFx
11074 ? function( clicked, $hide ) {
11075 $hide.animate( hideFx, hideFx.duration || "normal", function() {
11076 self.lis.removeClass( "ui-tabs-selected ui-state-active" );
11077 $hide.addClass( "ui-tabs-hide" );
11078 resetStyle( $hide, hideFx );
11079 self.element.dequeue( "tabs" );
11080 });
11081 }
11082 : function( clicked, $hide, $show ) {
11083 self.lis.removeClass( "ui-tabs-selected ui-state-active" );
11084 $hide.addClass( "ui-tabs-hide" );
11085 self.element.dequeue( "tabs" );
11086 };
11087
11088 // attach tab event handler, unbind to avoid duplicates from former tabifying...
11089 this.anchors.bind( o.event + ".tabs", function() {
11090 var el = this,
11091 $li = $(el).closest( "li" ),
11092 $hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
11093 $show = self.element.find( self._sanitizeSelector( el.hash ) );
11094
11095 // If tab is already selected and not collapsible or tab disabled or
11096 // or is already loading or click callback returns false stop here.
11097 // Check if click handler returns false last so that it is not executed
11098 // for a disabled or loading tab!
11099 if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
11100 $li.hasClass( "ui-state-disabled" ) ||
11101 $li.hasClass( "ui-state-processing" ) ||
11102 self.panels.filter( ":animated" ).length ||
11103 self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
11104 this.blur();
11105 return false;
11106 }
11107
11108 o.selected = self.anchors.index( this );
11109
11110 self.abort();
11111
11112 // if tab may be closed
11113 if ( o.collapsible ) {
11114 if ( $li.hasClass( "ui-tabs-selected" ) ) {
11115 o.selected = -1;
11116
11117 if ( o.cookie ) {
11118 self._cookie( o.selected, o.cookie );
11119 }
11120
11121 self.element.queue( "tabs", function() {
11122 hideTab( el, $hide );
11123 }).dequeue( "tabs" );
11124
11125 this.blur();
11126 return false;
11127 } else if ( !$hide.length ) {
11128 if ( o.cookie ) {
11129 self._cookie( o.selected, o.cookie );
11130 }
11131
11132 self.element.queue( "tabs", function() {
11133 showTab( el, $show );
11134 });
11135
11136 // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
11137 self.load( self.anchors.index( this ) );
11138
11139 this.blur();
11140 return false;
11141 }
11142 }
11143
11144 if ( o.cookie ) {
11145 self._cookie( o.selected, o.cookie );
11146 }
11147
11148 // show new tab
11149 if ( $show.length ) {
11150 if ( $hide.length ) {
11151 self.element.queue( "tabs", function() {
11152 hideTab( el, $hide );
11153 });
11154 }
11155 self.element.queue( "tabs", function() {
11156 showTab( el, $show );
11157 });
11158
11159 self.load( self.anchors.index( this ) );
11160 } else {
11161 throw "jQuery UI Tabs: Mismatching fragment identifier.";
11162 }
11163
11164 // Prevent IE from keeping other link focussed when using the back button
11165 // and remove dotted border from clicked link. This is controlled via CSS
11166 // in modern browsers; blur() removes focus from address bar in Firefox
11167 // which can become a usability and annoying problem with tabs('rotate').
11168 if ( $.browser.msie ) {
11169 this.blur();
11170 }
11171 });
11172
11173 // disable click in any case
11174 this.anchors.bind( "click.tabs", function(){
11175 return false;
11176 });
11177 },
11178
11179 _getIndex: function( index ) {
11180 // meta-function to give users option to provide a href string instead of a numerical index.
11181 // also sanitizes numerical indexes to valid values.
11182 if ( typeof index == "string" ) {
11183 index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
11184 }
11185
11186 return index;
11187 },
11188
11189 destroy: function() {
11190 var o = this.options;
11191
11192 this.abort();
11193
11194 this.element
11195 .unbind( ".tabs" )
11196 .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
11197 .removeData( "tabs" );
11198
11199 this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
11200
11201 this.anchors.each(function() {
11202 var href = $.data( this, "href.tabs" );
11203 if ( href ) {
11204 this.href = href;
11205 }
11206 var $this = $( this ).unbind( ".tabs" );
11207 $.each( [ "href", "load", "cache" ], function( i, prefix ) {
11208 $this.removeData( prefix + ".tabs" );
11209 });
11210 });
11211
11212 this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
11213 if ( $.data( this, "destroy.tabs" ) ) {
11214 $( this ).remove();
11215 } else {
11216 $( this ).removeClass([
11217 "ui-state-default",
11218 "ui-corner-top",
11219 "ui-tabs-selected",
11220 "ui-state-active",
11221 "ui-state-hover",
11222 "ui-state-focus",
11223 "ui-state-disabled",
11224 "ui-tabs-panel",
11225 "ui-widget-content",
11226 "ui-corner-bottom",
11227 "ui-tabs-hide"
11228 ].join( " " ) );
11229 }
11230 });
11231
11232 if ( o.cookie ) {
11233 this._cookie( null, o.cookie );
11234 }
11235
11236 return this;
11237 },
11238
11239 add: function( url, label, index ) {
11240 if ( index === undefined ) {
11241 index = this.anchors.length;
11242 }
11243
11244 var self = this,
11245 o = this.options,
11246 $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
11247 id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
11248
11249 $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
11250
11251 // try to find an existing element before creating a new one
11252 var $panel = self.element.find( "#" + id );
11253 if ( !$panel.length ) {
11254 $panel = $( o.panelTemplate )
11255 .attr( "id", id )
11256 .data( "destroy.tabs", true );
11257 }
11258 $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
11259
11260 if ( index >= this.lis.length ) {
11261 $li.appendTo( this.list );
11262 $panel.appendTo( this.list[ 0 ].parentNode );
11263 } else {
11264 $li.insertBefore( this.lis[ index ] );
11265 $panel.insertBefore( this.panels[ index ] );
11266 }
11267
11268 o.disabled = $.map( o.disabled, function( n, i ) {
11269 return n >= index ? ++n : n;
11270 });
11271
11272 this._tabify();
11273
11274 if ( this.anchors.length == 1 ) {
11275 o.selected = 0;
11276 $li.addClass( "ui-tabs-selected ui-state-active" );
11277 $panel.removeClass( "ui-tabs-hide" );
11278 this.element.queue( "tabs", function() {
11279 self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
11280 });
11281
11282 this.load( 0 );
11283 }
11284
11285 this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
11286 return this;
11287 },
11288
11289 remove: function( index ) {
11290 index = this._getIndex( index );
11291 var o = this.options,
11292 $li = this.lis.eq( index ).remove(),
11293 $panel = this.panels.eq( index ).remove();
11294
11295 // If selected tab was removed focus tab to the right or
11296 // in case the last tab was removed the tab to the left.
11297 if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
11298 this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
11299 }
11300
11301 o.disabled = $.map(
11302 $.grep( o.disabled, function(n, i) {
11303 return n != index;
11304 }),
11305 function( n, i ) {
11306 return n >= index ? --n : n;
11307 });
11308
11309 this._tabify();
11310
11311 this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
11312 return this;
11313 },
11314
11315 enable: function( index ) {
11316 index = this._getIndex( index );
11317 var o = this.options;
11318 if ( $.inArray( index, o.disabled ) == -1 ) {
11319 return;
11320 }
11321
11322 this.lis.eq( index ).removeClass( "ui-state-disabled" );
11323 o.disabled = $.grep( o.disabled, function( n, i ) {
11324 return n != index;
11325 });
11326
11327 this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
11328 return this;
11329 },
11330
11331 disable: function( index ) {
11332 index = this._getIndex( index );
11333 var self = this, o = this.options;
11334 // cannot disable already selected tab
11335 if ( index != o.selected ) {
11336 this.lis.eq( index ).addClass( "ui-state-disabled" );
11337
11338 o.disabled.push( index );
11339 o.disabled.sort();
11340
11341 this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
11342 }
11343
11344 return this;
11345 },
11346
11347 select: function( index ) {
11348 index = this._getIndex( index );
11349 if ( index == -1 ) {
11350 if ( this.options.collapsible && this.options.selected != -1 ) {
11351 index = this.options.selected;
11352 } else {
11353 return this;
11354 }
11355 }
11356 this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
11357 return this;
11358 },
11359
11360 load: function( index ) {
11361 index = this._getIndex( index );
11362 var self = this,
11363 o = this.options,
11364 a = this.anchors.eq( index )[ 0 ],
11365 url = $.data( a, "load.tabs" );
11366
11367 this.abort();
11368
11369 // not remote or from cache
11370 if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
11371 this.element.dequeue( "tabs" );
11372 return;
11373 }
11374
11375 // load remote from here on
11376 this.lis.eq( index ).addClass( "ui-state-processing" );
11377
11378 if ( o.spinner ) {
11379 var span = $( "span", a );
11380 span.data( "label.tabs", span.html() ).html( o.spinner );
11381 }
11382
11383 this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
11384 url: url,
11385 success: function( r, s ) {
11386 self.element.find( self._sanitizeSelector( a.hash ) ).html( r );
11387
11388 // take care of tab labels
11389 self._cleanup();
11390
11391 if ( o.cache ) {
11392 $.data( a, "cache.tabs", true );
11393 }
11394
11395 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
11396 try {
11397 o.ajaxOptions.success( r, s );
11398 }
11399 catch ( e ) {}
11400 },
11401 error: function( xhr, s, e ) {
11402 // take care of tab labels
11403 self._cleanup();
11404
11405 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
11406 try {
11407 // Passing index avoid a race condition when this method is
11408 // called after the user has selected another tab.
11409 // Pass the anchor that initiated this request allows
11410 // loadError to manipulate the tab content panel via $(a.hash)
11411 o.ajaxOptions.error( xhr, s, index, a );
11412 }
11413 catch ( e ) {}
11414 }
11415 } ) );
11416
11417 // last, so that load event is fired before show...
11418 self.element.dequeue( "tabs" );
11419
11420 return this;
11421 },
11422
11423 abort: function() {
11424 // stop possibly running animations
11425 this.element.queue( [] );
11426 this.panels.stop( false, true );
11427
11428 // "tabs" queue must not contain more than two elements,
11429 // which are the callbacks for the latest clicked tab...
11430 this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
11431
11432 // terminate pending requests from other tabs
11433 if ( this.xhr ) {
11434 this.xhr.abort();
11435 delete this.xhr;
11436 }
11437
11438 // take care of tab labels
11439 this._cleanup();
11440 return this;
11441 },
11442
11443 url: function( index, url ) {
11444 this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
11445 return this;
11446 },
11447
11448 length: function() {
11449 return this.anchors.length;
11450 }
11451});
11452
11453$.extend( $.ui.tabs, {
11454 version: "1.8.7"
11455});
11456
11457/*
11458 * Tabs Extensions
11459 */
11460
11461/*
11462 * Rotate
11463 */
11464$.extend( $.ui.tabs.prototype, {
11465 rotation: null,
11466 rotate: function( ms, continuing ) {
11467 var self = this,
11468 o = this.options;
11469
11470 var rotate = self._rotate || ( self._rotate = function( e ) {
11471 clearTimeout( self.rotation );
11472 self.rotation = setTimeout(function() {
11473 var t = o.selected;
11474 self.select( ++t < self.anchors.length ? t : 0 );
11475 }, ms );
11476
11477 if ( e ) {
11478 e.stopPropagation();
11479 }
11480 });
11481
11482 var stop = self._unrotate || ( self._unrotate = !continuing
11483 ? function(e) {
11484 if (e.clientX) { // in case of a true click
11485 self.rotate(null);
11486 }
11487 }
11488 : function( e ) {
11489 t = o.selected;
11490 rotate();
11491 });
11492
11493 // start rotation
11494 if ( ms ) {
11495 this.element.bind( "tabsshow", rotate );
11496 this.anchors.bind( o.event + ".tabs", stop );
11497 rotate();
11498 // stop rotation
11499 } else {
11500 clearTimeout( self.rotation );
11501 this.element.unbind( "tabsshow", rotate );
11502 this.anchors.unbind( o.event + ".tabs", stop );
11503 delete this._rotate;
11504 delete this._unrotate;
11505 }
11506
11507 return this;
11508 }
11509});
11510
11511})( jQuery );
Note: See TracBrowser for help on using the repository browser.