comparison jquery-ui/development-bundle/ui/jquery-ui-1.8.11.custom.js @ 0:b2e4605f20b2

beta version
author dwinter
date Thu, 30 Jun 2011 09:07:49 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:b2e4605f20b2
1 /*!
2 * jQuery UI 1.8.11
3 *
4 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT or GPL Version 2 licenses.
6 * http://jquery.org/license
7 *
8 * http://docs.jquery.com/UI
9 */
10 (function( $, undefined ) {
11
12 // prevent duplicate loading
13 // this is only a problem because we proxy existing functions
14 // and we don't want to double proxy them
15 $.ui = $.ui || {};
16 if ( $.ui.version ) {
17 return;
18 }
19
20 $.extend( $.ui, {
21 version: "1.8.11",
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
177 function 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.11
311 *
312 * Copyright 2011, 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+
321 if ( $.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.11
573 *
574 * Copyright 2011, 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 // Click event may never have fired (Gecko & Opera)
649 if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
650 $.removeData(event.target, this.widgetName + '.preventClickEvent');
651 }
652
653 // these delegates are required to keep context
654 this._mouseMoveDelegate = function(event) {
655 return self._mouseMove(event);
656 };
657 this._mouseUpDelegate = function(event) {
658 return self._mouseUp(event);
659 };
660 $(document)
661 .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
662 .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
663
664 event.preventDefault();
665 event.originalEvent.mouseHandled = true;
666 return true;
667 },
668
669 _mouseMove: function(event) {
670 // IE mouseup check - mouseup happened when mouse was out of window
671 if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
672 return this._mouseUp(event);
673 }
674
675 if (this._mouseStarted) {
676 this._mouseDrag(event);
677 return event.preventDefault();
678 }
679
680 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
681 this._mouseStarted =
682 (this._mouseStart(this._mouseDownEvent, event) !== false);
683 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
684 }
685
686 return !this._mouseStarted;
687 },
688
689 _mouseUp: function(event) {
690 $(document)
691 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
692 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
693
694 if (this._mouseStarted) {
695 this._mouseStarted = false;
696
697 if (event.target == this._mouseDownEvent.target) {
698 $.data(event.target, this.widgetName + '.preventClickEvent', true);
699 }
700
701 this._mouseStop(event);
702 }
703
704 return false;
705 },
706
707 _mouseDistanceMet: function(event) {
708 return (Math.max(
709 Math.abs(this._mouseDownEvent.pageX - event.pageX),
710 Math.abs(this._mouseDownEvent.pageY - event.pageY)
711 ) >= this.options.distance
712 );
713 },
714
715 _mouseDelayMet: function(event) {
716 return this.mouseDelayMet;
717 },
718
719 // These are placeholder methods, to be overriden by extending plugin
720 _mouseStart: function(event) {},
721 _mouseDrag: function(event) {},
722 _mouseStop: function(event) {},
723 _mouseCapture: function(event) { return true; }
724 });
725
726 })(jQuery);
727 /*
728 * jQuery UI Position 1.8.11
729 *
730 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
731 * Dual licensed under the MIT or GPL Version 2 licenses.
732 * http://jquery.org/license
733 *
734 * http://docs.jquery.com/UI/Position
735 */
736 (function( $, undefined ) {
737
738 $.ui = $.ui || {};
739
740 var horizontalPositions = /left|center|right/,
741 verticalPositions = /top|center|bottom/,
742 center = "center",
743 _position = $.fn.position,
744 _offset = $.fn.offset;
745
746 $.fn.position = function( options ) {
747 if ( !options || !options.of ) {
748 return _position.apply( this, arguments );
749 }
750
751 // make a copy, we don't want to modify arguments
752 options = $.extend( {}, options );
753
754 var target = $( options.of ),
755 targetElem = target[0],
756 collision = ( options.collision || "flip" ).split( " " ),
757 offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
758 targetWidth,
759 targetHeight,
760 basePosition;
761
762 if ( targetElem.nodeType === 9 ) {
763 targetWidth = target.width();
764 targetHeight = target.height();
765 basePosition = { top: 0, left: 0 };
766 // TODO: use $.isWindow() in 1.9
767 } else if ( targetElem.setTimeout ) {
768 targetWidth = target.width();
769 targetHeight = target.height();
770 basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
771 } else if ( targetElem.preventDefault ) {
772 // force left top to allow flipping
773 options.at = "left top";
774 targetWidth = targetHeight = 0;
775 basePosition = { top: options.of.pageY, left: options.of.pageX };
776 } else {
777 targetWidth = target.outerWidth();
778 targetHeight = target.outerHeight();
779 basePosition = target.offset();
780 }
781
782 // force my and at to have valid horizontal and veritcal positions
783 // if a value is missing or invalid, it will be converted to center
784 $.each( [ "my", "at" ], function() {
785 var pos = ( options[this] || "" ).split( " " );
786 if ( pos.length === 1) {
787 pos = horizontalPositions.test( pos[0] ) ?
788 pos.concat( [center] ) :
789 verticalPositions.test( pos[0] ) ?
790 [ center ].concat( pos ) :
791 [ center, center ];
792 }
793 pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
794 pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
795 options[ this ] = pos;
796 });
797
798 // normalize collision option
799 if ( collision.length === 1 ) {
800 collision[ 1 ] = collision[ 0 ];
801 }
802
803 // normalize offset option
804 offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
805 if ( offset.length === 1 ) {
806 offset[ 1 ] = offset[ 0 ];
807 }
808 offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
809
810 if ( options.at[0] === "right" ) {
811 basePosition.left += targetWidth;
812 } else if ( options.at[0] === center ) {
813 basePosition.left += targetWidth / 2;
814 }
815
816 if ( options.at[1] === "bottom" ) {
817 basePosition.top += targetHeight;
818 } else if ( options.at[1] === center ) {
819 basePosition.top += targetHeight / 2;
820 }
821
822 basePosition.left += offset[ 0 ];
823 basePosition.top += offset[ 1 ];
824
825 return this.each(function() {
826 var elem = $( this ),
827 elemWidth = elem.outerWidth(),
828 elemHeight = elem.outerHeight(),
829 marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
830 marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
831 collisionWidth = elemWidth + marginLeft +
832 ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
833 collisionHeight = elemHeight + marginTop +
834 ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
835 position = $.extend( {}, basePosition ),
836 collisionPosition;
837
838 if ( options.my[0] === "right" ) {
839 position.left -= elemWidth;
840 } else if ( options.my[0] === center ) {
841 position.left -= elemWidth / 2;
842 }
843
844 if ( options.my[1] === "bottom" ) {
845 position.top -= elemHeight;
846 } else if ( options.my[1] === center ) {
847 position.top -= elemHeight / 2;
848 }
849
850 // prevent fractions (see #5280)
851 position.left = Math.round( position.left );
852 position.top = Math.round( position.top );
853
854 collisionPosition = {
855 left: position.left - marginLeft,
856 top: position.top - marginTop
857 };
858
859 $.each( [ "left", "top" ], function( i, dir ) {
860 if ( $.ui.position[ collision[i] ] ) {
861 $.ui.position[ collision[i] ][ dir ]( position, {
862 targetWidth: targetWidth,
863 targetHeight: targetHeight,
864 elemWidth: elemWidth,
865 elemHeight: elemHeight,
866 collisionPosition: collisionPosition,
867 collisionWidth: collisionWidth,
868 collisionHeight: collisionHeight,
869 offset: offset,
870 my: options.my,
871 at: options.at
872 });
873 }
874 });
875
876 if ( $.fn.bgiframe ) {
877 elem.bgiframe();
878 }
879 elem.offset( $.extend( position, { using: options.using } ) );
880 });
881 };
882
883 $.ui.position = {
884 fit: {
885 left: function( position, data ) {
886 var win = $( window ),
887 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
888 position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
889 },
890 top: function( position, data ) {
891 var win = $( window ),
892 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
893 position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
894 }
895 },
896
897 flip: {
898 left: function( position, data ) {
899 if ( data.at[0] === center ) {
900 return;
901 }
902 var win = $( window ),
903 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
904 myOffset = data.my[ 0 ] === "left" ?
905 -data.elemWidth :
906 data.my[ 0 ] === "right" ?
907 data.elemWidth :
908 0,
909 atOffset = data.at[ 0 ] === "left" ?
910 data.targetWidth :
911 -data.targetWidth,
912 offset = -2 * data.offset[ 0 ];
913 position.left += data.collisionPosition.left < 0 ?
914 myOffset + atOffset + offset :
915 over > 0 ?
916 myOffset + atOffset + offset :
917 0;
918 },
919 top: function( position, data ) {
920 if ( data.at[1] === center ) {
921 return;
922 }
923 var win = $( window ),
924 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
925 myOffset = data.my[ 1 ] === "top" ?
926 -data.elemHeight :
927 data.my[ 1 ] === "bottom" ?
928 data.elemHeight :
929 0,
930 atOffset = data.at[ 1 ] === "top" ?
931 data.targetHeight :
932 -data.targetHeight,
933 offset = -2 * data.offset[ 1 ];
934 position.top += data.collisionPosition.top < 0 ?
935 myOffset + atOffset + offset :
936 over > 0 ?
937 myOffset + atOffset + offset :
938 0;
939 }
940 }
941 };
942
943 // offset setter from jQuery 1.4
944 if ( !$.offset.setOffset ) {
945 $.offset.setOffset = function( elem, options ) {
946 // set position first, in-case top/left are set even on static elem
947 if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
948 elem.style.position = "relative";
949 }
950 var curElem = $( elem ),
951 curOffset = curElem.offset(),
952 curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0,
953 curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0,
954 props = {
955 top: (options.top - curOffset.top) + curTop,
956 left: (options.left - curOffset.left) + curLeft
957 };
958
959 if ( 'using' in options ) {
960 options.using.call( elem, props );
961 } else {
962 curElem.css( props );
963 }
964 };
965
966 $.fn.offset = function( options ) {
967 var elem = this[ 0 ];
968 if ( !elem || !elem.ownerDocument ) { return null; }
969 if ( options ) {
970 return this.each(function() {
971 $.offset.setOffset( this, options );
972 });
973 }
974 return _offset.call( this );
975 };
976 }
977
978 }( jQuery ));
979 /*
980 * jQuery UI Draggable 1.8.11
981 *
982 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
983 * Dual licensed under the MIT or GPL Version 2 licenses.
984 * http://jquery.org/license
985 *
986 * http://docs.jquery.com/UI/Draggables
987 *
988 * Depends:
989 * jquery.ui.core.js
990 * jquery.ui.mouse.js
991 * jquery.ui.widget.js
992 */
993 (function( $, undefined ) {
994
995 $.widget("ui.draggable", $.ui.mouse, {
996 widgetEventPrefix: "drag",
997 options: {
998 addClasses: true,
999 appendTo: "parent",
1000 axis: false,
1001 connectToSortable: false,
1002 containment: false,
1003 cursor: "auto",
1004 cursorAt: false,
1005 grid: false,
1006 handle: false,
1007 helper: "original",
1008 iframeFix: false,
1009 opacity: false,
1010 refreshPositions: false,
1011 revert: false,
1012 revertDuration: 500,
1013 scope: "default",
1014 scroll: true,
1015 scrollSensitivity: 20,
1016 scrollSpeed: 20,
1017 snap: false,
1018 snapMode: "both",
1019 snapTolerance: 20,
1020 stack: false,
1021 zIndex: false
1022 },
1023 _create: function() {
1024
1025 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
1026 this.element[0].style.position = 'relative';
1027
1028 (this.options.addClasses && this.element.addClass("ui-draggable"));
1029 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
1030
1031 this._mouseInit();
1032
1033 },
1034
1035 destroy: function() {
1036 if(!this.element.data('draggable')) return;
1037 this.element
1038 .removeData("draggable")
1039 .unbind(".draggable")
1040 .removeClass("ui-draggable"
1041 + " ui-draggable-dragging"
1042 + " ui-draggable-disabled");
1043 this._mouseDestroy();
1044
1045 return this;
1046 },
1047
1048 _mouseCapture: function(event) {
1049
1050 var o = this.options;
1051
1052 // among others, prevent a drag on a resizable-handle
1053 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
1054 return false;
1055
1056 //Quit if we're not on a valid handle
1057 this.handle = this._getHandle(event);
1058 if (!this.handle)
1059 return false;
1060
1061 return true;
1062
1063 },
1064
1065 _mouseStart: function(event) {
1066
1067 var o = this.options;
1068
1069 //Create and append the visible helper
1070 this.helper = this._createHelper(event);
1071
1072 //Cache the helper size
1073 this._cacheHelperProportions();
1074
1075 //If ddmanager is used for droppables, set the global draggable
1076 if($.ui.ddmanager)
1077 $.ui.ddmanager.current = this;
1078
1079 /*
1080 * - Position generation -
1081 * This block generates everything position related - it's the core of draggables.
1082 */
1083
1084 //Cache the margins of the original element
1085 this._cacheMargins();
1086
1087 //Store the helper's css position
1088 this.cssPosition = this.helper.css("position");
1089 this.scrollParent = this.helper.scrollParent();
1090
1091 //The element's absolute position on the page minus margins
1092 this.offset = this.positionAbs = this.element.offset();
1093 this.offset = {
1094 top: this.offset.top - this.margins.top,
1095 left: this.offset.left - this.margins.left
1096 };
1097
1098 $.extend(this.offset, {
1099 click: { //Where the click happened, relative to the element
1100 left: event.pageX - this.offset.left,
1101 top: event.pageY - this.offset.top
1102 },
1103 parent: this._getParentOffset(),
1104 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
1105 });
1106
1107 //Generate the original position
1108 this.originalPosition = this.position = this._generatePosition(event);
1109 this.originalPageX = event.pageX;
1110 this.originalPageY = event.pageY;
1111
1112 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
1113 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
1114
1115 //Set a containment if given in the options
1116 if(o.containment)
1117 this._setContainment();
1118
1119 //Trigger event + callbacks
1120 if(this._trigger("start", event) === false) {
1121 this._clear();
1122 return false;
1123 }
1124
1125 //Recache the helper size
1126 this._cacheHelperProportions();
1127
1128 //Prepare the droppable offsets
1129 if ($.ui.ddmanager && !o.dropBehaviour)
1130 $.ui.ddmanager.prepareOffsets(this, event);
1131
1132 this.helper.addClass("ui-draggable-dragging");
1133 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
1134 return true;
1135 },
1136
1137 _mouseDrag: function(event, noPropagation) {
1138
1139 //Compute the helpers position
1140 this.position = this._generatePosition(event);
1141 this.positionAbs = this._convertPositionTo("absolute");
1142
1143 //Call plugins and callbacks and use the resulting position if something is returned
1144 if (!noPropagation) {
1145 var ui = this._uiHash();
1146 if(this._trigger('drag', event, ui) === false) {
1147 this._mouseUp({});
1148 return false;
1149 }
1150 this.position = ui.position;
1151 }
1152
1153 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
1154 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
1155 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
1156
1157 return false;
1158 },
1159
1160 _mouseStop: function(event) {
1161
1162 //If we are using droppables, inform the manager about the drop
1163 var dropped = false;
1164 if ($.ui.ddmanager && !this.options.dropBehaviour)
1165 dropped = $.ui.ddmanager.drop(this, event);
1166
1167 //if a drop comes from outside (a sortable)
1168 if(this.dropped) {
1169 dropped = this.dropped;
1170 this.dropped = false;
1171 }
1172
1173 //if the original element is removed, don't bother to continue if helper is set to "original"
1174 if((!this.element[0] || !this.element[0].parentNode) && this.options.helper == "original")
1175 return false;
1176
1177 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))) {
1178 var self = this;
1179 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
1180 if(self._trigger("stop", event) !== false) {
1181 self._clear();
1182 }
1183 });
1184 } else {
1185 if(this._trigger("stop", event) !== false) {
1186 this._clear();
1187 }
1188 }
1189
1190 return false;
1191 },
1192
1193 cancel: function() {
1194
1195 if(this.helper.is(".ui-draggable-dragging")) {
1196 this._mouseUp({});
1197 } else {
1198 this._clear();
1199 }
1200
1201 return this;
1202
1203 },
1204
1205 _getHandle: function(event) {
1206
1207 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
1208 $(this.options.handle, this.element)
1209 .find("*")
1210 .andSelf()
1211 .each(function() {
1212 if(this == event.target) handle = true;
1213 });
1214
1215 return handle;
1216
1217 },
1218
1219 _createHelper: function(event) {
1220
1221 var o = this.options;
1222 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
1223
1224 if(!helper.parents('body').length)
1225 helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
1226
1227 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
1228 helper.css("position", "absolute");
1229
1230 return helper;
1231
1232 },
1233
1234 _adjustOffsetFromHelper: function(obj) {
1235 if (typeof obj == 'string') {
1236 obj = obj.split(' ');
1237 }
1238 if ($.isArray(obj)) {
1239 obj = {left: +obj[0], top: +obj[1] || 0};
1240 }
1241 if ('left' in obj) {
1242 this.offset.click.left = obj.left + this.margins.left;
1243 }
1244 if ('right' in obj) {
1245 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1246 }
1247 if ('top' in obj) {
1248 this.offset.click.top = obj.top + this.margins.top;
1249 }
1250 if ('bottom' in obj) {
1251 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1252 }
1253 },
1254
1255 _getParentOffset: function() {
1256
1257 //Get the offsetParent and cache its position
1258 this.offsetParent = this.helper.offsetParent();
1259 var po = this.offsetParent.offset();
1260
1261 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1262 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1263 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1264 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1265 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
1266 po.left += this.scrollParent.scrollLeft();
1267 po.top += this.scrollParent.scrollTop();
1268 }
1269
1270 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
1271 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
1272 po = { top: 0, left: 0 };
1273
1274 return {
1275 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1276 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1277 };
1278
1279 },
1280
1281 _getRelativeOffset: function() {
1282
1283 if(this.cssPosition == "relative") {
1284 var p = this.element.position();
1285 return {
1286 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1287 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1288 };
1289 } else {
1290 return { top: 0, left: 0 };
1291 }
1292
1293 },
1294
1295 _cacheMargins: function() {
1296 this.margins = {
1297 left: (parseInt(this.element.css("marginLeft"),10) || 0),
1298 top: (parseInt(this.element.css("marginTop"),10) || 0),
1299 right: (parseInt(this.element.css("marginRight"),10) || 0),
1300 bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
1301 };
1302 },
1303
1304 _cacheHelperProportions: function() {
1305 this.helperProportions = {
1306 width: this.helper.outerWidth(),
1307 height: this.helper.outerHeight()
1308 };
1309 },
1310
1311 _setContainment: function() {
1312
1313 var o = this.options;
1314 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
1315 if(o.containment == 'document' || o.containment == 'window') this.containment = [
1316 (o.containment == 'document' ? 0 : $(window).scrollLeft()) - this.offset.relative.left - this.offset.parent.left,
1317 (o.containment == 'document' ? 0 : $(window).scrollTop()) - this.offset.relative.top - this.offset.parent.top,
1318 (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
1319 (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
1320 ];
1321
1322 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
1323 var ce = $(o.containment)[0]; if(!ce) return;
1324 var co = $(o.containment).offset();
1325 var over = ($(ce).css("overflow") != 'hidden');
1326
1327 this.containment = [
1328 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
1329 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
1330 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 - this.margins.right,
1331 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 - this.margins.bottom
1332 ];
1333 } else if(o.containment.constructor == Array) {
1334 this.containment = o.containment;
1335 }
1336
1337 },
1338
1339 _convertPositionTo: function(d, pos) {
1340
1341 if(!pos) pos = this.position;
1342 var mod = d == "absolute" ? 1 : -1;
1343 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);
1344
1345 return {
1346 top: (
1347 pos.top // The absolute mouse position
1348 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1349 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
1350 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
1351 ),
1352 left: (
1353 pos.left // The absolute mouse position
1354 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1355 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
1356 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
1357 )
1358 };
1359
1360 },
1361
1362 _generatePosition: function(event) {
1363
1364 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);
1365 var pageX = event.pageX;
1366 var pageY = event.pageY;
1367
1368 /*
1369 * - Position constraining -
1370 * Constrain the position to a mix of grid, containment.
1371 */
1372
1373 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
1374
1375 if(this.containment) {
1376 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
1377 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
1378 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
1379 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
1380 }
1381
1382 if(o.grid) {
1383 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
1384 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;
1385
1386 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
1387 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;
1388 }
1389
1390 }
1391
1392 return {
1393 top: (
1394 pageY // The absolute mouse position
1395 - this.offset.click.top // Click offset (relative to the element)
1396 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
1397 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
1398 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
1399 ),
1400 left: (
1401 pageX // The absolute mouse position
1402 - this.offset.click.left // Click offset (relative to the element)
1403 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
1404 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
1405 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
1406 )
1407 };
1408
1409 },
1410
1411 _clear: function() {
1412 this.helper.removeClass("ui-draggable-dragging");
1413 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
1414 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
1415 this.helper = null;
1416 this.cancelHelperRemoval = false;
1417 },
1418
1419 // From now on bulk stuff - mainly helpers
1420
1421 _trigger: function(type, event, ui) {
1422 ui = ui || this._uiHash();
1423 $.ui.plugin.call(this, type, [event, ui]);
1424 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
1425 return $.Widget.prototype._trigger.call(this, type, event, ui);
1426 },
1427
1428 plugins: {},
1429
1430 _uiHash: function(event) {
1431 return {
1432 helper: this.helper,
1433 position: this.position,
1434 originalPosition: this.originalPosition,
1435 offset: this.positionAbs
1436 };
1437 }
1438
1439 });
1440
1441 $.extend($.ui.draggable, {
1442 version: "1.8.11"
1443 });
1444
1445 $.ui.plugin.add("draggable", "connectToSortable", {
1446 start: function(event, ui) {
1447
1448 var inst = $(this).data("draggable"), o = inst.options,
1449 uiSortable = $.extend({}, ui, { item: inst.element });
1450 inst.sortables = [];
1451 $(o.connectToSortable).each(function() {
1452 var sortable = $.data(this, 'sortable');
1453 if (sortable && !sortable.options.disabled) {
1454 inst.sortables.push({
1455 instance: sortable,
1456 shouldRevert: sortable.options.revert
1457 });
1458 sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
1459 sortable._trigger("activate", event, uiSortable);
1460 }
1461 });
1462
1463 },
1464 stop: function(event, ui) {
1465
1466 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1467 var inst = $(this).data("draggable"),
1468 uiSortable = $.extend({}, ui, { item: inst.element });
1469
1470 $.each(inst.sortables, function() {
1471 if(this.instance.isOver) {
1472
1473 this.instance.isOver = 0;
1474
1475 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
1476 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1477
1478 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
1479 if(this.shouldRevert) this.instance.options.revert = true;
1480
1481 //Trigger the stop of the sortable
1482 this.instance._mouseStop(event);
1483
1484 this.instance.options.helper = this.instance.options._helper;
1485
1486 //If the helper has been the original item, restore properties in the sortable
1487 if(inst.options.helper == 'original')
1488 this.instance.currentItem.css({ top: 'auto', left: 'auto' });
1489
1490 } else {
1491 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1492 this.instance._trigger("deactivate", event, uiSortable);
1493 }
1494
1495 });
1496
1497 },
1498 drag: function(event, ui) {
1499
1500 var inst = $(this).data("draggable"), self = this;
1501
1502 var checkPos = function(o) {
1503 var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
1504 var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
1505 var itemHeight = o.height, itemWidth = o.width;
1506 var itemTop = o.top, itemLeft = o.left;
1507
1508 return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
1509 };
1510
1511 $.each(inst.sortables, function(i) {
1512
1513 //Copy over some variables to allow calling the sortable's native _intersectsWith
1514 this.instance.positionAbs = inst.positionAbs;
1515 this.instance.helperProportions = inst.helperProportions;
1516 this.instance.offset.click = inst.offset.click;
1517
1518 if(this.instance._intersectsWith(this.instance.containerCache)) {
1519
1520 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1521 if(!this.instance.isOver) {
1522
1523 this.instance.isOver = 1;
1524 //Now we fake the start of dragging for the sortable instance,
1525 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1526 //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)
1527 this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
1528 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1529 this.instance.options.helper = function() { return ui.helper[0]; };
1530
1531 event.target = this.instance.currentItem[0];
1532 this.instance._mouseCapture(event, true);
1533 this.instance._mouseStart(event, true, true);
1534
1535 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1536 this.instance.offset.click.top = inst.offset.click.top;
1537 this.instance.offset.click.left = inst.offset.click.left;
1538 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1539 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1540
1541 inst._trigger("toSortable", event);
1542 inst.dropped = this.instance.element; //draggable revert needs that
1543 //hack so receive/update callbacks work (mostly)
1544 inst.currentItem = inst.element;
1545 this.instance.fromOutside = inst;
1546
1547 }
1548
1549 //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
1550 if(this.instance.currentItem) this.instance._mouseDrag(event);
1551
1552 } else {
1553
1554 //If it doesn't intersect with the sortable, and it intersected before,
1555 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1556 if(this.instance.isOver) {
1557
1558 this.instance.isOver = 0;
1559 this.instance.cancelHelperRemoval = true;
1560
1561 //Prevent reverting on this forced stop
1562 this.instance.options.revert = false;
1563
1564 // The out event needs to be triggered independently
1565 this.instance._trigger('out', event, this.instance._uiHash(this.instance));
1566
1567 this.instance._mouseStop(event, true);
1568 this.instance.options.helper = this.instance.options._helper;
1569
1570 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1571 this.instance.currentItem.remove();
1572 if(this.instance.placeholder) this.instance.placeholder.remove();
1573
1574 inst._trigger("fromSortable", event);
1575 inst.dropped = false; //draggable revert needs that
1576 }
1577
1578 };
1579
1580 });
1581
1582 }
1583 });
1584
1585 $.ui.plugin.add("draggable", "cursor", {
1586 start: function(event, ui) {
1587 var t = $('body'), o = $(this).data('draggable').options;
1588 if (t.css("cursor")) o._cursor = t.css("cursor");
1589 t.css("cursor", o.cursor);
1590 },
1591 stop: function(event, ui) {
1592 var o = $(this).data('draggable').options;
1593 if (o._cursor) $('body').css("cursor", o._cursor);
1594 }
1595 });
1596
1597 $.ui.plugin.add("draggable", "iframeFix", {
1598 start: function(event, ui) {
1599 var o = $(this).data('draggable').options;
1600 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1601 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
1602 .css({
1603 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
1604 position: "absolute", opacity: "0.001", zIndex: 1000
1605 })
1606 .css($(this).offset())
1607 .appendTo("body");
1608 });
1609 },
1610 stop: function(event, ui) {
1611 $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
1612 }
1613 });
1614
1615 $.ui.plugin.add("draggable", "opacity", {
1616 start: function(event, ui) {
1617 var t = $(ui.helper), o = $(this).data('draggable').options;
1618 if(t.css("opacity")) o._opacity = t.css("opacity");
1619 t.css('opacity', o.opacity);
1620 },
1621 stop: function(event, ui) {
1622 var o = $(this).data('draggable').options;
1623 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
1624 }
1625 });
1626
1627 $.ui.plugin.add("draggable", "scroll", {
1628 start: function(event, ui) {
1629 var i = $(this).data("draggable");
1630 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
1631 },
1632 drag: function(event, ui) {
1633
1634 var i = $(this).data("draggable"), o = i.options, scrolled = false;
1635
1636 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
1637
1638 if(!o.axis || o.axis != 'x') {
1639 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
1640 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1641 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
1642 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1643 }
1644
1645 if(!o.axis || o.axis != 'y') {
1646 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
1647 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1648 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
1649 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1650 }
1651
1652 } else {
1653
1654 if(!o.axis || o.axis != 'x') {
1655 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
1656 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1657 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
1658 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1659 }
1660
1661 if(!o.axis || o.axis != 'y') {
1662 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
1663 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1664 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
1665 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1666 }
1667
1668 }
1669
1670 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
1671 $.ui.ddmanager.prepareOffsets(i, event);
1672
1673 }
1674 });
1675
1676 $.ui.plugin.add("draggable", "snap", {
1677 start: function(event, ui) {
1678
1679 var i = $(this).data("draggable"), o = i.options;
1680 i.snapElements = [];
1681
1682 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
1683 var $t = $(this); var $o = $t.offset();
1684 if(this != i.element[0]) i.snapElements.push({
1685 item: this,
1686 width: $t.outerWidth(), height: $t.outerHeight(),
1687 top: $o.top, left: $o.left
1688 });
1689 });
1690
1691 },
1692 drag: function(event, ui) {
1693
1694 var inst = $(this).data("draggable"), o = inst.options;
1695 var d = o.snapTolerance;
1696
1697 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
1698 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
1699
1700 for (var i = inst.snapElements.length - 1; i >= 0; i--){
1701
1702 var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
1703 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
1704
1705 //Yes, I know, this is insane ;)
1706 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))) {
1707 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 })));
1708 inst.snapElements[i].snapping = false;
1709 continue;
1710 }
1711
1712 if(o.snapMode != 'inner') {
1713 var ts = Math.abs(t - y2) <= d;
1714 var bs = Math.abs(b - y1) <= d;
1715 var ls = Math.abs(l - x2) <= d;
1716 var rs = Math.abs(r - x1) <= d;
1717 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1718 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1719 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1720 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1721 }
1722
1723 var first = (ts || bs || ls || rs);
1724
1725 if(o.snapMode != 'outer') {
1726 var ts = Math.abs(t - y1) <= d;
1727 var bs = Math.abs(b - y2) <= d;
1728 var ls = Math.abs(l - x1) <= d;
1729 var rs = Math.abs(r - x2) <= d;
1730 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1731 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1732 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1733 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1734 }
1735
1736 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
1737 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1738 inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1739
1740 };
1741
1742 }
1743 });
1744
1745 $.ui.plugin.add("draggable", "stack", {
1746 start: function(event, ui) {
1747
1748 var o = $(this).data("draggable").options;
1749
1750 var group = $.makeArray($(o.stack)).sort(function(a,b) {
1751 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
1752 });
1753 if (!group.length) { return; }
1754
1755 var min = parseInt(group[0].style.zIndex) || 0;
1756 $(group).each(function(i) {
1757 this.style.zIndex = min + i;
1758 });
1759
1760 this[0].style.zIndex = min + group.length;
1761
1762 }
1763 });
1764
1765 $.ui.plugin.add("draggable", "zIndex", {
1766 start: function(event, ui) {
1767 var t = $(ui.helper), o = $(this).data("draggable").options;
1768 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
1769 t.css('zIndex', o.zIndex);
1770 },
1771 stop: function(event, ui) {
1772 var o = $(this).data("draggable").options;
1773 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
1774 }
1775 });
1776
1777 })(jQuery);
1778 /*
1779 * jQuery UI Droppable 1.8.11
1780 *
1781 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
1782 * Dual licensed under the MIT or GPL Version 2 licenses.
1783 * http://jquery.org/license
1784 *
1785 * http://docs.jquery.com/UI/Droppables
1786 *
1787 * Depends:
1788 * jquery.ui.core.js
1789 * jquery.ui.widget.js
1790 * jquery.ui.mouse.js
1791 * jquery.ui.draggable.js
1792 */
1793 (function( $, undefined ) {
1794
1795 $.widget("ui.droppable", {
1796 widgetEventPrefix: "drop",
1797 options: {
1798 accept: '*',
1799 activeClass: false,
1800 addClasses: true,
1801 greedy: false,
1802 hoverClass: false,
1803 scope: 'default',
1804 tolerance: 'intersect'
1805 },
1806 _create: function() {
1807
1808 var o = this.options, accept = o.accept;
1809 this.isover = 0; this.isout = 1;
1810
1811 this.accept = $.isFunction(accept) ? accept : function(d) {
1812 return d.is(accept);
1813 };
1814
1815 //Store the droppable's proportions
1816 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
1817
1818 // Add the reference and positions to the manager
1819 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
1820 $.ui.ddmanager.droppables[o.scope].push(this);
1821
1822 (o.addClasses && this.element.addClass("ui-droppable"));
1823
1824 },
1825
1826 destroy: function() {
1827 var drop = $.ui.ddmanager.droppables[this.options.scope];
1828 for ( var i = 0; i < drop.length; i++ )
1829 if ( drop[i] == this )
1830 drop.splice(i, 1);
1831
1832 this.element
1833 .removeClass("ui-droppable ui-droppable-disabled")
1834 .removeData("droppable")
1835 .unbind(".droppable");
1836
1837 return this;
1838 },
1839
1840 _setOption: function(key, value) {
1841
1842 if(key == 'accept') {
1843 this.accept = $.isFunction(value) ? value : function(d) {
1844 return d.is(value);
1845 };
1846 }
1847 $.Widget.prototype._setOption.apply(this, arguments);
1848 },
1849
1850 _activate: function(event) {
1851 var draggable = $.ui.ddmanager.current;
1852 if(this.options.activeClass) this.element.addClass(this.options.activeClass);
1853 (draggable && this._trigger('activate', event, this.ui(draggable)));
1854 },
1855
1856 _deactivate: function(event) {
1857 var draggable = $.ui.ddmanager.current;
1858 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1859 (draggable && this._trigger('deactivate', event, this.ui(draggable)));
1860 },
1861
1862 _over: function(event) {
1863
1864 var draggable = $.ui.ddmanager.current;
1865 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1866
1867 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1868 if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
1869 this._trigger('over', event, this.ui(draggable));
1870 }
1871
1872 },
1873
1874 _out: function(event) {
1875
1876 var draggable = $.ui.ddmanager.current;
1877 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1878
1879 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1880 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1881 this._trigger('out', event, this.ui(draggable));
1882 }
1883
1884 },
1885
1886 _drop: function(event,custom) {
1887
1888 var draggable = custom || $.ui.ddmanager.current;
1889 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
1890
1891 var childrenIntersection = false;
1892 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
1893 var inst = $.data(this, 'droppable');
1894 if(
1895 inst.options.greedy
1896 && !inst.options.disabled
1897 && inst.options.scope == draggable.options.scope
1898 && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
1899 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
1900 ) { childrenIntersection = true; return false; }
1901 });
1902 if(childrenIntersection) return false;
1903
1904 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1905 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1906 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1907 this._trigger('drop', event, this.ui(draggable));
1908 return this.element;
1909 }
1910
1911 return false;
1912
1913 },
1914
1915 ui: function(c) {
1916 return {
1917 draggable: (c.currentItem || c.element),
1918 helper: c.helper,
1919 position: c.position,
1920 offset: c.positionAbs
1921 };
1922 }
1923
1924 });
1925
1926 $.extend($.ui.droppable, {
1927 version: "1.8.11"
1928 });
1929
1930 $.ui.intersect = function(draggable, droppable, toleranceMode) {
1931
1932 if (!droppable.offset) return false;
1933
1934 var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
1935 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
1936 var l = droppable.offset.left, r = l + droppable.proportions.width,
1937 t = droppable.offset.top, b = t + droppable.proportions.height;
1938
1939 switch (toleranceMode) {
1940 case 'fit':
1941 return (l <= x1 && x2 <= r
1942 && t <= y1 && y2 <= b);
1943 break;
1944 case 'intersect':
1945 return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
1946 && x2 - (draggable.helperProportions.width / 2) < r // Left Half
1947 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
1948 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
1949 break;
1950 case 'pointer':
1951 var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
1952 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
1953 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
1954 return isOver;
1955 break;
1956 case 'touch':
1957 return (
1958 (y1 >= t && y1 <= b) || // Top edge touching
1959 (y2 >= t && y2 <= b) || // Bottom edge touching
1960 (y1 < t && y2 > b) // Surrounded vertically
1961 ) && (
1962 (x1 >= l && x1 <= r) || // Left edge touching
1963 (x2 >= l && x2 <= r) || // Right edge touching
1964 (x1 < l && x2 > r) // Surrounded horizontally
1965 );
1966 break;
1967 default:
1968 return false;
1969 break;
1970 }
1971
1972 };
1973
1974 /*
1975 This manager tracks offsets of draggables and droppables
1976 */
1977 $.ui.ddmanager = {
1978 current: null,
1979 droppables: { 'default': [] },
1980 prepareOffsets: function(t, event) {
1981
1982 var m = $.ui.ddmanager.droppables[t.options.scope] || [];
1983 var type = event ? event.type : null; // workaround for #2317
1984 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
1985
1986 droppablesLoop: for (var i = 0; i < m.length; i++) {
1987
1988 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted
1989 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
1990 m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue
1991
1992 if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
1993
1994 m[i].offset = m[i].element.offset();
1995 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
1996
1997 }
1998
1999 },
2000 drop: function(draggable, event) {
2001
2002 var dropped = false;
2003 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
2004
2005 if(!this.options) return;
2006 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
2007 dropped = dropped || this._drop.call(this, event);
2008
2009 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2010 this.isout = 1; this.isover = 0;
2011 this._deactivate.call(this, event);
2012 }
2013
2014 });
2015 return dropped;
2016
2017 },
2018 drag: function(draggable, event) {
2019
2020 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
2021 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
2022
2023 //Run through all droppables and check their positions based on specific tolerance options
2024 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
2025
2026 if(this.options.disabled || this.greedyChild || !this.visible) return;
2027 var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
2028
2029 var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
2030 if(!c) return;
2031
2032 var parentInstance;
2033 if (this.options.greedy) {
2034 var parent = this.element.parents(':data(droppable):eq(0)');
2035 if (parent.length) {
2036 parentInstance = $.data(parent[0], 'droppable');
2037 parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
2038 }
2039 }
2040
2041 // we just moved into a greedy child
2042 if (parentInstance && c == 'isover') {
2043 parentInstance['isover'] = 0;
2044 parentInstance['isout'] = 1;
2045 parentInstance._out.call(parentInstance, event);
2046 }
2047
2048 this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
2049 this[c == "isover" ? "_over" : "_out"].call(this, event);
2050
2051 // we just moved out of a greedy child
2052 if (parentInstance && c == 'isout') {
2053 parentInstance['isout'] = 0;
2054 parentInstance['isover'] = 1;
2055 parentInstance._over.call(parentInstance, event);
2056 }
2057 });
2058
2059 }
2060 };
2061
2062 })(jQuery);
2063 /*
2064 * jQuery UI Resizable 1.8.11
2065 *
2066 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
2067 * Dual licensed under the MIT or GPL Version 2 licenses.
2068 * http://jquery.org/license
2069 *
2070 * http://docs.jquery.com/UI/Resizables
2071 *
2072 * Depends:
2073 * jquery.ui.core.js
2074 * jquery.ui.mouse.js
2075 * jquery.ui.widget.js
2076 */
2077 (function( $, undefined ) {
2078
2079 $.widget("ui.resizable", $.ui.mouse, {
2080 widgetEventPrefix: "resize",
2081 options: {
2082 alsoResize: false,
2083 animate: false,
2084 animateDuration: "slow",
2085 animateEasing: "swing",
2086 aspectRatio: false,
2087 autoHide: false,
2088 containment: false,
2089 ghost: false,
2090 grid: false,
2091 handles: "e,s,se",
2092 helper: false,
2093 maxHeight: null,
2094 maxWidth: null,
2095 minHeight: 10,
2096 minWidth: 10,
2097 zIndex: 1000
2098 },
2099 _create: function() {
2100
2101 var self = this, o = this.options;
2102 this.element.addClass("ui-resizable");
2103
2104 $.extend(this, {
2105 _aspectRatio: !!(o.aspectRatio),
2106 aspectRatio: o.aspectRatio,
2107 originalElement: this.element,
2108 _proportionallyResizeElements: [],
2109 _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
2110 });
2111
2112 //Wrap the element if it cannot hold child nodes
2113 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
2114
2115 //Opera fix for relative positioning
2116 if (/relative/.test(this.element.css('position')) && $.browser.opera)
2117 this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
2118
2119 //Create a wrapper element and set the wrapper to the new current internal element
2120 this.element.wrap(
2121 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
2122 position: this.element.css('position'),
2123 width: this.element.outerWidth(),
2124 height: this.element.outerHeight(),
2125 top: this.element.css('top'),
2126 left: this.element.css('left')
2127 })
2128 );
2129
2130 //Overwrite the original this.element
2131 this.element = this.element.parent().data(
2132 "resizable", this.element.data('resizable')
2133 );
2134
2135 this.elementIsWrapper = true;
2136
2137 //Move margins to the wrapper
2138 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
2139 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
2140
2141 //Prevent Safari textarea resize
2142 this.originalResizeStyle = this.originalElement.css('resize');
2143 this.originalElement.css('resize', 'none');
2144
2145 //Push the actual element to our proportionallyResize internal array
2146 this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
2147
2148 // avoid IE jump (hard set the margin)
2149 this.originalElement.css({ margin: this.originalElement.css('margin') });
2150
2151 // fix handlers offset
2152 this._proportionallyResize();
2153
2154 }
2155
2156 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' });
2157 if(this.handles.constructor == String) {
2158
2159 if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
2160 var n = this.handles.split(","); this.handles = {};
2161
2162 for(var i = 0; i < n.length; i++) {
2163
2164 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
2165 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
2166
2167 // increase zIndex of sw, se, ne, nw axis
2168 //TODO : this modifies original option
2169 if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
2170
2171 //TODO : What's going on here?
2172 if ('se' == handle) {
2173 axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
2174 };
2175
2176 //Insert into internal handles object and append to element
2177 this.handles[handle] = '.ui-resizable-'+handle;
2178 this.element.append(axis);
2179 }
2180
2181 }
2182
2183 this._renderAxis = function(target) {
2184
2185 target = target || this.element;
2186
2187 for(var i in this.handles) {
2188
2189 if(this.handles[i].constructor == String)
2190 this.handles[i] = $(this.handles[i], this.element).show();
2191
2192 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
2193 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
2194
2195 var axis = $(this.handles[i], this.element), padWrapper = 0;
2196
2197 //Checking the correct pad and border
2198 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
2199
2200 //The padding type i have to apply...
2201 var padPos = [ 'padding',
2202 /ne|nw|n/.test(i) ? 'Top' :
2203 /se|sw|s/.test(i) ? 'Bottom' :
2204 /^e$/.test(i) ? 'Right' : 'Left' ].join("");
2205
2206 target.css(padPos, padWrapper);
2207
2208 this._proportionallyResize();
2209
2210 }
2211
2212 //TODO: What's that good for? There's not anything to be executed left
2213 if(!$(this.handles[i]).length)
2214 continue;
2215
2216 }
2217 };
2218
2219 //TODO: make renderAxis a prototype function
2220 this._renderAxis(this.element);
2221
2222 this._handles = $('.ui-resizable-handle', this.element)
2223 .disableSelection();
2224
2225 //Matching axis name
2226 this._handles.mouseover(function() {
2227 if (!self.resizing) {
2228 if (this.className)
2229 var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
2230 //Axis, default = se
2231 self.axis = axis && axis[1] ? axis[1] : 'se';
2232 }
2233 });
2234
2235 //If we want to auto hide the elements
2236 if (o.autoHide) {
2237 this._handles.hide();
2238 $(this.element)
2239 .addClass("ui-resizable-autohide")
2240 .hover(function() {
2241 $(this).removeClass("ui-resizable-autohide");
2242 self._handles.show();
2243 },
2244 function(){
2245 if (!self.resizing) {
2246 $(this).addClass("ui-resizable-autohide");
2247 self._handles.hide();
2248 }
2249 });
2250 }
2251
2252 //Initialize the mouse interaction
2253 this._mouseInit();
2254
2255 },
2256
2257 destroy: function() {
2258
2259 this._mouseDestroy();
2260
2261 var _destroy = function(exp) {
2262 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
2263 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
2264 };
2265
2266 //TODO: Unwrap at same DOM position
2267 if (this.elementIsWrapper) {
2268 _destroy(this.element);
2269 var wrapper = this.element;
2270 wrapper.after(
2271 this.originalElement.css({
2272 position: wrapper.css('position'),
2273 width: wrapper.outerWidth(),
2274 height: wrapper.outerHeight(),
2275 top: wrapper.css('top'),
2276 left: wrapper.css('left')
2277 })
2278 ).remove();
2279 }
2280
2281 this.originalElement.css('resize', this.originalResizeStyle);
2282 _destroy(this.originalElement);
2283
2284 return this;
2285 },
2286
2287 _mouseCapture: function(event) {
2288 var handle = false;
2289 for (var i in this.handles) {
2290 if ($(this.handles[i])[0] == event.target) {
2291 handle = true;
2292 }
2293 }
2294
2295 return !this.options.disabled && handle;
2296 },
2297
2298 _mouseStart: function(event) {
2299
2300 var o = this.options, iniPos = this.element.position(), el = this.element;
2301
2302 this.resizing = true;
2303 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
2304
2305 // bugfix for http://dev.jquery.com/ticket/1749
2306 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
2307 el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
2308 }
2309
2310 //Opera fixing relative position
2311 if ($.browser.opera && (/relative/).test(el.css('position')))
2312 el.css({ position: 'relative', top: 'auto', left: 'auto' });
2313
2314 this._renderProxy();
2315
2316 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
2317
2318 if (o.containment) {
2319 curleft += $(o.containment).scrollLeft() || 0;
2320 curtop += $(o.containment).scrollTop() || 0;
2321 }
2322
2323 //Store needed variables
2324 this.offset = this.helper.offset();
2325 this.position = { left: curleft, top: curtop };
2326 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2327 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
2328 this.originalPosition = { left: curleft, top: curtop };
2329 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
2330 this.originalMousePosition = { left: event.pageX, top: event.pageY };
2331
2332 //Aspect Ratio
2333 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
2334
2335 var cursor = $('.ui-resizable-' + this.axis).css('cursor');
2336 $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
2337
2338 el.addClass("ui-resizable-resizing");
2339 this._propagate("start", event);
2340 return true;
2341 },
2342
2343 _mouseDrag: function(event) {
2344
2345 //Increase performance, avoid regex
2346 var el = this.helper, o = this.options, props = {},
2347 self = this, smp = this.originalMousePosition, a = this.axis;
2348
2349 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
2350 var trigger = this._change[a];
2351 if (!trigger) return false;
2352
2353 // Calculate the attrs that will be change
2354 var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
2355
2356 if (this._aspectRatio || event.shiftKey)
2357 data = this._updateRatio(data, event);
2358
2359 data = this._respectSize(data, event);
2360
2361 // plugins callbacks need to be called first
2362 this._propagate("resize", event);
2363
2364 el.css({
2365 top: this.position.top + "px", left: this.position.left + "px",
2366 width: this.size.width + "px", height: this.size.height + "px"
2367 });
2368
2369 if (!this._helper && this._proportionallyResizeElements.length)
2370 this._proportionallyResize();
2371
2372 this._updateCache(data);
2373
2374 // calling the user callback at the end
2375 this._trigger('resize', event, this.ui());
2376
2377 return false;
2378 },
2379
2380 _mouseStop: function(event) {
2381
2382 this.resizing = false;
2383 var o = this.options, self = this;
2384
2385 if(this._helper) {
2386 var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2387 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2388 soffsetw = ista ? 0 : self.sizeDiff.width;
2389
2390 var s = { width: (self.helper.width() - soffsetw), height: (self.helper.height() - soffseth) },
2391 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2392 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2393
2394 if (!o.animate)
2395 this.element.css($.extend(s, { top: top, left: left }));
2396
2397 self.helper.height(self.size.height);
2398 self.helper.width(self.size.width);
2399
2400 if (this._helper && !o.animate) this._proportionallyResize();
2401 }
2402
2403 $('body').css('cursor', 'auto');
2404
2405 this.element.removeClass("ui-resizable-resizing");
2406
2407 this._propagate("stop", event);
2408
2409 if (this._helper) this.helper.remove();
2410 return false;
2411
2412 },
2413
2414 _updateCache: function(data) {
2415 var o = this.options;
2416 this.offset = this.helper.offset();
2417 if (isNumber(data.left)) this.position.left = data.left;
2418 if (isNumber(data.top)) this.position.top = data.top;
2419 if (isNumber(data.height)) this.size.height = data.height;
2420 if (isNumber(data.width)) this.size.width = data.width;
2421 },
2422
2423 _updateRatio: function(data, event) {
2424
2425 var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
2426
2427 if (data.height) data.width = (csize.height * this.aspectRatio);
2428 else if (data.width) data.height = (csize.width / this.aspectRatio);
2429
2430 if (a == 'sw') {
2431 data.left = cpos.left + (csize.width - data.width);
2432 data.top = null;
2433 }
2434 if (a == 'nw') {
2435 data.top = cpos.top + (csize.height - data.height);
2436 data.left = cpos.left + (csize.width - data.width);
2437 }
2438
2439 return data;
2440 },
2441
2442 _respectSize: function(data, event) {
2443
2444 var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
2445 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
2446 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
2447
2448 if (isminw) data.width = o.minWidth;
2449 if (isminh) data.height = o.minHeight;
2450 if (ismaxw) data.width = o.maxWidth;
2451 if (ismaxh) data.height = o.maxHeight;
2452
2453 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
2454 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
2455
2456 if (isminw && cw) data.left = dw - o.minWidth;
2457 if (ismaxw && cw) data.left = dw - o.maxWidth;
2458 if (isminh && ch) data.top = dh - o.minHeight;
2459 if (ismaxh && ch) data.top = dh - o.maxHeight;
2460
2461 // fixing jump error on top/left - bug #2330
2462 var isNotwh = !data.width && !data.height;
2463 if (isNotwh && !data.left && data.top) data.top = null;
2464 else if (isNotwh && !data.top && data.left) data.left = null;
2465
2466 return data;
2467 },
2468
2469 _proportionallyResize: function() {
2470
2471 var o = this.options;
2472 if (!this._proportionallyResizeElements.length) return;
2473 var element = this.helper || this.element;
2474
2475 for (var i=0; i < this._proportionallyResizeElements.length; i++) {
2476
2477 var prel = this._proportionallyResizeElements[i];
2478
2479 if (!this.borderDif) {
2480 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
2481 p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
2482
2483 this.borderDif = $.map(b, function(v, i) {
2484 var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
2485 return border + padding;
2486 });
2487 }
2488
2489 if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
2490 continue;
2491
2492 prel.css({
2493 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
2494 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
2495 });
2496
2497 };
2498
2499 },
2500
2501 _renderProxy: function() {
2502
2503 var el = this.element, o = this.options;
2504 this.elementOffset = el.offset();
2505
2506 if(this._helper) {
2507
2508 this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
2509
2510 // fix ie6 offset TODO: This seems broken
2511 var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
2512 pxyoffset = ( ie6 ? 2 : -1 );
2513
2514 this.helper.addClass(this._helper).css({
2515 width: this.element.outerWidth() + pxyoffset,
2516 height: this.element.outerHeight() + pxyoffset,
2517 position: 'absolute',
2518 left: this.elementOffset.left - ie6offset +'px',
2519 top: this.elementOffset.top - ie6offset +'px',
2520 zIndex: ++o.zIndex //TODO: Don't modify option
2521 });
2522
2523 this.helper
2524 .appendTo("body")
2525 .disableSelection();
2526
2527 } else {
2528 this.helper = this.element;
2529 }
2530
2531 },
2532
2533 _change: {
2534 e: function(event, dx, dy) {
2535 return { width: this.originalSize.width + dx };
2536 },
2537 w: function(event, dx, dy) {
2538 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2539 return { left: sp.left + dx, width: cs.width - dx };
2540 },
2541 n: function(event, dx, dy) {
2542 var o = this.options, cs = this.originalSize, sp = this.originalPosition;
2543 return { top: sp.top + dy, height: cs.height - dy };
2544 },
2545 s: function(event, dx, dy) {
2546 return { height: this.originalSize.height + dy };
2547 },
2548 se: function(event, dx, dy) {
2549 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2550 },
2551 sw: function(event, dx, dy) {
2552 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2553 },
2554 ne: function(event, dx, dy) {
2555 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
2556 },
2557 nw: function(event, dx, dy) {
2558 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
2559 }
2560 },
2561
2562 _propagate: function(n, event) {
2563 $.ui.plugin.call(this, n, [event, this.ui()]);
2564 (n != "resize" && this._trigger(n, event, this.ui()));
2565 },
2566
2567 plugins: {},
2568
2569 ui: function() {
2570 return {
2571 originalElement: this.originalElement,
2572 element: this.element,
2573 helper: this.helper,
2574 position: this.position,
2575 size: this.size,
2576 originalSize: this.originalSize,
2577 originalPosition: this.originalPosition
2578 };
2579 }
2580
2581 });
2582
2583 $.extend($.ui.resizable, {
2584 version: "1.8.11"
2585 });
2586
2587 /*
2588 * Resizable Extensions
2589 */
2590
2591 $.ui.plugin.add("resizable", "alsoResize", {
2592
2593 start: function (event, ui) {
2594 var self = $(this).data("resizable"), o = self.options;
2595
2596 var _store = function (exp) {
2597 $(exp).each(function() {
2598 var el = $(this);
2599 el.data("resizable-alsoresize", {
2600 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
2601 left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
2602 position: el.css('position') // to reset Opera on stop()
2603 });
2604 });
2605 };
2606
2607 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
2608 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
2609 else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
2610 }else{
2611 _store(o.alsoResize);
2612 }
2613 },
2614
2615 resize: function (event, ui) {
2616 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
2617
2618 var delta = {
2619 height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
2620 top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
2621 },
2622
2623 _alsoResize = function (exp, c) {
2624 $(exp).each(function() {
2625 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {},
2626 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
2627
2628 $.each(css, function (i, prop) {
2629 var sum = (start[prop]||0) + (delta[prop]||0);
2630 if (sum && sum >= 0)
2631 style[prop] = sum || null;
2632 });
2633
2634 // Opera fixing relative position
2635 if ($.browser.opera && /relative/.test(el.css('position'))) {
2636 self._revertToRelativePosition = true;
2637 el.css({ position: 'absolute', top: 'auto', left: 'auto' });
2638 }
2639
2640 el.css(style);
2641 });
2642 };
2643
2644 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2645 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
2646 }else{
2647 _alsoResize(o.alsoResize);
2648 }
2649 },
2650
2651 stop: function (event, ui) {
2652 var self = $(this).data("resizable"), o = self.options;
2653
2654 var _reset = function (exp) {
2655 $(exp).each(function() {
2656 var el = $(this);
2657 // reset position for Opera - no need to verify it was changed
2658 el.css({ position: el.data("resizable-alsoresize").position });
2659 });
2660 };
2661
2662 if (self._revertToRelativePosition) {
2663 self._revertToRelativePosition = false;
2664 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
2665 $.each(o.alsoResize, function (exp) { _reset(exp); });
2666 }else{
2667 _reset(o.alsoResize);
2668 }
2669 }
2670
2671 $(this).removeData("resizable-alsoresize");
2672 }
2673 });
2674
2675 $.ui.plugin.add("resizable", "animate", {
2676
2677 stop: function(event, ui) {
2678 var self = $(this).data("resizable"), o = self.options;
2679
2680 var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
2681 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
2682 soffsetw = ista ? 0 : self.sizeDiff.width;
2683
2684 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
2685 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
2686 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
2687
2688 self.element.animate(
2689 $.extend(style, top && left ? { top: top, left: left } : {}), {
2690 duration: o.animateDuration,
2691 easing: o.animateEasing,
2692 step: function() {
2693
2694 var data = {
2695 width: parseInt(self.element.css('width'), 10),
2696 height: parseInt(self.element.css('height'), 10),
2697 top: parseInt(self.element.css('top'), 10),
2698 left: parseInt(self.element.css('left'), 10)
2699 };
2700
2701 if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
2702
2703 // propagating resize, and updating values for each animation step
2704 self._updateCache(data);
2705 self._propagate("resize", event);
2706
2707 }
2708 }
2709 );
2710 }
2711
2712 });
2713
2714 $.ui.plugin.add("resizable", "containment", {
2715
2716 start: function(event, ui) {
2717 var self = $(this).data("resizable"), o = self.options, el = self.element;
2718 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
2719 if (!ce) return;
2720
2721 self.containerElement = $(ce);
2722
2723 if (/document/.test(oc) || oc == document) {
2724 self.containerOffset = { left: 0, top: 0 };
2725 self.containerPosition = { left: 0, top: 0 };
2726
2727 self.parentData = {
2728 element: $(document), left: 0, top: 0,
2729 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
2730 };
2731 }
2732
2733 // i'm a node, so compute top, left, right, bottom
2734 else {
2735 var element = $(ce), p = [];
2736 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
2737
2738 self.containerOffset = element.offset();
2739 self.containerPosition = element.position();
2740 self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
2741
2742 var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width,
2743 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
2744
2745 self.parentData = {
2746 element: ce, left: co.left, top: co.top, width: width, height: height
2747 };
2748 }
2749 },
2750
2751 resize: function(event, ui) {
2752 var self = $(this).data("resizable"), o = self.options,
2753 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
2754 pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
2755
2756 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
2757
2758 if (cp.left < (self._helper ? co.left : 0)) {
2759 self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
2760 if (pRatio) self.size.height = self.size.width / o.aspectRatio;
2761 self.position.left = o.helper ? co.left : 0;
2762 }
2763
2764 if (cp.top < (self._helper ? co.top : 0)) {
2765 self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
2766 if (pRatio) self.size.width = self.size.height * o.aspectRatio;
2767 self.position.top = self._helper ? co.top : 0;
2768 }
2769
2770 self.offset.left = self.parentData.left+self.position.left;
2771 self.offset.top = self.parentData.top+self.position.top;
2772
2773 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
2774 hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
2775
2776 var isParent = self.containerElement.get(0) == self.element.parent().get(0),
2777 isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
2778
2779 if(isParent && isOffsetRelative) woset -= self.parentData.left;
2780
2781 if (woset + self.size.width >= self.parentData.width) {
2782 self.size.width = self.parentData.width - woset;
2783 if (pRatio) self.size.height = self.size.width / self.aspectRatio;
2784 }
2785
2786 if (hoset + self.size.height >= self.parentData.height) {
2787 self.size.height = self.parentData.height - hoset;
2788 if (pRatio) self.size.width = self.size.height * self.aspectRatio;
2789 }
2790 },
2791
2792 stop: function(event, ui){
2793 var self = $(this).data("resizable"), o = self.options, cp = self.position,
2794 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
2795
2796 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
2797
2798 if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
2799 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2800
2801 if (self._helper && !o.animate && (/static/).test(ce.css('position')))
2802 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
2803
2804 }
2805 });
2806
2807 $.ui.plugin.add("resizable", "ghost", {
2808
2809 start: function(event, ui) {
2810
2811 var self = $(this).data("resizable"), o = self.options, cs = self.size;
2812
2813 self.ghost = self.originalElement.clone();
2814 self.ghost
2815 .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
2816 .addClass('ui-resizable-ghost')
2817 .addClass(typeof o.ghost == 'string' ? o.ghost : '');
2818
2819 self.ghost.appendTo(self.helper);
2820
2821 },
2822
2823 resize: function(event, ui){
2824 var self = $(this).data("resizable"), o = self.options;
2825 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
2826 },
2827
2828 stop: function(event, ui){
2829 var self = $(this).data("resizable"), o = self.options;
2830 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
2831 }
2832
2833 });
2834
2835 $.ui.plugin.add("resizable", "grid", {
2836
2837 resize: function(event, ui) {
2838 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;
2839 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
2840 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);
2841
2842 if (/^(se|s|e)$/.test(a)) {
2843 self.size.width = os.width + ox;
2844 self.size.height = os.height + oy;
2845 }
2846 else if (/^(ne)$/.test(a)) {
2847 self.size.width = os.width + ox;
2848 self.size.height = os.height + oy;
2849 self.position.top = op.top - oy;
2850 }
2851 else if (/^(sw)$/.test(a)) {
2852 self.size.width = os.width + ox;
2853 self.size.height = os.height + oy;
2854 self.position.left = op.left - ox;
2855 }
2856 else {
2857 self.size.width = os.width + ox;
2858 self.size.height = os.height + oy;
2859 self.position.top = op.top - oy;
2860 self.position.left = op.left - ox;
2861 }
2862 }
2863
2864 });
2865
2866 var num = function(v) {
2867 return parseInt(v, 10) || 0;
2868 };
2869
2870 var isNumber = function(value) {
2871 return !isNaN(parseInt(value, 10));
2872 };
2873
2874 })(jQuery);
2875 /*
2876 * jQuery UI Selectable 1.8.11
2877 *
2878 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
2879 * Dual licensed under the MIT or GPL Version 2 licenses.
2880 * http://jquery.org/license
2881 *
2882 * http://docs.jquery.com/UI/Selectables
2883 *
2884 * Depends:
2885 * jquery.ui.core.js
2886 * jquery.ui.mouse.js
2887 * jquery.ui.widget.js
2888 */
2889 (function( $, undefined ) {
2890
2891 $.widget("ui.selectable", $.ui.mouse, {
2892 options: {
2893 appendTo: 'body',
2894 autoRefresh: true,
2895 distance: 0,
2896 filter: '*',
2897 tolerance: 'touch'
2898 },
2899 _create: function() {
2900 var self = this;
2901
2902 this.element.addClass("ui-selectable");
2903
2904 this.dragged = false;
2905
2906 // cache selectee children based on filter
2907 var selectees;
2908 this.refresh = function() {
2909 selectees = $(self.options.filter, self.element[0]);
2910 selectees.each(function() {
2911 var $this = $(this);
2912 var pos = $this.offset();
2913 $.data(this, "selectable-item", {
2914 element: this,
2915 $element: $this,
2916 left: pos.left,
2917 top: pos.top,
2918 right: pos.left + $this.outerWidth(),
2919 bottom: pos.top + $this.outerHeight(),
2920 startselected: false,
2921 selected: $this.hasClass('ui-selected'),
2922 selecting: $this.hasClass('ui-selecting'),
2923 unselecting: $this.hasClass('ui-unselecting')
2924 });
2925 });
2926 };
2927 this.refresh();
2928
2929 this.selectees = selectees.addClass("ui-selectee");
2930
2931 this._mouseInit();
2932
2933 this.helper = $("<div class='ui-selectable-helper'></div>");
2934 },
2935
2936 destroy: function() {
2937 this.selectees
2938 .removeClass("ui-selectee")
2939 .removeData("selectable-item");
2940 this.element
2941 .removeClass("ui-selectable ui-selectable-disabled")
2942 .removeData("selectable")
2943 .unbind(".selectable");
2944 this._mouseDestroy();
2945
2946 return this;
2947 },
2948
2949 _mouseStart: function(event) {
2950 var self = this;
2951
2952 this.opos = [event.pageX, event.pageY];
2953
2954 if (this.options.disabled)
2955 return;
2956
2957 var options = this.options;
2958
2959 this.selectees = $(options.filter, this.element[0]);
2960
2961 this._trigger("start", event);
2962
2963 $(options.appendTo).append(this.helper);
2964 // position helper (lasso)
2965 this.helper.css({
2966 "left": event.clientX,
2967 "top": event.clientY,
2968 "width": 0,
2969 "height": 0
2970 });
2971
2972 if (options.autoRefresh) {
2973 this.refresh();
2974 }
2975
2976 this.selectees.filter('.ui-selected').each(function() {
2977 var selectee = $.data(this, "selectable-item");
2978 selectee.startselected = true;
2979 if (!event.metaKey) {
2980 selectee.$element.removeClass('ui-selected');
2981 selectee.selected = false;
2982 selectee.$element.addClass('ui-unselecting');
2983 selectee.unselecting = true;
2984 // selectable UNSELECTING callback
2985 self._trigger("unselecting", event, {
2986 unselecting: selectee.element
2987 });
2988 }
2989 });
2990
2991 $(event.target).parents().andSelf().each(function() {
2992 var selectee = $.data(this, "selectable-item");
2993 if (selectee) {
2994 var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
2995 selectee.$element
2996 .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
2997 .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
2998 selectee.unselecting = !doSelect;
2999 selectee.selecting = doSelect;
3000 selectee.selected = doSelect;
3001 // selectable (UN)SELECTING callback
3002 if (doSelect) {
3003 self._trigger("selecting", event, {
3004 selecting: selectee.element
3005 });
3006 } else {
3007 self._trigger("unselecting", event, {
3008 unselecting: selectee.element
3009 });
3010 }
3011 return false;
3012 }
3013 });
3014
3015 },
3016
3017 _mouseDrag: function(event) {
3018 var self = this;
3019 this.dragged = true;
3020
3021 if (this.options.disabled)
3022 return;
3023
3024 var options = this.options;
3025
3026 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
3027 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
3028 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
3029 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
3030
3031 this.selectees.each(function() {
3032 var selectee = $.data(this, "selectable-item");
3033 //prevent helper from being selected if appendTo: selectable
3034 if (!selectee || selectee.element == self.element[0])
3035 return;
3036 var hit = false;
3037 if (options.tolerance == 'touch') {
3038 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
3039 } else if (options.tolerance == 'fit') {
3040 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
3041 }
3042
3043 if (hit) {
3044 // SELECT
3045 if (selectee.selected) {
3046 selectee.$element.removeClass('ui-selected');
3047 selectee.selected = false;
3048 }
3049 if (selectee.unselecting) {
3050 selectee.$element.removeClass('ui-unselecting');
3051 selectee.unselecting = false;
3052 }
3053 if (!selectee.selecting) {
3054 selectee.$element.addClass('ui-selecting');
3055 selectee.selecting = true;
3056 // selectable SELECTING callback
3057 self._trigger("selecting", event, {
3058 selecting: selectee.element
3059 });
3060 }
3061 } else {
3062 // UNSELECT
3063 if (selectee.selecting) {
3064 if (event.metaKey && selectee.startselected) {
3065 selectee.$element.removeClass('ui-selecting');
3066 selectee.selecting = false;
3067 selectee.$element.addClass('ui-selected');
3068 selectee.selected = true;
3069 } else {
3070 selectee.$element.removeClass('ui-selecting');
3071 selectee.selecting = false;
3072 if (selectee.startselected) {
3073 selectee.$element.addClass('ui-unselecting');
3074 selectee.unselecting = true;
3075 }
3076 // selectable UNSELECTING callback
3077 self._trigger("unselecting", event, {
3078 unselecting: selectee.element
3079 });
3080 }
3081 }
3082 if (selectee.selected) {
3083 if (!event.metaKey && !selectee.startselected) {
3084 selectee.$element.removeClass('ui-selected');
3085 selectee.selected = false;
3086
3087 selectee.$element.addClass('ui-unselecting');
3088 selectee.unselecting = true;
3089 // selectable UNSELECTING callback
3090 self._trigger("unselecting", event, {
3091 unselecting: selectee.element
3092 });
3093 }
3094 }
3095 }
3096 });
3097
3098 return false;
3099 },
3100
3101 _mouseStop: function(event) {
3102 var self = this;
3103
3104 this.dragged = false;
3105
3106 var options = this.options;
3107
3108 $('.ui-unselecting', this.element[0]).each(function() {
3109 var selectee = $.data(this, "selectable-item");
3110 selectee.$element.removeClass('ui-unselecting');
3111 selectee.unselecting = false;
3112 selectee.startselected = false;
3113 self._trigger("unselected", event, {
3114 unselected: selectee.element
3115 });
3116 });
3117 $('.ui-selecting', this.element[0]).each(function() {
3118 var selectee = $.data(this, "selectable-item");
3119 selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
3120 selectee.selecting = false;
3121 selectee.selected = true;
3122 selectee.startselected = true;
3123 self._trigger("selected", event, {
3124 selected: selectee.element
3125 });
3126 });
3127 this._trigger("stop", event);
3128
3129 this.helper.remove();
3130
3131 return false;
3132 }
3133
3134 });
3135
3136 $.extend($.ui.selectable, {
3137 version: "1.8.11"
3138 });
3139
3140 })(jQuery);
3141 /*
3142 * jQuery UI Sortable 1.8.11
3143 *
3144 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
3145 * Dual licensed under the MIT or GPL Version 2 licenses.
3146 * http://jquery.org/license
3147 *
3148 * http://docs.jquery.com/UI/Sortables
3149 *
3150 * Depends:
3151 * jquery.ui.core.js
3152 * jquery.ui.mouse.js
3153 * jquery.ui.widget.js
3154 */
3155 (function( $, undefined ) {
3156
3157 $.widget("ui.sortable", $.ui.mouse, {
3158 widgetEventPrefix: "sort",
3159 options: {
3160 appendTo: "parent",
3161 axis: false,
3162 connectWith: false,
3163 containment: false,
3164 cursor: 'auto',
3165 cursorAt: false,
3166 dropOnEmpty: true,
3167 forcePlaceholderSize: false,
3168 forceHelperSize: false,
3169 grid: false,
3170 handle: false,
3171 helper: "original",
3172 items: '> *',
3173 opacity: false,
3174 placeholder: false,
3175 revert: false,
3176 scroll: true,
3177 scrollSensitivity: 20,
3178 scrollSpeed: 20,
3179 scope: "default",
3180 tolerance: "intersect",
3181 zIndex: 1000
3182 },
3183 _create: function() {
3184
3185 var o = this.options;
3186 this.containerCache = {};
3187 this.element.addClass("ui-sortable");
3188
3189 //Get the items
3190 this.refresh();
3191
3192 //Let's determine if the items are being displayed horizontally
3193 this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
3194
3195 //Let's determine the parent's offset
3196 this.offset = this.element.offset();
3197
3198 //Initialize mouse events for interaction
3199 this._mouseInit();
3200
3201 },
3202
3203 destroy: function() {
3204 this.element
3205 .removeClass("ui-sortable ui-sortable-disabled")
3206 .removeData("sortable")
3207 .unbind(".sortable");
3208 this._mouseDestroy();
3209
3210 for ( var i = this.items.length - 1; i >= 0; i-- )
3211 this.items[i].item.removeData("sortable-item");
3212
3213 return this;
3214 },
3215
3216 _setOption: function(key, value){
3217 if ( key === "disabled" ) {
3218 this.options[ key ] = value;
3219
3220 this.widget()
3221 [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
3222 } else {
3223 // Don't call widget base _setOption for disable as it adds ui-state-disabled class
3224 $.Widget.prototype._setOption.apply(this, arguments);
3225 }
3226 },
3227
3228 _mouseCapture: function(event, overrideHandle) {
3229
3230 if (this.reverting) {
3231 return false;
3232 }
3233
3234 if(this.options.disabled || this.options.type == 'static') return false;
3235
3236 //We have to refresh the items data once first
3237 this._refreshItems(event);
3238
3239 //Find out if the clicked node (or one of its parents) is a actual item in this.items
3240 var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
3241 if($.data(this, 'sortable-item') == self) {
3242 currentItem = $(this);
3243 return false;
3244 }
3245 });
3246 if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
3247
3248 if(!currentItem) return false;
3249 if(this.options.handle && !overrideHandle) {
3250 var validHandle = false;
3251
3252 $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
3253 if(!validHandle) return false;
3254 }
3255
3256 this.currentItem = currentItem;
3257 this._removeCurrentsFromItems();
3258 return true;
3259
3260 },
3261
3262 _mouseStart: function(event, overrideHandle, noActivation) {
3263
3264 var o = this.options, self = this;
3265 this.currentContainer = this;
3266
3267 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
3268 this.refreshPositions();
3269
3270 //Create and append the visible helper
3271 this.helper = this._createHelper(event);
3272
3273 //Cache the helper size
3274 this._cacheHelperProportions();
3275
3276 /*
3277 * - Position generation -
3278 * This block generates everything position related - it's the core of draggables.
3279 */
3280
3281 //Cache the margins of the original element
3282 this._cacheMargins();
3283
3284 //Get the next scrolling parent
3285 this.scrollParent = this.helper.scrollParent();
3286
3287 //The element's absolute position on the page minus margins
3288 this.offset = this.currentItem.offset();
3289 this.offset = {
3290 top: this.offset.top - this.margins.top,
3291 left: this.offset.left - this.margins.left
3292 };
3293
3294 // Only after we got the offset, we can change the helper's position to absolute
3295 // TODO: Still need to figure out a way to make relative sorting possible
3296 this.helper.css("position", "absolute");
3297 this.cssPosition = this.helper.css("position");
3298
3299 $.extend(this.offset, {
3300 click: { //Where the click happened, relative to the element
3301 left: event.pageX - this.offset.left,
3302 top: event.pageY - this.offset.top
3303 },
3304 parent: this._getParentOffset(),
3305 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
3306 });
3307
3308 //Generate the original position
3309 this.originalPosition = this._generatePosition(event);
3310 this.originalPageX = event.pageX;
3311 this.originalPageY = event.pageY;
3312
3313 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
3314 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
3315
3316 //Cache the former DOM position
3317 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
3318
3319 //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
3320 if(this.helper[0] != this.currentItem[0]) {
3321 this.currentItem.hide();
3322 }
3323
3324 //Create the placeholder
3325 this._createPlaceholder();
3326
3327 //Set a containment if given in the options
3328 if(o.containment)
3329 this._setContainment();
3330
3331 if(o.cursor) { // cursor option
3332 if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
3333 $('body').css("cursor", o.cursor);
3334 }
3335
3336 if(o.opacity) { // opacity option
3337 if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
3338 this.helper.css("opacity", o.opacity);
3339 }
3340
3341 if(o.zIndex) { // zIndex option
3342 if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
3343 this.helper.css("zIndex", o.zIndex);
3344 }
3345
3346 //Prepare scrolling
3347 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
3348 this.overflowOffset = this.scrollParent.offset();
3349
3350 //Call callbacks
3351 this._trigger("start", event, this._uiHash());
3352
3353 //Recache the helper size
3354 if(!this._preserveHelperProportions)
3355 this._cacheHelperProportions();
3356
3357
3358 //Post 'activate' events to possible containers
3359 if(!noActivation) {
3360 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
3361 }
3362
3363 //Prepare possible droppables
3364 if($.ui.ddmanager)
3365 $.ui.ddmanager.current = this;
3366
3367 if ($.ui.ddmanager && !o.dropBehaviour)
3368 $.ui.ddmanager.prepareOffsets(this, event);
3369
3370 this.dragging = true;
3371
3372 this.helper.addClass("ui-sortable-helper");
3373 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
3374 return true;
3375
3376 },
3377
3378 _mouseDrag: function(event) {
3379
3380 //Compute the helpers position
3381 this.position = this._generatePosition(event);
3382 this.positionAbs = this._convertPositionTo("absolute");
3383
3384 if (!this.lastPositionAbs) {
3385 this.lastPositionAbs = this.positionAbs;
3386 }
3387
3388 //Do scrolling
3389 if(this.options.scroll) {
3390 var o = this.options, scrolled = false;
3391 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
3392
3393 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
3394 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
3395 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
3396 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
3397
3398 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
3399 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
3400 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
3401 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
3402
3403 } else {
3404
3405 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
3406 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
3407 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
3408 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
3409
3410 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
3411 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
3412 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
3413 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
3414
3415 }
3416
3417 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
3418 $.ui.ddmanager.prepareOffsets(this, event);
3419 }
3420
3421 //Regenerate the absolute position used for position checks
3422 this.positionAbs = this._convertPositionTo("absolute");
3423
3424 //Set the helper position
3425 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
3426 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
3427
3428 //Rearrange
3429 for (var i = this.items.length - 1; i >= 0; i--) {
3430
3431 //Cache variables and intersection, continue if no intersection
3432 var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
3433 if (!intersection) continue;
3434
3435 if(itemElement != this.currentItem[0] //cannot intersect with itself
3436 && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
3437 && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
3438 && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
3439 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
3440 ) {
3441
3442 this.direction = intersection == 1 ? "down" : "up";
3443
3444 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
3445 this._rearrange(event, item);
3446 } else {
3447 break;
3448 }
3449
3450 this._trigger("change", event, this._uiHash());
3451 break;
3452 }
3453 }
3454
3455 //Post events to containers
3456 this._contactContainers(event);
3457
3458 //Interconnect with droppables
3459 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
3460
3461 //Call callbacks
3462 this._trigger('sort', event, this._uiHash());
3463
3464 this.lastPositionAbs = this.positionAbs;
3465 return false;
3466
3467 },
3468
3469 _mouseStop: function(event, noPropagation) {
3470
3471 if(!event) return;
3472
3473 //If we are using droppables, inform the manager about the drop
3474 if ($.ui.ddmanager && !this.options.dropBehaviour)
3475 $.ui.ddmanager.drop(this, event);
3476
3477 if(this.options.revert) {
3478 var self = this;
3479 var cur = self.placeholder.offset();
3480
3481 self.reverting = true;
3482
3483 $(this.helper).animate({
3484 left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
3485 top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
3486 }, parseInt(this.options.revert, 10) || 500, function() {
3487 self._clear(event);
3488 });
3489 } else {
3490 this._clear(event, noPropagation);
3491 }
3492
3493 return false;
3494
3495 },
3496
3497 cancel: function() {
3498
3499 var self = this;
3500
3501 if(this.dragging) {
3502
3503 this._mouseUp({ target: null });
3504
3505 if(this.options.helper == "original")
3506 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3507 else
3508 this.currentItem.show();
3509
3510 //Post deactivating events to containers
3511 for (var i = this.containers.length - 1; i >= 0; i--){
3512 this.containers[i]._trigger("deactivate", null, self._uiHash(this));
3513 if(this.containers[i].containerCache.over) {
3514 this.containers[i]._trigger("out", null, self._uiHash(this));
3515 this.containers[i].containerCache.over = 0;
3516 }
3517 }
3518
3519 }
3520
3521 if (this.placeholder) {
3522 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3523 if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3524 if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
3525
3526 $.extend(this, {
3527 helper: null,
3528 dragging: false,
3529 reverting: false,
3530 _noFinalSort: null
3531 });
3532
3533 if(this.domPosition.prev) {
3534 $(this.domPosition.prev).after(this.currentItem);
3535 } else {
3536 $(this.domPosition.parent).prepend(this.currentItem);
3537 }
3538 }
3539
3540 return this;
3541
3542 },
3543
3544 serialize: function(o) {
3545
3546 var items = this._getItemsAsjQuery(o && o.connected);
3547 var str = []; o = o || {};
3548
3549 $(items).each(function() {
3550 var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
3551 if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
3552 });
3553
3554 if(!str.length && o.key) {
3555 str.push(o.key + '=');
3556 }
3557
3558 return str.join('&');
3559
3560 },
3561
3562 toArray: function(o) {
3563
3564 var items = this._getItemsAsjQuery(o && o.connected);
3565 var ret = []; o = o || {};
3566
3567 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
3568 return ret;
3569
3570 },
3571
3572 /* Be careful with the following core functions */
3573 _intersectsWith: function(item) {
3574
3575 var x1 = this.positionAbs.left,
3576 x2 = x1 + this.helperProportions.width,
3577 y1 = this.positionAbs.top,
3578 y2 = y1 + this.helperProportions.height;
3579
3580 var l = item.left,
3581 r = l + item.width,
3582 t = item.top,
3583 b = t + item.height;
3584
3585 var dyClick = this.offset.click.top,
3586 dxClick = this.offset.click.left;
3587
3588 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
3589
3590 if( this.options.tolerance == "pointer"
3591 || this.options.forcePointerForContainers
3592 || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
3593 ) {
3594 return isOverElement;
3595 } else {
3596
3597 return (l < x1 + (this.helperProportions.width / 2) // Right Half
3598 && x2 - (this.helperProportions.width / 2) < r // Left Half
3599 && t < y1 + (this.helperProportions.height / 2) // Bottom Half
3600 && y2 - (this.helperProportions.height / 2) < b ); // Top Half
3601
3602 }
3603 },
3604
3605 _intersectsWithPointer: function(item) {
3606
3607 var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
3608 isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
3609 isOverElement = isOverElementHeight && isOverElementWidth,
3610 verticalDirection = this._getDragVerticalDirection(),
3611 horizontalDirection = this._getDragHorizontalDirection();
3612
3613 if (!isOverElement)
3614 return false;
3615
3616 return this.floating ?
3617 ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
3618 : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
3619
3620 },
3621
3622 _intersectsWithSides: function(item) {
3623
3624 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
3625 isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
3626 verticalDirection = this._getDragVerticalDirection(),
3627 horizontalDirection = this._getDragHorizontalDirection();
3628
3629 if (this.floating && horizontalDirection) {
3630 return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
3631 } else {
3632 return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
3633 }
3634
3635 },
3636
3637 _getDragVerticalDirection: function() {
3638 var delta = this.positionAbs.top - this.lastPositionAbs.top;
3639 return delta != 0 && (delta > 0 ? "down" : "up");
3640 },
3641
3642 _getDragHorizontalDirection: function() {
3643 var delta = this.positionAbs.left - this.lastPositionAbs.left;
3644 return delta != 0 && (delta > 0 ? "right" : "left");
3645 },
3646
3647 refresh: function(event) {
3648 this._refreshItems(event);
3649 this.refreshPositions();
3650 return this;
3651 },
3652
3653 _connectWith: function() {
3654 var options = this.options;
3655 return options.connectWith.constructor == String
3656 ? [options.connectWith]
3657 : options.connectWith;
3658 },
3659
3660 _getItemsAsjQuery: function(connected) {
3661
3662 var self = this;
3663 var items = [];
3664 var queries = [];
3665 var connectWith = this._connectWith();
3666
3667 if(connectWith && connected) {
3668 for (var i = connectWith.length - 1; i >= 0; i--){
3669 var cur = $(connectWith[i]);
3670 for (var j = cur.length - 1; j >= 0; j--){
3671 var inst = $.data(cur[j], 'sortable');
3672 if(inst && inst != this && !inst.options.disabled) {
3673 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]);
3674 }
3675 };
3676 };
3677 }
3678
3679 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]);
3680
3681 for (var i = queries.length - 1; i >= 0; i--){
3682 queries[i][0].each(function() {
3683 items.push(this);
3684 });
3685 };
3686
3687 return $(items);
3688
3689 },
3690
3691 _removeCurrentsFromItems: function() {
3692
3693 var list = this.currentItem.find(":data(sortable-item)");
3694
3695 for (var i=0; i < this.items.length; i++) {
3696
3697 for (var j=0; j < list.length; j++) {
3698 if(list[j] == this.items[i].item[0])
3699 this.items.splice(i,1);
3700 };
3701
3702 };
3703
3704 },
3705
3706 _refreshItems: function(event) {
3707
3708 this.items = [];
3709 this.containers = [this];
3710 var items = this.items;
3711 var self = this;
3712 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
3713 var connectWith = this._connectWith();
3714
3715 if(connectWith) {
3716 for (var i = connectWith.length - 1; i >= 0; i--){
3717 var cur = $(connectWith[i]);
3718 for (var j = cur.length - 1; j >= 0; j--){
3719 var inst = $.data(cur[j], 'sortable');
3720 if(inst && inst != this && !inst.options.disabled) {
3721 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
3722 this.containers.push(inst);
3723 }
3724 };
3725 };
3726 }
3727
3728 for (var i = queries.length - 1; i >= 0; i--) {
3729 var targetData = queries[i][1];
3730 var _queries = queries[i][0];
3731
3732 for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
3733 var item = $(_queries[j]);
3734
3735 item.data('sortable-item', targetData); // Data for target checking (mouse manager)
3736
3737 items.push({
3738 item: item,
3739 instance: targetData,
3740 width: 0, height: 0,
3741 left: 0, top: 0
3742 });
3743 };
3744 };
3745
3746 },
3747
3748 refreshPositions: function(fast) {
3749
3750 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
3751 if(this.offsetParent && this.helper) {
3752 this.offset.parent = this._getParentOffset();
3753 }
3754
3755 for (var i = this.items.length - 1; i >= 0; i--){
3756 var item = this.items[i];
3757
3758 var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
3759
3760 if (!fast) {
3761 item.width = t.outerWidth();
3762 item.height = t.outerHeight();
3763 }
3764
3765 var p = t.offset();
3766 item.left = p.left;
3767 item.top = p.top;
3768 };
3769
3770 if(this.options.custom && this.options.custom.refreshContainers) {
3771 this.options.custom.refreshContainers.call(this);
3772 } else {
3773 for (var i = this.containers.length - 1; i >= 0; i--){
3774 var p = this.containers[i].element.offset();
3775 this.containers[i].containerCache.left = p.left;
3776 this.containers[i].containerCache.top = p.top;
3777 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
3778 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
3779 };
3780 }
3781
3782 return this;
3783 },
3784
3785 _createPlaceholder: function(that) {
3786
3787 var self = that || this, o = self.options;
3788
3789 if(!o.placeholder || o.placeholder.constructor == String) {
3790 var className = o.placeholder;
3791 o.placeholder = {
3792 element: function() {
3793
3794 var el = $(document.createElement(self.currentItem[0].nodeName))
3795 .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
3796 .removeClass("ui-sortable-helper")[0];
3797
3798 if(!className)
3799 el.style.visibility = "hidden";
3800
3801 return el;
3802 },
3803 update: function(container, p) {
3804
3805 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
3806 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
3807 if(className && !o.forcePlaceholderSize) return;
3808
3809 //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
3810 if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
3811 if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
3812 }
3813 };
3814 }
3815
3816 //Create the placeholder
3817 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
3818
3819 //Append it after the actual current item
3820 self.currentItem.after(self.placeholder);
3821
3822 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
3823 o.placeholder.update(self, self.placeholder);
3824
3825 },
3826
3827 _contactContainers: function(event) {
3828
3829 // get innermost container that intersects with item
3830 var innermostContainer = null, innermostIndex = null;
3831
3832
3833 for (var i = this.containers.length - 1; i >= 0; i--){
3834
3835 // never consider a container that's located within the item itself
3836 if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
3837 continue;
3838
3839 if(this._intersectsWith(this.containers[i].containerCache)) {
3840
3841 // if we've already found a container and it's more "inner" than this, then continue
3842 if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
3843 continue;
3844
3845 innermostContainer = this.containers[i];
3846 innermostIndex = i;
3847
3848 } else {
3849 // container doesn't intersect. trigger "out" event if necessary
3850 if(this.containers[i].containerCache.over) {
3851 this.containers[i]._trigger("out", event, this._uiHash(this));
3852 this.containers[i].containerCache.over = 0;
3853 }
3854 }
3855
3856 }
3857
3858 // if no intersecting containers found, return
3859 if(!innermostContainer) return;
3860
3861 // move the item into the container if it's not there already
3862 if(this.containers.length === 1) {
3863 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3864 this.containers[innermostIndex].containerCache.over = 1;
3865 } else if(this.currentContainer != this.containers[innermostIndex]) {
3866
3867 //When entering a new container, we will find the item with the least distance and append our item near it
3868 var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
3869 for (var j = this.items.length - 1; j >= 0; j--) {
3870 if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
3871 var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top'];
3872 if(Math.abs(cur - base) < dist) {
3873 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
3874 }
3875 }
3876
3877 if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
3878 return;
3879
3880 this.currentContainer = this.containers[innermostIndex];
3881 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
3882 this._trigger("change", event, this._uiHash());
3883 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
3884
3885 //Update the placeholder
3886 this.options.placeholder.update(this.currentContainer, this.placeholder);
3887
3888 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3889 this.containers[innermostIndex].containerCache.over = 1;
3890 }
3891
3892
3893 },
3894
3895 _createHelper: function(event) {
3896
3897 var o = this.options;
3898 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
3899
3900 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
3901 $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
3902
3903 if(helper[0] == this.currentItem[0])
3904 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") };
3905
3906 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
3907 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
3908
3909 return helper;
3910
3911 },
3912
3913 _adjustOffsetFromHelper: function(obj) {
3914 if (typeof obj == 'string') {
3915 obj = obj.split(' ');
3916 }
3917 if ($.isArray(obj)) {
3918 obj = {left: +obj[0], top: +obj[1] || 0};
3919 }
3920 if ('left' in obj) {
3921 this.offset.click.left = obj.left + this.margins.left;
3922 }
3923 if ('right' in obj) {
3924 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
3925 }
3926 if ('top' in obj) {
3927 this.offset.click.top = obj.top + this.margins.top;
3928 }
3929 if ('bottom' in obj) {
3930 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
3931 }
3932 },
3933
3934 _getParentOffset: function() {
3935
3936
3937 //Get the offsetParent and cache its position
3938 this.offsetParent = this.helper.offsetParent();
3939 var po = this.offsetParent.offset();
3940
3941 // This is a special case where we need to modify a offset calculated on start, since the following happened:
3942 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
3943 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
3944 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
3945 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
3946 po.left += this.scrollParent.scrollLeft();
3947 po.top += this.scrollParent.scrollTop();
3948 }
3949
3950 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
3951 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
3952 po = { top: 0, left: 0 };
3953
3954 return {
3955 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
3956 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
3957 };
3958
3959 },
3960
3961 _getRelativeOffset: function() {
3962
3963 if(this.cssPosition == "relative") {
3964 var p = this.currentItem.position();
3965 return {
3966 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
3967 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
3968 };
3969 } else {
3970 return { top: 0, left: 0 };
3971 }
3972
3973 },
3974
3975 _cacheMargins: function() {
3976 this.margins = {
3977 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
3978 top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
3979 };
3980 },
3981
3982 _cacheHelperProportions: function() {
3983 this.helperProportions = {
3984 width: this.helper.outerWidth(),
3985 height: this.helper.outerHeight()
3986 };
3987 },
3988
3989 _setContainment: function() {
3990
3991 var o = this.options;
3992 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
3993 if(o.containment == 'document' || o.containment == 'window') this.containment = [
3994 0 - this.offset.relative.left - this.offset.parent.left,
3995 0 - this.offset.relative.top - this.offset.parent.top,
3996 $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
3997 ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
3998 ];
3999
4000 if(!(/^(document|window|parent)$/).test(o.containment)) {
4001 var ce = $(o.containment)[0];
4002 var co = $(o.containment).offset();
4003 var over = ($(ce).css("overflow") != 'hidden');
4004
4005 this.containment = [
4006 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
4007 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
4008 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,
4009 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
4010 ];
4011 }
4012
4013 },
4014
4015 _convertPositionTo: function(d, pos) {
4016
4017 if(!pos) pos = this.position;
4018 var mod = d == "absolute" ? 1 : -1;
4019 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);
4020
4021 return {
4022 top: (
4023 pos.top // The absolute mouse position
4024 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
4025 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
4026 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
4027 ),
4028 left: (
4029 pos.left // The absolute mouse position
4030 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
4031 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
4032 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
4033 )
4034 };
4035
4036 },
4037
4038 _generatePosition: function(event) {
4039
4040 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);
4041
4042 // This is another very weird special case that only happens for relative elements:
4043 // 1. If the css position is relative
4044 // 2. and the scroll parent is the document or similar to the offset parent
4045 // we have to refresh the relative offset during the scroll so there are no jumps
4046 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
4047 this.offset.relative = this._getRelativeOffset();
4048 }
4049
4050 var pageX = event.pageX;
4051 var pageY = event.pageY;
4052
4053 /*
4054 * - Position constraining -
4055 * Constrain the position to a mix of grid, containment.
4056 */
4057
4058 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
4059
4060 if(this.containment) {
4061 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
4062 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
4063 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
4064 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
4065 }
4066
4067 if(o.grid) {
4068 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
4069 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;
4070
4071 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
4072 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;
4073 }
4074
4075 }
4076
4077 return {
4078 top: (
4079 pageY // The absolute mouse position
4080 - this.offset.click.top // Click offset (relative to the element)
4081 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
4082 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
4083 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
4084 ),
4085 left: (
4086 pageX // The absolute mouse position
4087 - this.offset.click.left // Click offset (relative to the element)
4088 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
4089 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
4090 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
4091 )
4092 };
4093
4094 },
4095
4096 _rearrange: function(event, i, a, hardRefresh) {
4097
4098 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));
4099
4100 //Various things done here to improve the performance:
4101 // 1. we create a setTimeout, that calls refreshPositions
4102 // 2. on the instance, we have a counter variable, that get's higher after every append
4103 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
4104 // 4. this lets only the last addition to the timeout stack through
4105 this.counter = this.counter ? ++this.counter : 1;
4106 var self = this, counter = this.counter;
4107
4108 window.setTimeout(function() {
4109 if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
4110 },0);
4111
4112 },
4113
4114 _clear: function(event, noPropagation) {
4115
4116 this.reverting = false;
4117 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
4118 // everything else normalized again
4119 var delayedTriggers = [], self = this;
4120
4121 // We first have to update the dom position of the actual currentItem
4122 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
4123 if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
4124 this._noFinalSort = null;
4125
4126 if(this.helper[0] == this.currentItem[0]) {
4127 for(var i in this._storedCSS) {
4128 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
4129 }
4130 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
4131 } else {
4132 this.currentItem.show();
4133 }
4134
4135 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
4136 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
4137 if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
4138 if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
4139 for (var i = this.containers.length - 1; i >= 0; i--){
4140 if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
4141 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4142 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4143 }
4144 };
4145 };
4146
4147 //Post events to containers
4148 for (var i = this.containers.length - 1; i >= 0; i--){
4149 if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4150 if(this.containers[i].containerCache.over) {
4151 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
4152 this.containers[i].containerCache.over = 0;
4153 }
4154 }
4155
4156 //Do what was originally in plugins
4157 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
4158 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
4159 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
4160
4161 this.dragging = false;
4162 if(this.cancelHelperRemoval) {
4163 if(!noPropagation) {
4164 this._trigger("beforeStop", event, this._uiHash());
4165 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
4166 this._trigger("stop", event, this._uiHash());
4167 }
4168 return false;
4169 }
4170
4171 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
4172
4173 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
4174 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
4175
4176 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
4177
4178 if(!noPropagation) {
4179 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
4180 this._trigger("stop", event, this._uiHash());
4181 }
4182
4183 this.fromOutside = false;
4184 return true;
4185
4186 },
4187
4188 _trigger: function() {
4189 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
4190 this.cancel();
4191 }
4192 },
4193
4194 _uiHash: function(inst) {
4195 var self = inst || this;
4196 return {
4197 helper: self.helper,
4198 placeholder: self.placeholder || $([]),
4199 position: self.position,
4200 originalPosition: self.originalPosition,
4201 offset: self.positionAbs,
4202 item: self.currentItem,
4203 sender: inst ? inst.element : null
4204 };
4205 }
4206
4207 });
4208
4209 $.extend($.ui.sortable, {
4210 version: "1.8.11"
4211 });
4212
4213 })(jQuery);
4214 /*
4215 * jQuery UI Accordion 1.8.11
4216 *
4217 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4218 * Dual licensed under the MIT or GPL Version 2 licenses.
4219 * http://jquery.org/license
4220 *
4221 * http://docs.jquery.com/UI/Accordion
4222 *
4223 * Depends:
4224 * jquery.ui.core.js
4225 * jquery.ui.widget.js
4226 */
4227 (function( $, undefined ) {
4228
4229 $.widget( "ui.accordion", {
4230 options: {
4231 active: 0,
4232 animated: "slide",
4233 autoHeight: true,
4234 clearStyle: false,
4235 collapsible: false,
4236 event: "click",
4237 fillSpace: false,
4238 header: "> li > :first-child,> :not(li):even",
4239 icons: {
4240 header: "ui-icon-triangle-1-e",
4241 headerSelected: "ui-icon-triangle-1-s"
4242 },
4243 navigation: false,
4244 navigationFilter: function() {
4245 return this.href.toLowerCase() === location.href.toLowerCase();
4246 }
4247 },
4248
4249 _create: function() {
4250 var self = this,
4251 options = self.options;
4252
4253 self.running = 0;
4254
4255 self.element
4256 .addClass( "ui-accordion ui-widget ui-helper-reset" )
4257 // in lack of child-selectors in CSS
4258 // we need to mark top-LIs in a UL-accordion for some IE-fix
4259 .children( "li" )
4260 .addClass( "ui-accordion-li-fix" );
4261
4262 self.headers = self.element.find( options.header )
4263 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
4264 .bind( "mouseenter.accordion", function() {
4265 if ( options.disabled ) {
4266 return;
4267 }
4268 $( this ).addClass( "ui-state-hover" );
4269 })
4270 .bind( "mouseleave.accordion", function() {
4271 if ( options.disabled ) {
4272 return;
4273 }
4274 $( this ).removeClass( "ui-state-hover" );
4275 })
4276 .bind( "focus.accordion", function() {
4277 if ( options.disabled ) {
4278 return;
4279 }
4280 $( this ).addClass( "ui-state-focus" );
4281 })
4282 .bind( "blur.accordion", function() {
4283 if ( options.disabled ) {
4284 return;
4285 }
4286 $( this ).removeClass( "ui-state-focus" );
4287 });
4288
4289 self.headers.next()
4290 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
4291
4292 if ( options.navigation ) {
4293 var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
4294 if ( current.length ) {
4295 var header = current.closest( ".ui-accordion-header" );
4296 if ( header.length ) {
4297 // anchor within header
4298 self.active = header;
4299 } else {
4300 // anchor within content
4301 self.active = current.closest( ".ui-accordion-content" ).prev();
4302 }
4303 }
4304 }
4305
4306 self.active = self._findActive( self.active || options.active )
4307 .addClass( "ui-state-default ui-state-active" )
4308 .toggleClass( "ui-corner-all" )
4309 .toggleClass( "ui-corner-top" );
4310 self.active.next().addClass( "ui-accordion-content-active" );
4311
4312 self._createIcons();
4313 self.resize();
4314
4315 // ARIA
4316 self.element.attr( "role", "tablist" );
4317
4318 self.headers
4319 .attr( "role", "tab" )
4320 .bind( "keydown.accordion", function( event ) {
4321 return self._keydown( event );
4322 })
4323 .next()
4324 .attr( "role", "tabpanel" );
4325
4326 self.headers
4327 .not( self.active || "" )
4328 .attr({
4329 "aria-expanded": "false",
4330 "aria-selected": "false",
4331 tabIndex: -1
4332 })
4333 .next()
4334 .hide();
4335
4336 // make sure at least one header is in the tab order
4337 if ( !self.active.length ) {
4338 self.headers.eq( 0 ).attr( "tabIndex", 0 );
4339 } else {
4340 self.active
4341 .attr({
4342 "aria-expanded": "true",
4343 "aria-selected": "true",
4344 tabIndex: 0
4345 });
4346 }
4347
4348 // only need links in tab order for Safari
4349 if ( !$.browser.safari ) {
4350 self.headers.find( "a" ).attr( "tabIndex", -1 );
4351 }
4352
4353 if ( options.event ) {
4354 self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
4355 self._clickHandler.call( self, event, this );
4356 event.preventDefault();
4357 });
4358 }
4359 },
4360
4361 _createIcons: function() {
4362 var options = this.options;
4363 if ( options.icons ) {
4364 $( "<span></span>" )
4365 .addClass( "ui-icon " + options.icons.header )
4366 .prependTo( this.headers );
4367 this.active.children( ".ui-icon" )
4368 .toggleClass(options.icons.header)
4369 .toggleClass(options.icons.headerSelected);
4370 this.element.addClass( "ui-accordion-icons" );
4371 }
4372 },
4373
4374 _destroyIcons: function() {
4375 this.headers.children( ".ui-icon" ).remove();
4376 this.element.removeClass( "ui-accordion-icons" );
4377 },
4378
4379 destroy: function() {
4380 var options = this.options;
4381
4382 this.element
4383 .removeClass( "ui-accordion ui-widget ui-helper-reset" )
4384 .removeAttr( "role" );
4385
4386 this.headers
4387 .unbind( ".accordion" )
4388 .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" )
4389 .removeAttr( "role" )
4390 .removeAttr( "aria-expanded" )
4391 .removeAttr( "aria-selected" )
4392 .removeAttr( "tabIndex" );
4393
4394 this.headers.find( "a" ).removeAttr( "tabIndex" );
4395 this._destroyIcons();
4396 var contents = this.headers.next()
4397 .css( "display", "" )
4398 .removeAttr( "role" )
4399 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
4400 if ( options.autoHeight || options.fillHeight ) {
4401 contents.css( "height", "" );
4402 }
4403
4404 return $.Widget.prototype.destroy.call( this );
4405 },
4406
4407 _setOption: function( key, value ) {
4408 $.Widget.prototype._setOption.apply( this, arguments );
4409
4410 if ( key == "active" ) {
4411 this.activate( value );
4412 }
4413 if ( key == "icons" ) {
4414 this._destroyIcons();
4415 if ( value ) {
4416 this._createIcons();
4417 }
4418 }
4419 // #5332 - opacity doesn't cascade to positioned elements in IE
4420 // so we need to add the disabled class to the headers and panels
4421 if ( key == "disabled" ) {
4422 this.headers.add(this.headers.next())
4423 [ value ? "addClass" : "removeClass" ](
4424 "ui-accordion-disabled ui-state-disabled" );
4425 }
4426 },
4427
4428 _keydown: function( event ) {
4429 if ( this.options.disabled || event.altKey || event.ctrlKey ) {
4430 return;
4431 }
4432
4433 var keyCode = $.ui.keyCode,
4434 length = this.headers.length,
4435 currentIndex = this.headers.index( event.target ),
4436 toFocus = false;
4437
4438 switch ( event.keyCode ) {
4439 case keyCode.RIGHT:
4440 case keyCode.DOWN:
4441 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
4442 break;
4443 case keyCode.LEFT:
4444 case keyCode.UP:
4445 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
4446 break;
4447 case keyCode.SPACE:
4448 case keyCode.ENTER:
4449 this._clickHandler( { target: event.target }, event.target );
4450 event.preventDefault();
4451 }
4452
4453 if ( toFocus ) {
4454 $( event.target ).attr( "tabIndex", -1 );
4455 $( toFocus ).attr( "tabIndex", 0 );
4456 toFocus.focus();
4457 return false;
4458 }
4459
4460 return true;
4461 },
4462
4463 resize: function() {
4464 var options = this.options,
4465 maxHeight;
4466
4467 if ( options.fillSpace ) {
4468 if ( $.browser.msie ) {
4469 var defOverflow = this.element.parent().css( "overflow" );
4470 this.element.parent().css( "overflow", "hidden");
4471 }
4472 maxHeight = this.element.parent().height();
4473 if ($.browser.msie) {
4474 this.element.parent().css( "overflow", defOverflow );
4475 }
4476
4477 this.headers.each(function() {
4478 maxHeight -= $( this ).outerHeight( true );
4479 });
4480
4481 this.headers.next()
4482 .each(function() {
4483 $( this ).height( Math.max( 0, maxHeight -
4484 $( this ).innerHeight() + $( this ).height() ) );
4485 })
4486 .css( "overflow", "auto" );
4487 } else if ( options.autoHeight ) {
4488 maxHeight = 0;
4489 this.headers.next()
4490 .each(function() {
4491 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
4492 })
4493 .height( maxHeight );
4494 }
4495
4496 return this;
4497 },
4498
4499 activate: function( index ) {
4500 // TODO this gets called on init, changing the option without an explicit call for that
4501 this.options.active = index;
4502 // call clickHandler with custom event
4503 var active = this._findActive( index )[ 0 ];
4504 this._clickHandler( { target: active }, active );
4505
4506 return this;
4507 },
4508
4509 _findActive: function( selector ) {
4510 return selector
4511 ? typeof selector === "number"
4512 ? this.headers.filter( ":eq(" + selector + ")" )
4513 : this.headers.not( this.headers.not( selector ) )
4514 : selector === false
4515 ? $( [] )
4516 : this.headers.filter( ":eq(0)" );
4517 },
4518
4519 // TODO isn't event.target enough? why the separate target argument?
4520 _clickHandler: function( event, target ) {
4521 var options = this.options;
4522 if ( options.disabled ) {
4523 return;
4524 }
4525
4526 // called only when using activate(false) to close all parts programmatically
4527 if ( !event.target ) {
4528 if ( !options.collapsible ) {
4529 return;
4530 }
4531 this.active
4532 .removeClass( "ui-state-active ui-corner-top" )
4533 .addClass( "ui-state-default ui-corner-all" )
4534 .children( ".ui-icon" )
4535 .removeClass( options.icons.headerSelected )
4536 .addClass( options.icons.header );
4537 this.active.next().addClass( "ui-accordion-content-active" );
4538 var toHide = this.active.next(),
4539 data = {
4540 options: options,
4541 newHeader: $( [] ),
4542 oldHeader: options.active,
4543 newContent: $( [] ),
4544 oldContent: toHide
4545 },
4546 toShow = ( this.active = $( [] ) );
4547 this._toggle( toShow, toHide, data );
4548 return;
4549 }
4550
4551 // get the click target
4552 var clicked = $( event.currentTarget || target ),
4553 clickedIsActive = clicked[0] === this.active[0];
4554
4555 // TODO the option is changed, is that correct?
4556 // TODO if it is correct, shouldn't that happen after determining that the click is valid?
4557 options.active = options.collapsible && clickedIsActive ?
4558 false :
4559 this.headers.index( clicked );
4560
4561 // if animations are still active, or the active header is the target, ignore click
4562 if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
4563 return;
4564 }
4565
4566 // find elements to show and hide
4567 var active = this.active,
4568 toShow = clicked.next(),
4569 toHide = this.active.next(),
4570 data = {
4571 options: options,
4572 newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
4573 oldHeader: this.active,
4574 newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
4575 oldContent: toHide
4576 },
4577 down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
4578
4579 // when the call to ._toggle() comes after the class changes
4580 // it causes a very odd bug in IE 8 (see #6720)
4581 this.active = clickedIsActive ? $([]) : clicked;
4582 this._toggle( toShow, toHide, data, clickedIsActive, down );
4583
4584 // switch classes
4585 active
4586 .removeClass( "ui-state-active ui-corner-top" )
4587 .addClass( "ui-state-default ui-corner-all" )
4588 .children( ".ui-icon" )
4589 .removeClass( options.icons.headerSelected )
4590 .addClass( options.icons.header );
4591 if ( !clickedIsActive ) {
4592 clicked
4593 .removeClass( "ui-state-default ui-corner-all" )
4594 .addClass( "ui-state-active ui-corner-top" )
4595 .children( ".ui-icon" )
4596 .removeClass( options.icons.header )
4597 .addClass( options.icons.headerSelected );
4598 clicked
4599 .next()
4600 .addClass( "ui-accordion-content-active" );
4601 }
4602
4603 return;
4604 },
4605
4606 _toggle: function( toShow, toHide, data, clickedIsActive, down ) {
4607 var self = this,
4608 options = self.options;
4609
4610 self.toShow = toShow;
4611 self.toHide = toHide;
4612 self.data = data;
4613
4614 var complete = function() {
4615 if ( !self ) {
4616 return;
4617 }
4618 return self._completed.apply( self, arguments );
4619 };
4620
4621 // trigger changestart event
4622 self._trigger( "changestart", null, self.data );
4623
4624 // count elements to animate
4625 self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
4626
4627 if ( options.animated ) {
4628 var animOptions = {};
4629
4630 if ( options.collapsible && clickedIsActive ) {
4631 animOptions = {
4632 toShow: $( [] ),
4633 toHide: toHide,
4634 complete: complete,
4635 down: down,
4636 autoHeight: options.autoHeight || options.fillSpace
4637 };
4638 } else {
4639 animOptions = {
4640 toShow: toShow,
4641 toHide: toHide,
4642 complete: complete,
4643 down: down,
4644 autoHeight: options.autoHeight || options.fillSpace
4645 };
4646 }
4647
4648 if ( !options.proxied ) {
4649 options.proxied = options.animated;
4650 }
4651
4652 if ( !options.proxiedDuration ) {
4653 options.proxiedDuration = options.duration;
4654 }
4655
4656 options.animated = $.isFunction( options.proxied ) ?
4657 options.proxied( animOptions ) :
4658 options.proxied;
4659
4660 options.duration = $.isFunction( options.proxiedDuration ) ?
4661 options.proxiedDuration( animOptions ) :
4662 options.proxiedDuration;
4663
4664 var animations = $.ui.accordion.animations,
4665 duration = options.duration,
4666 easing = options.animated;
4667
4668 if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
4669 easing = "slide";
4670 }
4671 if ( !animations[ easing ] ) {
4672 animations[ easing ] = function( options ) {
4673 this.slide( options, {
4674 easing: easing,
4675 duration: duration || 700
4676 });
4677 };
4678 }
4679
4680 animations[ easing ]( animOptions );
4681 } else {
4682 if ( options.collapsible && clickedIsActive ) {
4683 toShow.toggle();
4684 } else {
4685 toHide.hide();
4686 toShow.show();
4687 }
4688
4689 complete( true );
4690 }
4691
4692 // TODO assert that the blur and focus triggers are really necessary, remove otherwise
4693 toHide.prev()
4694 .attr({
4695 "aria-expanded": "false",
4696 "aria-selected": "false",
4697 tabIndex: -1
4698 })
4699 .blur();
4700 toShow.prev()
4701 .attr({
4702 "aria-expanded": "true",
4703 "aria-selected": "true",
4704 tabIndex: 0
4705 })
4706 .focus();
4707 },
4708
4709 _completed: function( cancel ) {
4710 this.running = cancel ? 0 : --this.running;
4711 if ( this.running ) {
4712 return;
4713 }
4714
4715 if ( this.options.clearStyle ) {
4716 this.toShow.add( this.toHide ).css({
4717 height: "",
4718 overflow: ""
4719 });
4720 }
4721
4722 // other classes are removed before the animation; this one needs to stay until completed
4723 this.toHide.removeClass( "ui-accordion-content-active" );
4724 // Work around for rendering bug in IE (#5421)
4725 if ( this.toHide.length ) {
4726 this.toHide.parent()[0].className = this.toHide.parent()[0].className;
4727 }
4728
4729 this._trigger( "change", null, this.data );
4730 }
4731 });
4732
4733 $.extend( $.ui.accordion, {
4734 version: "1.8.11",
4735 animations: {
4736 slide: function( options, additions ) {
4737 options = $.extend({
4738 easing: "swing",
4739 duration: 300
4740 }, options, additions );
4741 if ( !options.toHide.size() ) {
4742 options.toShow.animate({
4743 height: "show",
4744 paddingTop: "show",
4745 paddingBottom: "show"
4746 }, options );
4747 return;
4748 }
4749 if ( !options.toShow.size() ) {
4750 options.toHide.animate({
4751 height: "hide",
4752 paddingTop: "hide",
4753 paddingBottom: "hide"
4754 }, options );
4755 return;
4756 }
4757 var overflow = options.toShow.css( "overflow" ),
4758 percentDone = 0,
4759 showProps = {},
4760 hideProps = {},
4761 fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
4762 originalWidth;
4763 // fix width before calculating height of hidden element
4764 var s = options.toShow;
4765 originalWidth = s[0].style.width;
4766 s.width( parseInt( s.parent().width(), 10 )
4767 - parseInt( s.css( "paddingLeft" ), 10 )
4768 - parseInt( s.css( "paddingRight" ), 10 )
4769 - ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
4770 - ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
4771
4772 $.each( fxAttrs, function( i, prop ) {
4773 hideProps[ prop ] = "hide";
4774
4775 var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
4776 showProps[ prop ] = {
4777 value: parts[ 1 ],
4778 unit: parts[ 2 ] || "px"
4779 };
4780 });
4781 options.toShow.css({ height: 0, overflow: "hidden" }).show();
4782 options.toHide
4783 .filter( ":hidden" )
4784 .each( options.complete )
4785 .end()
4786 .filter( ":visible" )
4787 .animate( hideProps, {
4788 step: function( now, settings ) {
4789 // only calculate the percent when animating height
4790 // IE gets very inconsistent results when animating elements
4791 // with small values, which is common for padding
4792 if ( settings.prop == "height" ) {
4793 percentDone = ( settings.end - settings.start === 0 ) ? 0 :
4794 ( settings.now - settings.start ) / ( settings.end - settings.start );
4795 }
4796
4797 options.toShow[ 0 ].style[ settings.prop ] =
4798 ( percentDone * showProps[ settings.prop ].value )
4799 + showProps[ settings.prop ].unit;
4800 },
4801 duration: options.duration,
4802 easing: options.easing,
4803 complete: function() {
4804 if ( !options.autoHeight ) {
4805 options.toShow.css( "height", "" );
4806 }
4807 options.toShow.css({
4808 width: originalWidth,
4809 overflow: overflow
4810 });
4811 options.complete();
4812 }
4813 });
4814 },
4815 bounceslide: function( options ) {
4816 this.slide( options, {
4817 easing: options.down ? "easeOutBounce" : "swing",
4818 duration: options.down ? 1000 : 200
4819 });
4820 }
4821 }
4822 });
4823
4824 })( jQuery );
4825 /*
4826 * jQuery UI Autocomplete 1.8.11
4827 *
4828 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
4829 * Dual licensed under the MIT or GPL Version 2 licenses.
4830 * http://jquery.org/license
4831 *
4832 * http://docs.jquery.com/UI/Autocomplete
4833 *
4834 * Depends:
4835 * jquery.ui.core.js
4836 * jquery.ui.widget.js
4837 * jquery.ui.position.js
4838 */
4839 (function( $, undefined ) {
4840
4841 // used to prevent race conditions with remote data sources
4842 var requestIndex = 0;
4843
4844 $.widget( "ui.autocomplete", {
4845 options: {
4846 appendTo: "body",
4847 autoFocus: false,
4848 delay: 300,
4849 minLength: 1,
4850 position: {
4851 my: "left top",
4852 at: "left bottom",
4853 collision: "none"
4854 },
4855 source: null
4856 },
4857
4858 pending: 0,
4859
4860 _create: function() {
4861 var self = this,
4862 doc = this.element[ 0 ].ownerDocument,
4863 suppressKeyPress;
4864
4865 this.element
4866 .addClass( "ui-autocomplete-input" )
4867 .attr( "autocomplete", "off" )
4868 // TODO verify these actually work as intended
4869 .attr({
4870 role: "textbox",
4871 "aria-autocomplete": "list",
4872 "aria-haspopup": "true"
4873 })
4874 .bind( "keydown.autocomplete", function( event ) {
4875 if ( self.options.disabled || self.element.attr( "readonly" ) ) {
4876 return;
4877 }
4878
4879 suppressKeyPress = false;
4880 var keyCode = $.ui.keyCode;
4881 switch( event.keyCode ) {
4882 case keyCode.PAGE_UP:
4883 self._move( "previousPage", event );
4884 break;
4885 case keyCode.PAGE_DOWN:
4886 self._move( "nextPage", event );
4887 break;
4888 case keyCode.UP:
4889 self._move( "previous", event );
4890 // prevent moving cursor to beginning of text field in some browsers
4891 event.preventDefault();
4892 break;
4893 case keyCode.DOWN:
4894 self._move( "next", event );
4895 // prevent moving cursor to end of text field in some browsers
4896 event.preventDefault();
4897 break;
4898 case keyCode.ENTER:
4899 case keyCode.NUMPAD_ENTER:
4900 // when menu is open and has focus
4901 if ( self.menu.active ) {
4902 // #6055 - Opera still allows the keypress to occur
4903 // which causes forms to submit
4904 suppressKeyPress = true;
4905 event.preventDefault();
4906 }
4907 //passthrough - ENTER and TAB both select the current element
4908 case keyCode.TAB:
4909 if ( !self.menu.active ) {
4910 return;
4911 }
4912 self.menu.select( event );
4913 break;
4914 case keyCode.ESCAPE:
4915 self.element.val( self.term );
4916 self.close( event );
4917 break;
4918 default:
4919 // keypress is triggered before the input value is changed
4920 clearTimeout( self.searching );
4921 self.searching = setTimeout(function() {
4922 // only search if the value has changed
4923 if ( self.term != self.element.val() ) {
4924 self.selectedItem = null;
4925 self.search( null, event );
4926 }
4927 }, self.options.delay );
4928 break;
4929 }
4930 })
4931 .bind( "keypress.autocomplete", function( event ) {
4932 if ( suppressKeyPress ) {
4933 suppressKeyPress = false;
4934 event.preventDefault();
4935 }
4936 })
4937 .bind( "focus.autocomplete", function() {
4938 if ( self.options.disabled ) {
4939 return;
4940 }
4941
4942 self.selectedItem = null;
4943 self.previous = self.element.val();
4944 })
4945 .bind( "blur.autocomplete", function( event ) {
4946 if ( self.options.disabled ) {
4947 return;
4948 }
4949
4950 clearTimeout( self.searching );
4951 // clicks on the menu (or a button to trigger a search) will cause a blur event
4952 self.closing = setTimeout(function() {
4953 self.close( event );
4954 self._change( event );
4955 }, 150 );
4956 });
4957 this._initSource();
4958 this.response = function() {
4959 return self._response.apply( self, arguments );
4960 };
4961 this.menu = $( "<ul></ul>" )
4962 .addClass( "ui-autocomplete" )
4963 .appendTo( $( this.options.appendTo || "body", doc )[0] )
4964 // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
4965 .mousedown(function( event ) {
4966 // clicking on the scrollbar causes focus to shift to the body
4967 // but we can't detect a mouseup or a click immediately afterward
4968 // so we have to track the next mousedown and close the menu if
4969 // the user clicks somewhere outside of the autocomplete
4970 var menuElement = self.menu.element[ 0 ];
4971 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
4972 setTimeout(function() {
4973 $( document ).one( 'mousedown', function( event ) {
4974 if ( event.target !== self.element[ 0 ] &&
4975 event.target !== menuElement &&
4976 !$.ui.contains( menuElement, event.target ) ) {
4977 self.close();
4978 }
4979 });
4980 }, 1 );
4981 }
4982
4983 // use another timeout to make sure the blur-event-handler on the input was already triggered
4984 setTimeout(function() {
4985 clearTimeout( self.closing );
4986 }, 13);
4987 })
4988 .menu({
4989 focus: function( event, ui ) {
4990 var item = ui.item.data( "item.autocomplete" );
4991 if ( false !== self._trigger( "focus", event, { item: item } ) ) {
4992 // use value to match what will end up in the input, if it was a key event
4993 if ( /^key/.test(event.originalEvent.type) ) {
4994 self.element.val( item.value );
4995 }
4996 }
4997 },
4998 selected: function( event, ui ) {
4999 var item = ui.item.data( "item.autocomplete" ),
5000 previous = self.previous;
5001
5002 // only trigger when focus was lost (click on menu)
5003 if ( self.element[0] !== doc.activeElement ) {
5004 self.element.focus();
5005 self.previous = previous;
5006 // #6109 - IE triggers two focus events and the second
5007 // is asynchronous, so we need to reset the previous
5008 // term synchronously and asynchronously :-(
5009 setTimeout(function() {
5010 self.previous = previous;
5011 self.selectedItem = item;
5012 }, 1);
5013 }
5014
5015 if ( false !== self._trigger( "select", event, { item: item } ) ) {
5016 self.element.val( item.value );
5017 }
5018 // reset the term after the select event
5019 // this allows custom select handling to work properly
5020 self.term = self.element.val();
5021
5022 self.close( event );
5023 self.selectedItem = item;
5024 },
5025 blur: function( event, ui ) {
5026 // don't set the value of the text field if it's already correct
5027 // this prevents moving the cursor unnecessarily
5028 if ( self.menu.element.is(":visible") &&
5029 ( self.element.val() !== self.term ) ) {
5030 self.element.val( self.term );
5031 }
5032 }
5033 })
5034 .zIndex( this.element.zIndex() + 1 )
5035 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
5036 .css({ top: 0, left: 0 })
5037 .hide()
5038 .data( "menu" );
5039 if ( $.fn.bgiframe ) {
5040 this.menu.element.bgiframe();
5041 }
5042 },
5043
5044 destroy: function() {
5045 this.element
5046 .removeClass( "ui-autocomplete-input" )
5047 .removeAttr( "autocomplete" )
5048 .removeAttr( "role" )
5049 .removeAttr( "aria-autocomplete" )
5050 .removeAttr( "aria-haspopup" );
5051 this.menu.element.remove();
5052 $.Widget.prototype.destroy.call( this );
5053 },
5054
5055 _setOption: function( key, value ) {
5056 $.Widget.prototype._setOption.apply( this, arguments );
5057 if ( key === "source" ) {
5058 this._initSource();
5059 }
5060 if ( key === "appendTo" ) {
5061 this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
5062 }
5063 if ( key === "disabled" && value && this.xhr ) {
5064 this.xhr.abort();
5065 }
5066 },
5067
5068 _initSource: function() {
5069 var self = this,
5070 array,
5071 url;
5072 if ( $.isArray(this.options.source) ) {
5073 array = this.options.source;
5074 this.source = function( request, response ) {
5075 response( $.ui.autocomplete.filter(array, request.term) );
5076 };
5077 } else if ( typeof this.options.source === "string" ) {
5078 url = this.options.source;
5079 this.source = function( request, response ) {
5080 if ( self.xhr ) {
5081 self.xhr.abort();
5082 }
5083 self.xhr = $.ajax({
5084 url: url,
5085 data: request,
5086 dataType: "json",
5087 autocompleteRequest: ++requestIndex,
5088 success: function( data, status ) {
5089 if ( this.autocompleteRequest === requestIndex ) {
5090 response( data );
5091 }
5092 },
5093 error: function() {
5094 if ( this.autocompleteRequest === requestIndex ) {
5095 response( [] );
5096 }
5097 }
5098 });
5099 };
5100 } else {
5101 this.source = this.options.source;
5102 }
5103 },
5104
5105 search: function( value, event ) {
5106 value = value != null ? value : this.element.val();
5107
5108 // always save the actual value, not the one passed as an argument
5109 this.term = this.element.val();
5110
5111 if ( value.length < this.options.minLength ) {
5112 return this.close( event );
5113 }
5114
5115 clearTimeout( this.closing );
5116 if ( this._trigger( "search", event ) === false ) {
5117 return;
5118 }
5119
5120 return this._search( value );
5121 },
5122
5123 _search: function( value ) {
5124 this.pending++;
5125 this.element.addClass( "ui-autocomplete-loading" );
5126
5127 this.source( { term: value }, this.response );
5128 },
5129
5130 _response: function( content ) {
5131 if ( !this.options.disabled && content && content.length ) {
5132 content = this._normalize( content );
5133 this._suggest( content );
5134 this._trigger( "open" );
5135 } else {
5136 this.close();
5137 }
5138 this.pending--;
5139 if ( !this.pending ) {
5140 this.element.removeClass( "ui-autocomplete-loading" );
5141 }
5142 },
5143
5144 close: function( event ) {
5145 clearTimeout( this.closing );
5146 if ( this.menu.element.is(":visible") ) {
5147 this.menu.element.hide();
5148 this.menu.deactivate();
5149 this._trigger( "close", event );
5150 }
5151 },
5152
5153 _change: function( event ) {
5154 if ( this.previous !== this.element.val() ) {
5155 this._trigger( "change", event, { item: this.selectedItem } );
5156 }
5157 },
5158
5159 _normalize: function( items ) {
5160 // assume all items have the right format when the first item is complete
5161 if ( items.length && items[0].label && items[0].value ) {
5162 return items;
5163 }
5164 return $.map( items, function(item) {
5165 if ( typeof item === "string" ) {
5166 return {
5167 label: item,
5168 value: item
5169 };
5170 }
5171 return $.extend({
5172 label: item.label || item.value,
5173 value: item.value || item.label
5174 }, item );
5175 });
5176 },
5177
5178 _suggest: function( items ) {
5179 var ul = this.menu.element
5180 .empty()
5181 .zIndex( this.element.zIndex() + 1 );
5182 this._renderMenu( ul, items );
5183 // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
5184 this.menu.deactivate();
5185 this.menu.refresh();
5186
5187 // size and position menu
5188 ul.show();
5189 this._resizeMenu();
5190 ul.position( $.extend({
5191 of: this.element
5192 }, this.options.position ));
5193
5194 if ( this.options.autoFocus ) {
5195 this.menu.next( new $.Event("mouseover") );
5196 }
5197 },
5198
5199 _resizeMenu: function() {
5200 var ul = this.menu.element;
5201 ul.outerWidth( Math.max(
5202 ul.width( "" ).outerWidth(),
5203 this.element.outerWidth()
5204 ) );
5205 },
5206
5207 _renderMenu: function( ul, items ) {
5208 var self = this;
5209 $.each( items, function( index, item ) {
5210 self._renderItem( ul, item );
5211 });
5212 },
5213
5214 _renderItem: function( ul, item) {
5215 return $( "<li></li>" )
5216 .data( "item.autocomplete", item )
5217 .append( $( "<a></a>" ).text( item.label ) )
5218 .appendTo( ul );
5219 },
5220
5221 _move: function( direction, event ) {
5222 if ( !this.menu.element.is(":visible") ) {
5223 this.search( null, event );
5224 return;
5225 }
5226 if ( this.menu.first() && /^previous/.test(direction) ||
5227 this.menu.last() && /^next/.test(direction) ) {
5228 this.element.val( this.term );
5229 this.menu.deactivate();
5230 return;
5231 }
5232 this.menu[ direction ]( event );
5233 },
5234
5235 widget: function() {
5236 return this.menu.element;
5237 }
5238 });
5239
5240 $.extend( $.ui.autocomplete, {
5241 escapeRegex: function( value ) {
5242 return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
5243 },
5244 filter: function(array, term) {
5245 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
5246 return $.grep( array, function(value) {
5247 return matcher.test( value.label || value.value || value );
5248 });
5249 }
5250 });
5251
5252 }( jQuery ));
5253
5254 /*
5255 * jQuery UI Menu (not officially released)
5256 *
5257 * This widget isn't yet finished and the API is subject to change. We plan to finish
5258 * it for the next release. You're welcome to give it a try anyway and give us feedback,
5259 * as long as you're okay with migrating your code later on. We can help with that, too.
5260 *
5261 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5262 * Dual licensed under the MIT or GPL Version 2 licenses.
5263 * http://jquery.org/license
5264 *
5265 * http://docs.jquery.com/UI/Menu
5266 *
5267 * Depends:
5268 * jquery.ui.core.js
5269 * jquery.ui.widget.js
5270 */
5271 (function($) {
5272
5273 $.widget("ui.menu", {
5274 _create: function() {
5275 var self = this;
5276 this.element
5277 .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
5278 .attr({
5279 role: "listbox",
5280 "aria-activedescendant": "ui-active-menuitem"
5281 })
5282 .click(function( event ) {
5283 if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
5284 return;
5285 }
5286 // temporary
5287 event.preventDefault();
5288 self.select( event );
5289 });
5290 this.refresh();
5291 },
5292
5293 refresh: function() {
5294 var self = this;
5295
5296 // don't refresh list items that are already adapted
5297 var items = this.element.children("li:not(.ui-menu-item):has(a)")
5298 .addClass("ui-menu-item")
5299 .attr("role", "menuitem");
5300
5301 items.children("a")
5302 .addClass("ui-corner-all")
5303 .attr("tabindex", -1)
5304 // mouseenter doesn't work with event delegation
5305 .mouseenter(function( event ) {
5306 self.activate( event, $(this).parent() );
5307 })
5308 .mouseleave(function() {
5309 self.deactivate();
5310 });
5311 },
5312
5313 activate: function( event, item ) {
5314 this.deactivate();
5315 if (this.hasScroll()) {
5316 var offset = item.offset().top - this.element.offset().top,
5317 scroll = this.element.attr("scrollTop"),
5318 elementHeight = this.element.height();
5319 if (offset < 0) {
5320 this.element.attr("scrollTop", scroll + offset);
5321 } else if (offset >= elementHeight) {
5322 this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
5323 }
5324 }
5325 this.active = item.eq(0)
5326 .children("a")
5327 .addClass("ui-state-hover")
5328 .attr("id", "ui-active-menuitem")
5329 .end();
5330 this._trigger("focus", event, { item: item });
5331 },
5332
5333 deactivate: function() {
5334 if (!this.active) { return; }
5335
5336 this.active.children("a")
5337 .removeClass("ui-state-hover")
5338 .removeAttr("id");
5339 this._trigger("blur");
5340 this.active = null;
5341 },
5342
5343 next: function(event) {
5344 this.move("next", ".ui-menu-item:first", event);
5345 },
5346
5347 previous: function(event) {
5348 this.move("prev", ".ui-menu-item:last", event);
5349 },
5350
5351 first: function() {
5352 return this.active && !this.active.prevAll(".ui-menu-item").length;
5353 },
5354
5355 last: function() {
5356 return this.active && !this.active.nextAll(".ui-menu-item").length;
5357 },
5358
5359 move: function(direction, edge, event) {
5360 if (!this.active) {
5361 this.activate(event, this.element.children(edge));
5362 return;
5363 }
5364 var next = this.active[direction + "All"](".ui-menu-item").eq(0);
5365 if (next.length) {
5366 this.activate(event, next);
5367 } else {
5368 this.activate(event, this.element.children(edge));
5369 }
5370 },
5371
5372 // TODO merge with previousPage
5373 nextPage: function(event) {
5374 if (this.hasScroll()) {
5375 // TODO merge with no-scroll-else
5376 if (!this.active || this.last()) {
5377 this.activate(event, this.element.children(".ui-menu-item:first"));
5378 return;
5379 }
5380 var base = this.active.offset().top,
5381 height = this.element.height(),
5382 result = this.element.children(".ui-menu-item").filter(function() {
5383 var close = $(this).offset().top - base - height + $(this).height();
5384 // TODO improve approximation
5385 return close < 10 && close > -10;
5386 });
5387
5388 // TODO try to catch this earlier when scrollTop indicates the last page anyway
5389 if (!result.length) {
5390 result = this.element.children(".ui-menu-item:last");
5391 }
5392 this.activate(event, result);
5393 } else {
5394 this.activate(event, this.element.children(".ui-menu-item")
5395 .filter(!this.active || this.last() ? ":first" : ":last"));
5396 }
5397 },
5398
5399 // TODO merge with nextPage
5400 previousPage: function(event) {
5401 if (this.hasScroll()) {
5402 // TODO merge with no-scroll-else
5403 if (!this.active || this.first()) {
5404 this.activate(event, this.element.children(".ui-menu-item:last"));
5405 return;
5406 }
5407
5408 var base = this.active.offset().top,
5409 height = this.element.height();
5410 result = this.element.children(".ui-menu-item").filter(function() {
5411 var close = $(this).offset().top - base + height - $(this).height();
5412 // TODO improve approximation
5413 return close < 10 && close > -10;
5414 });
5415
5416 // TODO try to catch this earlier when scrollTop indicates the last page anyway
5417 if (!result.length) {
5418 result = this.element.children(".ui-menu-item:first");
5419 }
5420 this.activate(event, result);
5421 } else {
5422 this.activate(event, this.element.children(".ui-menu-item")
5423 .filter(!this.active || this.first() ? ":last" : ":first"));
5424 }
5425 },
5426
5427 hasScroll: function() {
5428 return this.element.height() < this.element.attr("scrollHeight");
5429 },
5430
5431 select: function( event ) {
5432 this._trigger("selected", event, { item: this.active });
5433 }
5434 });
5435
5436 }(jQuery));
5437 /*
5438 * jQuery UI Button 1.8.11
5439 *
5440 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5441 * Dual licensed under the MIT or GPL Version 2 licenses.
5442 * http://jquery.org/license
5443 *
5444 * http://docs.jquery.com/UI/Button
5445 *
5446 * Depends:
5447 * jquery.ui.core.js
5448 * jquery.ui.widget.js
5449 */
5450 (function( $, undefined ) {
5451
5452 var lastActive,
5453 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
5454 stateClasses = "ui-state-hover ui-state-active ",
5455 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",
5456 formResetHandler = function( event ) {
5457 $( ":ui-button", event.target.form ).each(function() {
5458 var inst = $( this ).data( "button" );
5459 setTimeout(function() {
5460 inst.refresh();
5461 }, 1 );
5462 });
5463 },
5464 radioGroup = function( radio ) {
5465 var name = radio.name,
5466 form = radio.form,
5467 radios = $( [] );
5468 if ( name ) {
5469 if ( form ) {
5470 radios = $( form ).find( "[name='" + name + "']" );
5471 } else {
5472 radios = $( "[name='" + name + "']", radio.ownerDocument )
5473 .filter(function() {
5474 return !this.form;
5475 });
5476 }
5477 }
5478 return radios;
5479 };
5480
5481 $.widget( "ui.button", {
5482 options: {
5483 disabled: null,
5484 text: true,
5485 label: null,
5486 icons: {
5487 primary: null,
5488 secondary: null
5489 }
5490 },
5491 _create: function() {
5492 this.element.closest( "form" )
5493 .unbind( "reset.button" )
5494 .bind( "reset.button", formResetHandler );
5495
5496 if ( typeof this.options.disabled !== "boolean" ) {
5497 this.options.disabled = this.element.attr( "disabled" );
5498 }
5499
5500 this._determineButtonType();
5501 this.hasTitle = !!this.buttonElement.attr( "title" );
5502
5503 var self = this,
5504 options = this.options,
5505 toggleButton = this.type === "checkbox" || this.type === "radio",
5506 hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
5507 focusClass = "ui-state-focus";
5508
5509 if ( options.label === null ) {
5510 options.label = this.buttonElement.html();
5511 }
5512
5513 if ( this.element.is( ":disabled" ) ) {
5514 options.disabled = true;
5515 }
5516
5517 this.buttonElement
5518 .addClass( baseClasses )
5519 .attr( "role", "button" )
5520 .bind( "mouseenter.button", function() {
5521 if ( options.disabled ) {
5522 return;
5523 }
5524 $( this ).addClass( "ui-state-hover" );
5525 if ( this === lastActive ) {
5526 $( this ).addClass( "ui-state-active" );
5527 }
5528 })
5529 .bind( "mouseleave.button", function() {
5530 if ( options.disabled ) {
5531 return;
5532 }
5533 $( this ).removeClass( hoverClass );
5534 })
5535 .bind( "focus.button", function() {
5536 // no need to check disabled, focus won't be triggered anyway
5537 $( this ).addClass( focusClass );
5538 })
5539 .bind( "blur.button", function() {
5540 $( this ).removeClass( focusClass );
5541 });
5542
5543 if ( toggleButton ) {
5544 this.element.bind( "change.button", function() {
5545 self.refresh();
5546 });
5547 }
5548
5549 if ( this.type === "checkbox" ) {
5550 this.buttonElement.bind( "click.button", function() {
5551 if ( options.disabled ) {
5552 return false;
5553 }
5554 $( this ).toggleClass( "ui-state-active" );
5555 self.buttonElement.attr( "aria-pressed", self.element[0].checked );
5556 });
5557 } else if ( this.type === "radio" ) {
5558 this.buttonElement.bind( "click.button", function() {
5559 if ( options.disabled ) {
5560 return false;
5561 }
5562 $( this ).addClass( "ui-state-active" );
5563 self.buttonElement.attr( "aria-pressed", true );
5564
5565 var radio = self.element[ 0 ];
5566 radioGroup( radio )
5567 .not( radio )
5568 .map(function() {
5569 return $( this ).button( "widget" )[ 0 ];
5570 })
5571 .removeClass( "ui-state-active" )
5572 .attr( "aria-pressed", false );
5573 });
5574 } else {
5575 this.buttonElement
5576 .bind( "mousedown.button", function() {
5577 if ( options.disabled ) {
5578 return false;
5579 }
5580 $( this ).addClass( "ui-state-active" );
5581 lastActive = this;
5582 $( document ).one( "mouseup", function() {
5583 lastActive = null;
5584 });
5585 })
5586 .bind( "mouseup.button", function() {
5587 if ( options.disabled ) {
5588 return false;
5589 }
5590 $( this ).removeClass( "ui-state-active" );
5591 })
5592 .bind( "keydown.button", function(event) {
5593 if ( options.disabled ) {
5594 return false;
5595 }
5596 if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
5597 $( this ).addClass( "ui-state-active" );
5598 }
5599 })
5600 .bind( "keyup.button", function() {
5601 $( this ).removeClass( "ui-state-active" );
5602 });
5603
5604 if ( this.buttonElement.is("a") ) {
5605 this.buttonElement.keyup(function(event) {
5606 if ( event.keyCode === $.ui.keyCode.SPACE ) {
5607 // TODO pass through original event correctly (just as 2nd argument doesn't work)
5608 $( this ).click();
5609 }
5610 });
5611 }
5612 }
5613
5614 // TODO: pull out $.Widget's handling for the disabled option into
5615 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
5616 // be overridden by individual plugins
5617 this._setOption( "disabled", options.disabled );
5618 },
5619
5620 _determineButtonType: function() {
5621
5622 if ( this.element.is(":checkbox") ) {
5623 this.type = "checkbox";
5624 } else {
5625 if ( this.element.is(":radio") ) {
5626 this.type = "radio";
5627 } else {
5628 if ( this.element.is("input") ) {
5629 this.type = "input";
5630 } else {
5631 this.type = "button";
5632 }
5633 }
5634 }
5635
5636 if ( this.type === "checkbox" || this.type === "radio" ) {
5637 // we don't search against the document in case the element
5638 // is disconnected from the DOM
5639 var ancestor = this.element.parents().filter(":last"),
5640 labelSelector = "label[for=" + this.element.attr("id") + "]";
5641 this.buttonElement = ancestor.find( labelSelector );
5642 if ( !this.buttonElement.length ) {
5643 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
5644 this.buttonElement = ancestor.filter( labelSelector );
5645 if ( !this.buttonElement.length ) {
5646 this.buttonElement = ancestor.find( labelSelector );
5647 }
5648 }
5649 this.element.addClass( "ui-helper-hidden-accessible" );
5650
5651 var checked = this.element.is( ":checked" );
5652 if ( checked ) {
5653 this.buttonElement.addClass( "ui-state-active" );
5654 }
5655 this.buttonElement.attr( "aria-pressed", checked );
5656 } else {
5657 this.buttonElement = this.element;
5658 }
5659 },
5660
5661 widget: function() {
5662 return this.buttonElement;
5663 },
5664
5665 destroy: function() {
5666 this.element
5667 .removeClass( "ui-helper-hidden-accessible" );
5668 this.buttonElement
5669 .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
5670 .removeAttr( "role" )
5671 .removeAttr( "aria-pressed" )
5672 .html( this.buttonElement.find(".ui-button-text").html() );
5673
5674 if ( !this.hasTitle ) {
5675 this.buttonElement.removeAttr( "title" );
5676 }
5677
5678 $.Widget.prototype.destroy.call( this );
5679 },
5680
5681 _setOption: function( key, value ) {
5682 $.Widget.prototype._setOption.apply( this, arguments );
5683 if ( key === "disabled" ) {
5684 if ( value ) {
5685 this.element.attr( "disabled", true );
5686 } else {
5687 this.element.removeAttr( "disabled" );
5688 }
5689 }
5690 this._resetButton();
5691 },
5692
5693 refresh: function() {
5694 var isDisabled = this.element.is( ":disabled" );
5695 if ( isDisabled !== this.options.disabled ) {
5696 this._setOption( "disabled", isDisabled );
5697 }
5698 if ( this.type === "radio" ) {
5699 radioGroup( this.element[0] ).each(function() {
5700 if ( $( this ).is( ":checked" ) ) {
5701 $( this ).button( "widget" )
5702 .addClass( "ui-state-active" )
5703 .attr( "aria-pressed", true );
5704 } else {
5705 $( this ).button( "widget" )
5706 .removeClass( "ui-state-active" )
5707 .attr( "aria-pressed", false );
5708 }
5709 });
5710 } else if ( this.type === "checkbox" ) {
5711 if ( this.element.is( ":checked" ) ) {
5712 this.buttonElement
5713 .addClass( "ui-state-active" )
5714 .attr( "aria-pressed", true );
5715 } else {
5716 this.buttonElement
5717 .removeClass( "ui-state-active" )
5718 .attr( "aria-pressed", false );
5719 }
5720 }
5721 },
5722
5723 _resetButton: function() {
5724 if ( this.type === "input" ) {
5725 if ( this.options.label ) {
5726 this.element.val( this.options.label );
5727 }
5728 return;
5729 }
5730 var buttonElement = this.buttonElement.removeClass( typeClasses ),
5731 buttonText = $( "<span></span>" )
5732 .addClass( "ui-button-text" )
5733 .html( this.options.label )
5734 .appendTo( buttonElement.empty() )
5735 .text(),
5736 icons = this.options.icons,
5737 multipleIcons = icons.primary && icons.secondary,
5738 buttonClasses = [];
5739
5740 if ( icons.primary || icons.secondary ) {
5741 if ( this.options.text ) {
5742 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
5743 }
5744
5745 if ( icons.primary ) {
5746 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
5747 }
5748
5749 if ( icons.secondary ) {
5750 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
5751 }
5752
5753 if ( !this.options.text ) {
5754 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
5755
5756 if ( !this.hasTitle ) {
5757 buttonElement.attr( "title", buttonText );
5758 }
5759 }
5760 } else {
5761 buttonClasses.push( "ui-button-text-only" );
5762 }
5763 buttonElement.addClass( buttonClasses.join( " " ) );
5764 }
5765 });
5766
5767 $.widget( "ui.buttonset", {
5768 options: {
5769 items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
5770 },
5771
5772 _create: function() {
5773 this.element.addClass( "ui-buttonset" );
5774 },
5775
5776 _init: function() {
5777 this.refresh();
5778 },
5779
5780 _setOption: function( key, value ) {
5781 if ( key === "disabled" ) {
5782 this.buttons.button( "option", key, value );
5783 }
5784
5785 $.Widget.prototype._setOption.apply( this, arguments );
5786 },
5787
5788 refresh: function() {
5789 this.buttons = this.element.find( this.options.items )
5790 .filter( ":ui-button" )
5791 .button( "refresh" )
5792 .end()
5793 .not( ":ui-button" )
5794 .button()
5795 .end()
5796 .map(function() {
5797 return $( this ).button( "widget" )[ 0 ];
5798 })
5799 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
5800 .filter( ":first" )
5801 .addClass( "ui-corner-left" )
5802 .end()
5803 .filter( ":last" )
5804 .addClass( "ui-corner-right" )
5805 .end()
5806 .end();
5807 },
5808
5809 destroy: function() {
5810 this.element.removeClass( "ui-buttonset" );
5811 this.buttons
5812 .map(function() {
5813 return $( this ).button( "widget" )[ 0 ];
5814 })
5815 .removeClass( "ui-corner-left ui-corner-right" )
5816 .end()
5817 .button( "destroy" );
5818
5819 $.Widget.prototype.destroy.call( this );
5820 }
5821 });
5822
5823 }( jQuery ) );
5824 /*
5825 * jQuery UI Dialog 1.8.11
5826 *
5827 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5828 * Dual licensed under the MIT or GPL Version 2 licenses.
5829 * http://jquery.org/license
5830 *
5831 * http://docs.jquery.com/UI/Dialog
5832 *
5833 * Depends:
5834 * jquery.ui.core.js
5835 * jquery.ui.widget.js
5836 * jquery.ui.button.js
5837 * jquery.ui.draggable.js
5838 * jquery.ui.mouse.js
5839 * jquery.ui.position.js
5840 * jquery.ui.resizable.js
5841 */
5842 (function( $, undefined ) {
5843
5844 var uiDialogClasses =
5845 'ui-dialog ' +
5846 'ui-widget ' +
5847 'ui-widget-content ' +
5848 'ui-corner-all ',
5849 sizeRelatedOptions = {
5850 buttons: true,
5851 height: true,
5852 maxHeight: true,
5853 maxWidth: true,
5854 minHeight: true,
5855 minWidth: true,
5856 width: true
5857 },
5858 resizableRelatedOptions = {
5859 maxHeight: true,
5860 maxWidth: true,
5861 minHeight: true,
5862 minWidth: true
5863 };
5864
5865 $.widget("ui.dialog", {
5866 options: {
5867 autoOpen: true,
5868 buttons: {},
5869 closeOnEscape: true,
5870 closeText: 'close',
5871 dialogClass: '',
5872 draggable: true,
5873 hide: null,
5874 height: 'auto',
5875 maxHeight: false,
5876 maxWidth: false,
5877 minHeight: 150,
5878 minWidth: 150,
5879 modal: false,
5880 position: {
5881 my: 'center',
5882 at: 'center',
5883 collision: 'fit',
5884 // ensure that the titlebar is never outside the document
5885 using: function(pos) {
5886 var topOffset = $(this).css(pos).offset().top;
5887 if (topOffset < 0) {
5888 $(this).css('top', pos.top - topOffset);
5889 }
5890 }
5891 },
5892 resizable: true,
5893 show: null,
5894 stack: true,
5895 title: '',
5896 width: 300,
5897 zIndex: 1000
5898 },
5899
5900 _create: function() {
5901 this.originalTitle = this.element.attr('title');
5902 // #5742 - .attr() might return a DOMElement
5903 if ( typeof this.originalTitle !== "string" ) {
5904 this.originalTitle = "";
5905 }
5906
5907 this.options.title = this.options.title || this.originalTitle;
5908 var self = this,
5909 options = self.options,
5910
5911 title = options.title || '&#160;',
5912 titleId = $.ui.dialog.getTitleId(self.element),
5913
5914 uiDialog = (self.uiDialog = $('<div></div>'))
5915 .appendTo(document.body)
5916 .hide()
5917 .addClass(uiDialogClasses + options.dialogClass)
5918 .css({
5919 zIndex: options.zIndex
5920 })
5921 // setting tabIndex makes the div focusable
5922 // setting outline to 0 prevents a border on focus in Mozilla
5923 .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
5924 if (options.closeOnEscape && event.keyCode &&
5925 event.keyCode === $.ui.keyCode.ESCAPE) {
5926
5927 self.close(event);
5928 event.preventDefault();
5929 }
5930 })
5931 .attr({
5932 role: 'dialog',
5933 'aria-labelledby': titleId
5934 })
5935 .mousedown(function(event) {
5936 self.moveToTop(false, event);
5937 }),
5938
5939 uiDialogContent = self.element
5940 .show()
5941 .removeAttr('title')
5942 .addClass(
5943 'ui-dialog-content ' +
5944 'ui-widget-content')
5945 .appendTo(uiDialog),
5946
5947 uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
5948 .addClass(
5949 'ui-dialog-titlebar ' +
5950 'ui-widget-header ' +
5951 'ui-corner-all ' +
5952 'ui-helper-clearfix'
5953 )
5954 .prependTo(uiDialog),
5955
5956 uiDialogTitlebarClose = $('<a href="#"></a>')
5957 .addClass(
5958 'ui-dialog-titlebar-close ' +
5959 'ui-corner-all'
5960 )
5961 .attr('role', 'button')
5962 .hover(
5963 function() {
5964 uiDialogTitlebarClose.addClass('ui-state-hover');
5965 },
5966 function() {
5967 uiDialogTitlebarClose.removeClass('ui-state-hover');
5968 }
5969 )
5970 .focus(function() {
5971 uiDialogTitlebarClose.addClass('ui-state-focus');
5972 })
5973 .blur(function() {
5974 uiDialogTitlebarClose.removeClass('ui-state-focus');
5975 })
5976 .click(function(event) {
5977 self.close(event);
5978 return false;
5979 })
5980 .appendTo(uiDialogTitlebar),
5981
5982 uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
5983 .addClass(
5984 'ui-icon ' +
5985 'ui-icon-closethick'
5986 )
5987 .text(options.closeText)
5988 .appendTo(uiDialogTitlebarClose),
5989
5990 uiDialogTitle = $('<span></span>')
5991 .addClass('ui-dialog-title')
5992 .attr('id', titleId)
5993 .html(title)
5994 .prependTo(uiDialogTitlebar);
5995
5996 //handling of deprecated beforeclose (vs beforeClose) option
5997 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
5998 //TODO: remove in 1.9pre
5999 if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
6000 options.beforeClose = options.beforeclose;
6001 }
6002
6003 uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
6004
6005 if (options.draggable && $.fn.draggable) {
6006 self._makeDraggable();
6007 }
6008 if (options.resizable && $.fn.resizable) {
6009 self._makeResizable();
6010 }
6011
6012 self._createButtons(options.buttons);
6013 self._isOpen = false;
6014
6015 if ($.fn.bgiframe) {
6016 uiDialog.bgiframe();
6017 }
6018 },
6019
6020 _init: function() {
6021 if ( this.options.autoOpen ) {
6022 this.open();
6023 }
6024 },
6025
6026 destroy: function() {
6027 var self = this;
6028
6029 if (self.overlay) {
6030 self.overlay.destroy();
6031 }
6032 self.uiDialog.hide();
6033 self.element
6034 .unbind('.dialog')
6035 .removeData('dialog')
6036 .removeClass('ui-dialog-content ui-widget-content')
6037 .hide().appendTo('body');
6038 self.uiDialog.remove();
6039
6040 if (self.originalTitle) {
6041 self.element.attr('title', self.originalTitle);
6042 }
6043
6044 return self;
6045 },
6046
6047 widget: function() {
6048 return this.uiDialog;
6049 },
6050
6051 close: function(event) {
6052 var self = this,
6053 maxZ, thisZ;
6054
6055 if (false === self._trigger('beforeClose', event)) {
6056 return;
6057 }
6058
6059 if (self.overlay) {
6060 self.overlay.destroy();
6061 }
6062 self.uiDialog.unbind('keypress.ui-dialog');
6063
6064 self._isOpen = false;
6065
6066 if (self.options.hide) {
6067 self.uiDialog.hide(self.options.hide, function() {
6068 self._trigger('close', event);
6069 });
6070 } else {
6071 self.uiDialog.hide();
6072 self._trigger('close', event);
6073 }
6074
6075 $.ui.dialog.overlay.resize();
6076
6077 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
6078 if (self.options.modal) {
6079 maxZ = 0;
6080 $('.ui-dialog').each(function() {
6081 if (this !== self.uiDialog[0]) {
6082 thisZ = $(this).css('z-index');
6083 if(!isNaN(thisZ)) {
6084 maxZ = Math.max(maxZ, thisZ);
6085 }
6086 }
6087 });
6088 $.ui.dialog.maxZ = maxZ;
6089 }
6090
6091 return self;
6092 },
6093
6094 isOpen: function() {
6095 return this._isOpen;
6096 },
6097
6098 // the force parameter allows us to move modal dialogs to their correct
6099 // position on open
6100 moveToTop: function(force, event) {
6101 var self = this,
6102 options = self.options,
6103 saveScroll;
6104
6105 if ((options.modal && !force) ||
6106 (!options.stack && !options.modal)) {
6107 return self._trigger('focus', event);
6108 }
6109
6110 if (options.zIndex > $.ui.dialog.maxZ) {
6111 $.ui.dialog.maxZ = options.zIndex;
6112 }
6113 if (self.overlay) {
6114 $.ui.dialog.maxZ += 1;
6115 self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
6116 }
6117
6118 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
6119 // http://ui.jquery.com/bugs/ticket/3193
6120 saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
6121 $.ui.dialog.maxZ += 1;
6122 self.uiDialog.css('z-index', $.ui.dialog.maxZ);
6123 self.element.attr(saveScroll);
6124 self._trigger('focus', event);
6125
6126 return self;
6127 },
6128
6129 open: function() {
6130 if (this._isOpen) { return; }
6131
6132 var self = this,
6133 options = self.options,
6134 uiDialog = self.uiDialog;
6135
6136 self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
6137 self._size();
6138 self._position(options.position);
6139 uiDialog.show(options.show);
6140 self.moveToTop(true);
6141
6142 // prevent tabbing out of modal dialogs
6143 if (options.modal) {
6144 uiDialog.bind('keypress.ui-dialog', function(event) {
6145 if (event.keyCode !== $.ui.keyCode.TAB) {
6146 return;
6147 }
6148
6149 var tabbables = $(':tabbable', this),
6150 first = tabbables.filter(':first'),
6151 last = tabbables.filter(':last');
6152
6153 if (event.target === last[0] && !event.shiftKey) {
6154 first.focus(1);
6155 return false;
6156 } else if (event.target === first[0] && event.shiftKey) {
6157 last.focus(1);
6158 return false;
6159 }
6160 });
6161 }
6162
6163 // set focus to the first tabbable element in the content area or the first button
6164 // if there are no tabbable elements, set focus on the dialog itself
6165 $(self.element.find(':tabbable').get().concat(
6166 uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
6167 uiDialog.get()))).eq(0).focus();
6168
6169 self._isOpen = true;
6170 self._trigger('open');
6171
6172 return self;
6173 },
6174
6175 _createButtons: function(buttons) {
6176 var self = this,
6177 hasButtons = false,
6178 uiDialogButtonPane = $('<div></div>')
6179 .addClass(
6180 'ui-dialog-buttonpane ' +
6181 'ui-widget-content ' +
6182 'ui-helper-clearfix'
6183 ),
6184 uiButtonSet = $( "<div></div>" )
6185 .addClass( "ui-dialog-buttonset" )
6186 .appendTo( uiDialogButtonPane );
6187
6188 // if we already have a button pane, remove it
6189 self.uiDialog.find('.ui-dialog-buttonpane').remove();
6190
6191 if (typeof buttons === 'object' && buttons !== null) {
6192 $.each(buttons, function() {
6193 return !(hasButtons = true);
6194 });
6195 }
6196 if (hasButtons) {
6197 $.each(buttons, function(name, props) {
6198 props = $.isFunction( props ) ?
6199 { click: props, text: name } :
6200 props;
6201 var button = $('<button type="button"></button>')
6202 .attr( props, true )
6203 .unbind('click')
6204 .click(function() {
6205 props.click.apply(self.element[0], arguments);
6206 })
6207 .appendTo(uiButtonSet);
6208 if ($.fn.button) {
6209 button.button();
6210 }
6211 });
6212 uiDialogButtonPane.appendTo(self.uiDialog);
6213 }
6214 },
6215
6216 _makeDraggable: function() {
6217 var self = this,
6218 options = self.options,
6219 doc = $(document),
6220 heightBeforeDrag;
6221
6222 function filteredUi(ui) {
6223 return {
6224 position: ui.position,
6225 offset: ui.offset
6226 };
6227 }
6228
6229 self.uiDialog.draggable({
6230 cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
6231 handle: '.ui-dialog-titlebar',
6232 containment: 'document',
6233 start: function(event, ui) {
6234 heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
6235 $(this).height($(this).height()).addClass("ui-dialog-dragging");
6236 self._trigger('dragStart', event, filteredUi(ui));
6237 },
6238 drag: function(event, ui) {
6239 self._trigger('drag', event, filteredUi(ui));
6240 },
6241 stop: function(event, ui) {
6242 options.position = [ui.position.left - doc.scrollLeft(),
6243 ui.position.top - doc.scrollTop()];
6244 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
6245 self._trigger('dragStop', event, filteredUi(ui));
6246 $.ui.dialog.overlay.resize();
6247 }
6248 });
6249 },
6250
6251 _makeResizable: function(handles) {
6252 handles = (handles === undefined ? this.options.resizable : handles);
6253 var self = this,
6254 options = self.options,
6255 // .ui-resizable has position: relative defined in the stylesheet
6256 // but dialogs have to use absolute or fixed positioning
6257 position = self.uiDialog.css('position'),
6258 resizeHandles = (typeof handles === 'string' ?
6259 handles :
6260 'n,e,s,w,se,sw,ne,nw'
6261 );
6262
6263 function filteredUi(ui) {
6264 return {
6265 originalPosition: ui.originalPosition,
6266 originalSize: ui.originalSize,
6267 position: ui.position,
6268 size: ui.size
6269 };
6270 }
6271
6272 self.uiDialog.resizable({
6273 cancel: '.ui-dialog-content',
6274 containment: 'document',
6275 alsoResize: self.element,
6276 maxWidth: options.maxWidth,
6277 maxHeight: options.maxHeight,
6278 minWidth: options.minWidth,
6279 minHeight: self._minHeight(),
6280 handles: resizeHandles,
6281 start: function(event, ui) {
6282 $(this).addClass("ui-dialog-resizing");
6283 self._trigger('resizeStart', event, filteredUi(ui));
6284 },
6285 resize: function(event, ui) {
6286 self._trigger('resize', event, filteredUi(ui));
6287 },
6288 stop: function(event, ui) {
6289 $(this).removeClass("ui-dialog-resizing");
6290 options.height = $(this).height();
6291 options.width = $(this).width();
6292 self._trigger('resizeStop', event, filteredUi(ui));
6293 $.ui.dialog.overlay.resize();
6294 }
6295 })
6296 .css('position', position)
6297 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
6298 },
6299
6300 _minHeight: function() {
6301 var options = this.options;
6302
6303 if (options.height === 'auto') {
6304 return options.minHeight;
6305 } else {
6306 return Math.min(options.minHeight, options.height);
6307 }
6308 },
6309
6310 _position: function(position) {
6311 var myAt = [],
6312 offset = [0, 0],
6313 isVisible;
6314
6315 if (position) {
6316 // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
6317 // if (typeof position == 'string' || $.isArray(position)) {
6318 // myAt = $.isArray(position) ? position : position.split(' ');
6319
6320 if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
6321 myAt = position.split ? position.split(' ') : [position[0], position[1]];
6322 if (myAt.length === 1) {
6323 myAt[1] = myAt[0];
6324 }
6325
6326 $.each(['left', 'top'], function(i, offsetPosition) {
6327 if (+myAt[i] === myAt[i]) {
6328 offset[i] = myAt[i];
6329 myAt[i] = offsetPosition;
6330 }
6331 });
6332
6333 position = {
6334 my: myAt.join(" "),
6335 at: myAt.join(" "),
6336 offset: offset.join(" ")
6337 };
6338 }
6339
6340 position = $.extend({}, $.ui.dialog.prototype.options.position, position);
6341 } else {
6342 position = $.ui.dialog.prototype.options.position;
6343 }
6344
6345 // need to show the dialog to get the actual offset in the position plugin
6346 isVisible = this.uiDialog.is(':visible');
6347 if (!isVisible) {
6348 this.uiDialog.show();
6349 }
6350 this.uiDialog
6351 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
6352 .css({ top: 0, left: 0 })
6353 .position($.extend({ of: window }, position));
6354 if (!isVisible) {
6355 this.uiDialog.hide();
6356 }
6357 },
6358
6359 _setOptions: function( options ) {
6360 var self = this,
6361 resizableOptions = {},
6362 resize = false;
6363
6364 $.each( options, function( key, value ) {
6365 self._setOption( key, value );
6366
6367 if ( key in sizeRelatedOptions ) {
6368 resize = true;
6369 }
6370 if ( key in resizableRelatedOptions ) {
6371 resizableOptions[ key ] = value;
6372 }
6373 });
6374
6375 if ( resize ) {
6376 this._size();
6377 }
6378 if ( this.uiDialog.is( ":data(resizable)" ) ) {
6379 this.uiDialog.resizable( "option", resizableOptions );
6380 }
6381 },
6382
6383 _setOption: function(key, value){
6384 var self = this,
6385 uiDialog = self.uiDialog;
6386
6387 switch (key) {
6388 //handling of deprecated beforeclose (vs beforeClose) option
6389 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
6390 //TODO: remove in 1.9pre
6391 case "beforeclose":
6392 key = "beforeClose";
6393 break;
6394 case "buttons":
6395 self._createButtons(value);
6396 break;
6397 case "closeText":
6398 // ensure that we always pass a string
6399 self.uiDialogTitlebarCloseText.text("" + value);
6400 break;
6401 case "dialogClass":
6402 uiDialog
6403 .removeClass(self.options.dialogClass)
6404 .addClass(uiDialogClasses + value);
6405 break;
6406 case "disabled":
6407 if (value) {
6408 uiDialog.addClass('ui-dialog-disabled');
6409 } else {
6410 uiDialog.removeClass('ui-dialog-disabled');
6411 }
6412 break;
6413 case "draggable":
6414 var isDraggable = uiDialog.is( ":data(draggable)" );
6415 if ( isDraggable && !value ) {
6416 uiDialog.draggable( "destroy" );
6417 }
6418
6419 if ( !isDraggable && value ) {
6420 self._makeDraggable();
6421 }
6422 break;
6423 case "position":
6424 self._position(value);
6425 break;
6426 case "resizable":
6427 // currently resizable, becoming non-resizable
6428 var isResizable = uiDialog.is( ":data(resizable)" );
6429 if (isResizable && !value) {
6430 uiDialog.resizable('destroy');
6431 }
6432
6433 // currently resizable, changing handles
6434 if (isResizable && typeof value === 'string') {
6435 uiDialog.resizable('option', 'handles', value);
6436 }
6437
6438 // currently non-resizable, becoming resizable
6439 if (!isResizable && value !== false) {
6440 self._makeResizable(value);
6441 }
6442 break;
6443 case "title":
6444 // convert whatever was passed in o a string, for html() to not throw up
6445 $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
6446 break;
6447 }
6448
6449 $.Widget.prototype._setOption.apply(self, arguments);
6450 },
6451
6452 _size: function() {
6453 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
6454 * divs will both have width and height set, so we need to reset them
6455 */
6456 var options = this.options,
6457 nonContentHeight,
6458 minContentHeight,
6459 isVisible = this.uiDialog.is( ":visible" );
6460
6461 // reset content sizing
6462 this.element.show().css({
6463 width: 'auto',
6464 minHeight: 0,
6465 height: 0
6466 });
6467
6468 if (options.minWidth > options.width) {
6469 options.width = options.minWidth;
6470 }
6471
6472 // reset wrapper sizing
6473 // determine the height of all the non-content elements
6474 nonContentHeight = this.uiDialog.css({
6475 height: 'auto',
6476 width: options.width
6477 })
6478 .height();
6479 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
6480
6481 if ( options.height === "auto" ) {
6482 // only needed for IE6 support
6483 if ( $.support.minHeight ) {
6484 this.element.css({
6485 minHeight: minContentHeight,
6486 height: "auto"
6487 });
6488 } else {
6489 this.uiDialog.show();
6490 var autoHeight = this.element.css( "height", "auto" ).height();
6491 if ( !isVisible ) {
6492 this.uiDialog.hide();
6493 }
6494 this.element.height( Math.max( autoHeight, minContentHeight ) );
6495 }
6496 } else {
6497 this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
6498 }
6499
6500 if (this.uiDialog.is(':data(resizable)')) {
6501 this.uiDialog.resizable('option', 'minHeight', this._minHeight());
6502 }
6503 }
6504 });
6505
6506 $.extend($.ui.dialog, {
6507 version: "1.8.11",
6508
6509 uuid: 0,
6510 maxZ: 0,
6511
6512 getTitleId: function($el) {
6513 var id = $el.attr('id');
6514 if (!id) {
6515 this.uuid += 1;
6516 id = this.uuid;
6517 }
6518 return 'ui-dialog-title-' + id;
6519 },
6520
6521 overlay: function(dialog) {
6522 this.$el = $.ui.dialog.overlay.create(dialog);
6523 }
6524 });
6525
6526 $.extend($.ui.dialog.overlay, {
6527 instances: [],
6528 // reuse old instances due to IE memory leak with alpha transparency (see #5185)
6529 oldInstances: [],
6530 maxZ: 0,
6531 events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
6532 function(event) { return event + '.dialog-overlay'; }).join(' '),
6533 create: function(dialog) {
6534 if (this.instances.length === 0) {
6535 // prevent use of anchors and inputs
6536 // we use a setTimeout in case the overlay is created from an
6537 // event that we're going to be cancelling (see #2804)
6538 setTimeout(function() {
6539 // handle $(el).dialog().dialog('close') (see #4065)
6540 if ($.ui.dialog.overlay.instances.length) {
6541 $(document).bind($.ui.dialog.overlay.events, function(event) {
6542 // stop events if the z-index of the target is < the z-index of the overlay
6543 // we cannot return true when we don't want to cancel the event (#3523)
6544 if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
6545 return false;
6546 }
6547 });
6548 }
6549 }, 1);
6550
6551 // allow closing by pressing the escape key
6552 $(document).bind('keydown.dialog-overlay', function(event) {
6553 if (dialog.options.closeOnEscape && event.keyCode &&
6554 event.keyCode === $.ui.keyCode.ESCAPE) {
6555
6556 dialog.close(event);
6557 event.preventDefault();
6558 }
6559 });
6560
6561 // handle window resize
6562 $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
6563 }
6564
6565 var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
6566 .appendTo(document.body)
6567 .css({
6568 width: this.width(),
6569 height: this.height()
6570 });
6571
6572 if ($.fn.bgiframe) {
6573 $el.bgiframe();
6574 }
6575
6576 this.instances.push($el);
6577 return $el;
6578 },
6579
6580 destroy: function($el) {
6581 var indexOf = $.inArray($el, this.instances);
6582 if (indexOf != -1){
6583 this.oldInstances.push(this.instances.splice(indexOf, 1)[0]);
6584 }
6585
6586 if (this.instances.length === 0) {
6587 $([document, window]).unbind('.dialog-overlay');
6588 }
6589
6590 $el.remove();
6591
6592 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
6593 var maxZ = 0;
6594 $.each(this.instances, function() {
6595 maxZ = Math.max(maxZ, this.css('z-index'));
6596 });
6597 this.maxZ = maxZ;
6598 },
6599
6600 height: function() {
6601 var scrollHeight,
6602 offsetHeight;
6603 // handle IE 6
6604 if ($.browser.msie && $.browser.version < 7) {
6605 scrollHeight = Math.max(
6606 document.documentElement.scrollHeight,
6607 document.body.scrollHeight
6608 );
6609 offsetHeight = Math.max(
6610 document.documentElement.offsetHeight,
6611 document.body.offsetHeight
6612 );
6613
6614 if (scrollHeight < offsetHeight) {
6615 return $(window).height() + 'px';
6616 } else {
6617 return scrollHeight + 'px';
6618 }
6619 // handle "good" browsers
6620 } else {
6621 return $(document).height() + 'px';
6622 }
6623 },
6624
6625 width: function() {
6626 var scrollWidth,
6627 offsetWidth;
6628 // handle IE 6
6629 if ($.browser.msie && $.browser.version < 7) {
6630 scrollWidth = Math.max(
6631 document.documentElement.scrollWidth,
6632 document.body.scrollWidth
6633 );
6634 offsetWidth = Math.max(
6635 document.documentElement.offsetWidth,
6636 document.body.offsetWidth
6637 );
6638
6639 if (scrollWidth < offsetWidth) {
6640 return $(window).width() + 'px';
6641 } else {
6642 return scrollWidth + 'px';
6643 }
6644 // handle "good" browsers
6645 } else {
6646 return $(document).width() + 'px';
6647 }
6648 },
6649
6650 resize: function() {
6651 /* If the dialog is draggable and the user drags it past the
6652 * right edge of the window, the document becomes wider so we
6653 * need to stretch the overlay. If the user then drags the
6654 * dialog back to the left, the document will become narrower,
6655 * so we need to shrink the overlay to the appropriate size.
6656 * This is handled by shrinking the overlay before setting it
6657 * to the full document size.
6658 */
6659 var $overlays = $([]);
6660 $.each($.ui.dialog.overlay.instances, function() {
6661 $overlays = $overlays.add(this);
6662 });
6663
6664 $overlays.css({
6665 width: 0,
6666 height: 0
6667 }).css({
6668 width: $.ui.dialog.overlay.width(),
6669 height: $.ui.dialog.overlay.height()
6670 });
6671 }
6672 });
6673
6674 $.extend($.ui.dialog.overlay.prototype, {
6675 destroy: function() {
6676 $.ui.dialog.overlay.destroy(this.$el);
6677 }
6678 });
6679
6680 }(jQuery));