excercises: uporzadkuj, luki, zastap
[redakcja.git] / redakcja / static / jquery-ui / js / jquery-ui-1.9.2.custom.js
1 /*! jQuery UI - v1.9.2 - 2013-01-02
2 * http://jqueryui.com
3 * Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.selectable.js, jquery.ui.sortable.js
4 * Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */
5
6 (function( $, undefined ) {
7
8 var uuid = 0,
9         runiqueId = /^ui-id-\d+$/;
10
11 // prevent duplicate loading
12 // this is only a problem because we proxy existing functions
13 // and we don't want to double proxy them
14 $.ui = $.ui || {};
15 if ( $.ui.version ) {
16         return;
17 }
18
19 $.extend( $.ui, {
20         version: "1.9.2",
21
22         keyCode: {
23                 BACKSPACE: 8,
24                 COMMA: 188,
25                 DELETE: 46,
26                 DOWN: 40,
27                 END: 35,
28                 ENTER: 13,
29                 ESCAPE: 27,
30                 HOME: 36,
31                 LEFT: 37,
32                 NUMPAD_ADD: 107,
33                 NUMPAD_DECIMAL: 110,
34                 NUMPAD_DIVIDE: 111,
35                 NUMPAD_ENTER: 108,
36                 NUMPAD_MULTIPLY: 106,
37                 NUMPAD_SUBTRACT: 109,
38                 PAGE_DOWN: 34,
39                 PAGE_UP: 33,
40                 PERIOD: 190,
41                 RIGHT: 39,
42                 SPACE: 32,
43                 TAB: 9,
44                 UP: 38
45         }
46 });
47
48 // plugins
49 $.fn.extend({
50         _focus: $.fn.focus,
51         focus: function( delay, fn ) {
52                 return typeof delay === "number" ?
53                         this.each(function() {
54                                 var elem = this;
55                                 setTimeout(function() {
56                                         $( elem ).focus();
57                                         if ( fn ) {
58                                                 fn.call( elem );
59                                         }
60                                 }, delay );
61                         }) :
62                         this._focus.apply( this, arguments );
63         },
64
65         scrollParent: function() {
66                 var scrollParent;
67                 if (($.ui.ie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
68                         scrollParent = this.parents().filter(function() {
69                                 return (/(relative|absolute|fixed)/).test($.css(this,'position')) && (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));
70                         }).eq(0);
71                 } else {
72                         scrollParent = this.parents().filter(function() {
73                                 return (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));
74                         }).eq(0);
75                 }
76
77                 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
78         },
79
80         zIndex: function( zIndex ) {
81                 if ( zIndex !== undefined ) {
82                         return this.css( "zIndex", zIndex );
83                 }
84
85                 if ( this.length ) {
86                         var elem = $( this[ 0 ] ), position, value;
87                         while ( elem.length && elem[ 0 ] !== document ) {
88                                 // Ignore z-index if position is set to a value where z-index is ignored by the browser
89                                 // This makes behavior of this function consistent across browsers
90                                 // WebKit always returns auto if the element is positioned
91                                 position = elem.css( "position" );
92                                 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
93                                         // IE returns 0 when zIndex is not specified
94                                         // other browsers return a string
95                                         // we ignore the case of nested elements with an explicit value of 0
96                                         // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
97                                         value = parseInt( elem.css( "zIndex" ), 10 );
98                                         if ( !isNaN( value ) && value !== 0 ) {
99                                                 return value;
100                                         }
101                                 }
102                                 elem = elem.parent();
103                         }
104                 }
105
106                 return 0;
107         },
108
109         uniqueId: function() {
110                 return this.each(function() {
111                         if ( !this.id ) {
112                                 this.id = "ui-id-" + (++uuid);
113                         }
114                 });
115         },
116
117         removeUniqueId: function() {
118                 return this.each(function() {
119                         if ( runiqueId.test( this.id ) ) {
120                                 $( this ).removeAttr( "id" );
121                         }
122                 });
123         }
124 });
125
126 // selectors
127 function focusable( element, isTabIndexNotNaN ) {
128         var map, mapName, img,
129                 nodeName = element.nodeName.toLowerCase();
130         if ( "area" === nodeName ) {
131                 map = element.parentNode;
132                 mapName = map.name;
133                 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
134                         return false;
135                 }
136                 img = $( "img[usemap=#" + mapName + "]" )[0];
137                 return !!img && visible( img );
138         }
139         return ( /input|select|textarea|button|object/.test( nodeName ) ?
140                 !element.disabled :
141                 "a" === nodeName ?
142                         element.href || isTabIndexNotNaN :
143                         isTabIndexNotNaN) &&
144                 // the element and all of its ancestors must be visible
145                 visible( element );
146 }
147
148 function visible( element ) {
149         return $.expr.filters.visible( element ) &&
150                 !$( element ).parents().andSelf().filter(function() {
151                         return $.css( this, "visibility" ) === "hidden";
152                 }).length;
153 }
154
155 $.extend( $.expr[ ":" ], {
156         data: $.expr.createPseudo ?
157                 $.expr.createPseudo(function( dataName ) {
158                         return function( elem ) {
159                                 return !!$.data( elem, dataName );
160                         };
161                 }) :
162                 // support: jQuery <1.8
163                 function( elem, i, match ) {
164                         return !!$.data( elem, match[ 3 ] );
165                 },
166
167         focusable: function( element ) {
168                 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
169         },
170
171         tabbable: function( element ) {
172                 var tabIndex = $.attr( element, "tabindex" ),
173                         isTabIndexNaN = isNaN( tabIndex );
174                 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
175         }
176 });
177
178 // support
179 $(function() {
180         var body = document.body,
181                 div = body.appendChild( div = document.createElement( "div" ) );
182
183         // access offsetHeight before setting the style to prevent a layout bug
184         // in IE 9 which causes the element to continue to take up space even
185         // after it is removed from the DOM (#8026)
186         div.offsetHeight;
187
188         $.extend( div.style, {
189                 minHeight: "100px",
190                 height: "auto",
191                 padding: 0,
192                 borderWidth: 0
193         });
194
195         $.support.minHeight = div.offsetHeight === 100;
196         $.support.selectstart = "onselectstart" in div;
197
198         // set display to none to avoid a layout bug in IE
199         // http://dev.jquery.com/ticket/4014
200         body.removeChild( div ).style.display = "none";
201 });
202
203 // support: jQuery <1.8
204 if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
205         $.each( [ "Width", "Height" ], function( i, name ) {
206                 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
207                         type = name.toLowerCase(),
208                         orig = {
209                                 innerWidth: $.fn.innerWidth,
210                                 innerHeight: $.fn.innerHeight,
211                                 outerWidth: $.fn.outerWidth,
212                                 outerHeight: $.fn.outerHeight
213                         };
214
215                 function reduce( elem, size, border, margin ) {
216                         $.each( side, function() {
217                                 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
218                                 if ( border ) {
219                                         size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
220                                 }
221                                 if ( margin ) {
222                                         size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
223                                 }
224                         });
225                         return size;
226                 }
227
228                 $.fn[ "inner" + name ] = function( size ) {
229                         if ( size === undefined ) {
230                                 return orig[ "inner" + name ].call( this );
231                         }
232
233                         return this.each(function() {
234                                 $( this ).css( type, reduce( this, size ) + "px" );
235                         });
236                 };
237
238                 $.fn[ "outer" + name] = function( size, margin ) {
239                         if ( typeof size !== "number" ) {
240                                 return orig[ "outer" + name ].call( this, size );
241                         }
242
243                         return this.each(function() {
244                                 $( this).css( type, reduce( this, size, true, margin ) + "px" );
245                         });
246                 };
247         });
248 }
249
250 // support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
251 if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
252         $.fn.removeData = (function( removeData ) {
253                 return function( key ) {
254                         if ( arguments.length ) {
255                                 return removeData.call( this, $.camelCase( key ) );
256                         } else {
257                                 return removeData.call( this );
258                         }
259                 };
260         })( $.fn.removeData );
261 }
262
263
264
265
266
267 // deprecated
268
269 (function() {
270         var uaMatch = /msie ([\w.]+)/.exec( navigator.userAgent.toLowerCase() ) || [];
271         $.ui.ie = uaMatch.length ? true : false;
272         $.ui.ie6 = parseFloat( uaMatch[ 1 ], 10 ) === 6;
273 })();
274
275 $.fn.extend({
276         disableSelection: function() {
277                 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
278                         ".ui-disableSelection", function( event ) {
279                                 event.preventDefault();
280                         });
281         },
282
283         enableSelection: function() {
284                 return this.unbind( ".ui-disableSelection" );
285         }
286 });
287
288 $.extend( $.ui, {
289         // $.ui.plugin is deprecated.  Use the proxy pattern instead.
290         plugin: {
291                 add: function( module, option, set ) {
292                         var i,
293                                 proto = $.ui[ module ].prototype;
294                         for ( i in set ) {
295                                 proto.plugins[ i ] = proto.plugins[ i ] || [];
296                                 proto.plugins[ i ].push( [ option, set[ i ] ] );
297                         }
298                 },
299                 call: function( instance, name, args ) {
300                         var i,
301                                 set = instance.plugins[ name ];
302                         if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
303                                 return;
304                         }
305
306                         for ( i = 0; i < set.length; i++ ) {
307                                 if ( instance.options[ set[ i ][ 0 ] ] ) {
308                                         set[ i ][ 1 ].apply( instance.element, args );
309                                 }
310                         }
311                 }
312         },
313
314         contains: $.contains,
315
316         // only used by resizable
317         hasScroll: function( el, a ) {
318
319                 //If overflow is hidden, the element might have extra content, but the user wants to hide it
320                 if ( $( el ).css( "overflow" ) === "hidden") {
321                         return false;
322                 }
323
324                 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
325                         has = false;
326
327                 if ( el[ scroll ] > 0 ) {
328                         return true;
329                 }
330
331                 // TODO: determine which cases actually cause this to happen
332                 // if the element doesn't have the scroll set, see if it's possible to
333                 // set the scroll
334                 el[ scroll ] = 1;
335                 has = ( el[ scroll ] > 0 );
336                 el[ scroll ] = 0;
337                 return has;
338         },
339
340         // these are odd functions, fix the API or move into individual plugins
341         isOverAxis: function( x, reference, size ) {
342                 //Determines when x coordinate is over "b" element axis
343                 return ( x > reference ) && ( x < ( reference + size ) );
344         },
345         isOver: function( y, x, top, left, height, width ) {
346                 //Determines when x, y coordinates is over "b" element
347                 return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
348         }
349 });
350
351 })( jQuery );
352 (function( $, undefined ) {
353
354 var uuid = 0,
355         slice = Array.prototype.slice,
356         _cleanData = $.cleanData;
357 $.cleanData = function( elems ) {
358         for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
359                 try {
360                         $( elem ).triggerHandler( "remove" );
361                 // http://bugs.jquery.com/ticket/8235
362                 } catch( e ) {}
363         }
364         _cleanData( elems );
365 };
366
367 $.widget = function( name, base, prototype ) {
368         var fullName, existingConstructor, constructor, basePrototype,
369                 namespace = name.split( "." )[ 0 ];
370
371         name = name.split( "." )[ 1 ];
372         fullName = namespace + "-" + name;
373
374         if ( !prototype ) {
375                 prototype = base;
376                 base = $.Widget;
377         }
378
379         // create selector for plugin
380         $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
381                 return !!$.data( elem, fullName );
382         };
383
384         $[ namespace ] = $[ namespace ] || {};
385         existingConstructor = $[ namespace ][ name ];
386         constructor = $[ namespace ][ name ] = function( options, element ) {
387                 // allow instantiation without "new" keyword
388                 if ( !this._createWidget ) {
389                         return new constructor( options, element );
390                 }
391
392                 // allow instantiation without initializing for simple inheritance
393                 // must use "new" keyword (the code above always passes args)
394                 if ( arguments.length ) {
395                         this._createWidget( options, element );
396                 }
397         };
398         // extend with the existing constructor to carry over any static properties
399         $.extend( constructor, existingConstructor, {
400                 version: prototype.version,
401                 // copy the object used to create the prototype in case we need to
402                 // redefine the widget later
403                 _proto: $.extend( {}, prototype ),
404                 // track widgets that inherit from this widget in case this widget is
405                 // redefined after a widget inherits from it
406                 _childConstructors: []
407         });
408
409         basePrototype = new base();
410         // we need to make the options hash a property directly on the new instance
411         // otherwise we'll modify the options hash on the prototype that we're
412         // inheriting from
413         basePrototype.options = $.widget.extend( {}, basePrototype.options );
414         $.each( prototype, function( prop, value ) {
415                 if ( $.isFunction( value ) ) {
416                         prototype[ prop ] = (function() {
417                                 var _super = function() {
418                                                 return base.prototype[ prop ].apply( this, arguments );
419                                         },
420                                         _superApply = function( args ) {
421                                                 return base.prototype[ prop ].apply( this, args );
422                                         };
423                                 return function() {
424                                         var __super = this._super,
425                                                 __superApply = this._superApply,
426                                                 returnValue;
427
428                                         this._super = _super;
429                                         this._superApply = _superApply;
430
431                                         returnValue = value.apply( this, arguments );
432
433                                         this._super = __super;
434                                         this._superApply = __superApply;
435
436                                         return returnValue;
437                                 };
438                         })();
439                 }
440         });
441         constructor.prototype = $.widget.extend( basePrototype, {
442                 // TODO: remove support for widgetEventPrefix
443                 // always use the name + a colon as the prefix, e.g., draggable:start
444                 // don't prefix for widgets that aren't DOM-based
445                 widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
446         }, prototype, {
447                 constructor: constructor,
448                 namespace: namespace,
449                 widgetName: name,
450                 // TODO remove widgetBaseClass, see #8155
451                 widgetBaseClass: fullName,
452                 widgetFullName: fullName
453         });
454
455         // If this widget is being redefined then we need to find all widgets that
456         // are inheriting from it and redefine all of them so that they inherit from
457         // the new version of this widget. We're essentially trying to replace one
458         // level in the prototype chain.
459         if ( existingConstructor ) {
460                 $.each( existingConstructor._childConstructors, function( i, child ) {
461                         var childPrototype = child.prototype;
462
463                         // redefine the child widget using the same prototype that was
464                         // originally used, but inherit from the new version of the base
465                         $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
466                 });
467                 // remove the list of existing child constructors from the old constructor
468                 // so the old child constructors can be garbage collected
469                 delete existingConstructor._childConstructors;
470         } else {
471                 base._childConstructors.push( constructor );
472         }
473
474         $.widget.bridge( name, constructor );
475 };
476
477 $.widget.extend = function( target ) {
478         var input = slice.call( arguments, 1 ),
479                 inputIndex = 0,
480                 inputLength = input.length,
481                 key,
482                 value;
483         for ( ; inputIndex < inputLength; inputIndex++ ) {
484                 for ( key in input[ inputIndex ] ) {
485                         value = input[ inputIndex ][ key ];
486                         if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
487                                 // Clone objects
488                                 if ( $.isPlainObject( value ) ) {
489                                         target[ key ] = $.isPlainObject( target[ key ] ) ?
490                                                 $.widget.extend( {}, target[ key ], value ) :
491                                                 // Don't extend strings, arrays, etc. with objects
492                                                 $.widget.extend( {}, value );
493                                 // Copy everything else by reference
494                                 } else {
495                                         target[ key ] = value;
496                                 }
497                         }
498                 }
499         }
500         return target;
501 };
502
503 $.widget.bridge = function( name, object ) {
504         var fullName = object.prototype.widgetFullName || name;
505         $.fn[ name ] = function( options ) {
506                 var isMethodCall = typeof options === "string",
507                         args = slice.call( arguments, 1 ),
508                         returnValue = this;
509
510                 // allow multiple hashes to be passed on init
511                 options = !isMethodCall && args.length ?
512                         $.widget.extend.apply( null, [ options ].concat(args) ) :
513                         options;
514
515                 if ( isMethodCall ) {
516                         this.each(function() {
517                                 var methodValue,
518                                         instance = $.data( this, fullName );
519                                 if ( !instance ) {
520                                         return $.error( "cannot call methods on " + name + " prior to initialization; " +
521                                                 "attempted to call method '" + options + "'" );
522                                 }
523                                 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
524                                         return $.error( "no such method '" + options + "' for " + name + " widget instance" );
525                                 }
526                                 methodValue = instance[ options ].apply( instance, args );
527                                 if ( methodValue !== instance && methodValue !== undefined ) {
528                                         returnValue = methodValue && methodValue.jquery ?
529                                                 returnValue.pushStack( methodValue.get() ) :
530                                                 methodValue;
531                                         return false;
532                                 }
533                         });
534                 } else {
535                         this.each(function() {
536                                 var instance = $.data( this, fullName );
537                                 if ( instance ) {
538                                         instance.option( options || {} )._init();
539                                 } else {
540                                         $.data( this, fullName, new object( options, this ) );
541                                 }
542                         });
543                 }
544
545                 return returnValue;
546         };
547 };
548
549 $.Widget = function( /* options, element */ ) {};
550 $.Widget._childConstructors = [];
551
552 $.Widget.prototype = {
553         widgetName: "widget",
554         widgetEventPrefix: "",
555         defaultElement: "<div>",
556         options: {
557                 disabled: false,
558
559                 // callbacks
560                 create: null
561         },
562         _createWidget: function( options, element ) {
563                 element = $( element || this.defaultElement || this )[ 0 ];
564                 this.element = $( element );
565                 this.uuid = uuid++;
566                 this.eventNamespace = "." + this.widgetName + this.uuid;
567                 this.options = $.widget.extend( {},
568                         this.options,
569                         this._getCreateOptions(),
570                         options );
571
572                 this.bindings = $();
573                 this.hoverable = $();
574                 this.focusable = $();
575
576                 if ( element !== this ) {
577                         // 1.9 BC for #7810
578                         // TODO remove dual storage
579                         $.data( element, this.widgetName, this );
580                         $.data( element, this.widgetFullName, this );
581                         this._on( true, this.element, {
582                                 remove: function( event ) {
583                                         if ( event.target === element ) {
584                                                 this.destroy();
585                                         }
586                                 }
587                         });
588                         this.document = $( element.style ?
589                                 // element within the document
590                                 element.ownerDocument :
591                                 // element is window or document
592                                 element.document || element );
593                         this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
594                 }
595
596                 this._create();
597                 this._trigger( "create", null, this._getCreateEventData() );
598                 this._init();
599         },
600         _getCreateOptions: $.noop,
601         _getCreateEventData: $.noop,
602         _create: $.noop,
603         _init: $.noop,
604
605         destroy: function() {
606                 this._destroy();
607                 // we can probably remove the unbind calls in 2.0
608                 // all event bindings should go through this._on()
609                 this.element
610                         .unbind( this.eventNamespace )
611                         // 1.9 BC for #7810
612                         // TODO remove dual storage
613                         .removeData( this.widgetName )
614                         .removeData( this.widgetFullName )
615                         // support: jquery <1.6.3
616                         // http://bugs.jquery.com/ticket/9413
617                         .removeData( $.camelCase( this.widgetFullName ) );
618                 this.widget()
619                         .unbind( this.eventNamespace )
620                         .removeAttr( "aria-disabled" )
621                         .removeClass(
622                                 this.widgetFullName + "-disabled " +
623                                 "ui-state-disabled" );
624
625                 // clean up events and states
626                 this.bindings.unbind( this.eventNamespace );
627                 this.hoverable.removeClass( "ui-state-hover" );
628                 this.focusable.removeClass( "ui-state-focus" );
629         },
630         _destroy: $.noop,
631
632         widget: function() {
633                 return this.element;
634         },
635
636         option: function( key, value ) {
637                 var options = key,
638                         parts,
639                         curOption,
640                         i;
641
642                 if ( arguments.length === 0 ) {
643                         // don't return a reference to the internal hash
644                         return $.widget.extend( {}, this.options );
645                 }
646
647                 if ( typeof key === "string" ) {
648                         // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
649                         options = {};
650                         parts = key.split( "." );
651                         key = parts.shift();
652                         if ( parts.length ) {
653                                 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
654                                 for ( i = 0; i < parts.length - 1; i++ ) {
655                                         curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
656                                         curOption = curOption[ parts[ i ] ];
657                                 }
658                                 key = parts.pop();
659                                 if ( value === undefined ) {
660                                         return curOption[ key ] === undefined ? null : curOption[ key ];
661                                 }
662                                 curOption[ key ] = value;
663                         } else {
664                                 if ( value === undefined ) {
665                                         return this.options[ key ] === undefined ? null : this.options[ key ];
666                                 }
667                                 options[ key ] = value;
668                         }
669                 }
670
671                 this._setOptions( options );
672
673                 return this;
674         },
675         _setOptions: function( options ) {
676                 var key;
677
678                 for ( key in options ) {
679                         this._setOption( key, options[ key ] );
680                 }
681
682                 return this;
683         },
684         _setOption: function( key, value ) {
685                 this.options[ key ] = value;
686
687                 if ( key === "disabled" ) {
688                         this.widget()
689                                 .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
690                                 .attr( "aria-disabled", value );
691                         this.hoverable.removeClass( "ui-state-hover" );
692                         this.focusable.removeClass( "ui-state-focus" );
693                 }
694
695                 return this;
696         },
697
698         enable: function() {
699                 return this._setOption( "disabled", false );
700         },
701         disable: function() {
702                 return this._setOption( "disabled", true );
703         },
704
705         _on: function( suppressDisabledCheck, element, handlers ) {
706                 var delegateElement,
707                         instance = this;
708
709                 // no suppressDisabledCheck flag, shuffle arguments
710                 if ( typeof suppressDisabledCheck !== "boolean" ) {
711                         handlers = element;
712                         element = suppressDisabledCheck;
713                         suppressDisabledCheck = false;
714                 }
715
716                 // no element argument, shuffle and use this.element
717                 if ( !handlers ) {
718                         handlers = element;
719                         element = this.element;
720                         delegateElement = this.widget();
721                 } else {
722                         // accept selectors, DOM elements
723                         element = delegateElement = $( element );
724                         this.bindings = this.bindings.add( element );
725                 }
726
727                 $.each( handlers, function( event, handler ) {
728                         function handlerProxy() {
729                                 // allow widgets to customize the disabled handling
730                                 // - disabled as an array instead of boolean
731                                 // - disabled class as method for disabling individual parts
732                                 if ( !suppressDisabledCheck &&
733                                                 ( instance.options.disabled === true ||
734                                                         $( this ).hasClass( "ui-state-disabled" ) ) ) {
735                                         return;
736                                 }
737                                 return ( typeof handler === "string" ? instance[ handler ] : handler )
738                                         .apply( instance, arguments );
739                         }
740
741                         // copy the guid so direct unbinding works
742                         if ( typeof handler !== "string" ) {
743                                 handlerProxy.guid = handler.guid =
744                                         handler.guid || handlerProxy.guid || $.guid++;
745                         }
746
747                         var match = event.match( /^(\w+)\s*(.*)$/ ),
748                                 eventName = match[1] + instance.eventNamespace,
749                                 selector = match[2];
750                         if ( selector ) {
751                                 delegateElement.delegate( selector, eventName, handlerProxy );
752                         } else {
753                                 element.bind( eventName, handlerProxy );
754                         }
755                 });
756         },
757
758         _off: function( element, eventName ) {
759                 eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
760                 element.unbind( eventName ).undelegate( eventName );
761         },
762
763         _delay: function( handler, delay ) {
764                 function handlerProxy() {
765                         return ( typeof handler === "string" ? instance[ handler ] : handler )
766                                 .apply( instance, arguments );
767                 }
768                 var instance = this;
769                 return setTimeout( handlerProxy, delay || 0 );
770         },
771
772         _hoverable: function( element ) {
773                 this.hoverable = this.hoverable.add( element );
774                 this._on( element, {
775                         mouseenter: function( event ) {
776                                 $( event.currentTarget ).addClass( "ui-state-hover" );
777                         },
778                         mouseleave: function( event ) {
779                                 $( event.currentTarget ).removeClass( "ui-state-hover" );
780                         }
781                 });
782         },
783
784         _focusable: function( element ) {
785                 this.focusable = this.focusable.add( element );
786                 this._on( element, {
787                         focusin: function( event ) {
788                                 $( event.currentTarget ).addClass( "ui-state-focus" );
789                         },
790                         focusout: function( event ) {
791                                 $( event.currentTarget ).removeClass( "ui-state-focus" );
792                         }
793                 });
794         },
795
796         _trigger: function( type, event, data ) {
797                 var prop, orig,
798                         callback = this.options[ type ];
799
800                 data = data || {};
801                 event = $.Event( event );
802                 event.type = ( type === this.widgetEventPrefix ?
803                         type :
804                         this.widgetEventPrefix + type ).toLowerCase();
805                 // the original event may come from any element
806                 // so we need to reset the target on the new event
807                 event.target = this.element[ 0 ];
808
809                 // copy original event properties over to the new event
810                 orig = event.originalEvent;
811                 if ( orig ) {
812                         for ( prop in orig ) {
813                                 if ( !( prop in event ) ) {
814                                         event[ prop ] = orig[ prop ];
815                                 }
816                         }
817                 }
818
819                 this.element.trigger( event, data );
820                 return !( $.isFunction( callback ) &&
821                         callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
822                         event.isDefaultPrevented() );
823         }
824 };
825
826 $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
827         $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
828                 if ( typeof options === "string" ) {
829                         options = { effect: options };
830                 }
831                 var hasOptions,
832                         effectName = !options ?
833                                 method :
834                                 options === true || typeof options === "number" ?
835                                         defaultEffect :
836                                         options.effect || defaultEffect;
837                 options = options || {};
838                 if ( typeof options === "number" ) {
839                         options = { duration: options };
840                 }
841                 hasOptions = !$.isEmptyObject( options );
842                 options.complete = callback;
843                 if ( options.delay ) {
844                         element.delay( options.delay );
845                 }
846                 if ( hasOptions && $.effects && ( $.effects.effect[ effectName ] || $.uiBackCompat !== false && $.effects[ effectName ] ) ) {
847                         element[ method ]( options );
848                 } else if ( effectName !== method && element[ effectName ] ) {
849                         element[ effectName ]( options.duration, options.easing, callback );
850                 } else {
851                         element.queue(function( next ) {
852                                 $( this )[ method ]();
853                                 if ( callback ) {
854                                         callback.call( element[ 0 ] );
855                                 }
856                                 next();
857                         });
858                 }
859         };
860 });
861
862 // DEPRECATED
863 if ( $.uiBackCompat !== false ) {
864         $.Widget.prototype._getCreateOptions = function() {
865                 return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
866         };
867 }
868
869 })( jQuery );
870 (function( $, undefined ) {
871
872 var mouseHandled = false;
873 $( document ).mouseup( function( e ) {
874         mouseHandled = false;
875 });
876
877 $.widget("ui.mouse", {
878         version: "1.9.2",
879         options: {
880                 cancel: 'input,textarea,button,select,option',
881                 distance: 1,
882                 delay: 0
883         },
884         _mouseInit: function() {
885                 var that = this;
886
887                 this.element
888                         .bind('mousedown.'+this.widgetName, function(event) {
889                                 return that._mouseDown(event);
890                         })
891                         .bind('click.'+this.widgetName, function(event) {
892                                 if (true === $.data(event.target, that.widgetName + '.preventClickEvent')) {
893                                         $.removeData(event.target, that.widgetName + '.preventClickEvent');
894                                         event.stopImmediatePropagation();
895                                         return false;
896                                 }
897                         });
898
899                 this.started = false;
900         },
901
902         // TODO: make sure destroying one instance of mouse doesn't mess with
903         // other instances of mouse
904         _mouseDestroy: function() {
905                 this.element.unbind('.'+this.widgetName);
906                 if ( this._mouseMoveDelegate ) {
907                         $(document)
908                                 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
909                                 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
910                 }
911         },
912
913         _mouseDown: function(event) {
914                 // don't let more than one widget handle mouseStart
915                 if( mouseHandled ) { return; }
916
917                 // we may have missed mouseup (out of window)
918                 (this._mouseStarted && this._mouseUp(event));
919
920                 this._mouseDownEvent = event;
921
922                 var that = this,
923                         btnIsLeft = (event.which === 1),
924                         // event.target.nodeName works around a bug in IE 8 with
925                         // disabled inputs (#7620)
926                         elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
927                 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
928                         return true;
929                 }
930
931                 this.mouseDelayMet = !this.options.delay;
932                 if (!this.mouseDelayMet) {
933                         this._mouseDelayTimer = setTimeout(function() {
934                                 that.mouseDelayMet = true;
935                         }, this.options.delay);
936                 }
937
938                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
939                         this._mouseStarted = (this._mouseStart(event) !== false);
940                         if (!this._mouseStarted) {
941                                 event.preventDefault();
942                                 return true;
943                         }
944                 }
945
946                 // Click event may never have fired (Gecko & Opera)
947                 if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
948                         $.removeData(event.target, this.widgetName + '.preventClickEvent');
949                 }
950
951                 // these delegates are required to keep context
952                 this._mouseMoveDelegate = function(event) {
953                         return that._mouseMove(event);
954                 };
955                 this._mouseUpDelegate = function(event) {
956                         return that._mouseUp(event);
957                 };
958                 $(document)
959                         .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
960                         .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
961
962                 event.preventDefault();
963
964                 mouseHandled = true;
965                 return true;
966         },
967
968         _mouseMove: function(event) {
969                 // IE mouseup check - mouseup happened when mouse was out of window
970                 if ($.ui.ie && !(document.documentMode >= 9) && !event.button) {
971                         return this._mouseUp(event);
972                 }
973
974                 if (this._mouseStarted) {
975                         this._mouseDrag(event);
976                         return event.preventDefault();
977                 }
978
979                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
980                         this._mouseStarted =
981                                 (this._mouseStart(this._mouseDownEvent, event) !== false);
982                         (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
983                 }
984
985                 return !this._mouseStarted;
986         },
987
988         _mouseUp: function(event) {
989                 $(document)
990                         .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
991                         .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
992
993                 if (this._mouseStarted) {
994                         this._mouseStarted = false;
995
996                         if (event.target === this._mouseDownEvent.target) {
997                                 $.data(event.target, this.widgetName + '.preventClickEvent', true);
998                         }
999
1000                         this._mouseStop(event);
1001                 }
1002
1003                 return false;
1004         },
1005
1006         _mouseDistanceMet: function(event) {
1007                 return (Math.max(
1008                                 Math.abs(this._mouseDownEvent.pageX - event.pageX),
1009                                 Math.abs(this._mouseDownEvent.pageY - event.pageY)
1010                         ) >= this.options.distance
1011                 );
1012         },
1013
1014         _mouseDelayMet: function(event) {
1015                 return this.mouseDelayMet;
1016         },
1017
1018         // These are placeholder methods, to be overriden by extending plugin
1019         _mouseStart: function(event) {},
1020         _mouseDrag: function(event) {},
1021         _mouseStop: function(event) {},
1022         _mouseCapture: function(event) { return true; }
1023 });
1024
1025 })(jQuery);
1026 (function( $, undefined ) {
1027
1028 $.widget("ui.draggable", $.ui.mouse, {
1029         version: "1.9.2",
1030         widgetEventPrefix: "drag",
1031         options: {
1032                 addClasses: true,
1033                 appendTo: "parent",
1034                 axis: false,
1035                 connectToSortable: false,
1036                 containment: false,
1037                 cursor: "auto",
1038                 cursorAt: false,
1039                 grid: false,
1040                 handle: false,
1041                 helper: "original",
1042                 iframeFix: false,
1043                 opacity: false,
1044                 refreshPositions: false,
1045                 revert: false,
1046                 revertDuration: 500,
1047                 scope: "default",
1048                 scroll: true,
1049                 scrollSensitivity: 20,
1050                 scrollSpeed: 20,
1051                 snap: false,
1052                 snapMode: "both",
1053                 snapTolerance: 20,
1054                 stack: false,
1055                 zIndex: false
1056         },
1057         _create: function() {
1058
1059                 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
1060                         this.element[0].style.position = 'relative';
1061
1062                 (this.options.addClasses && this.element.addClass("ui-draggable"));
1063                 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
1064
1065                 this._mouseInit();
1066
1067         },
1068
1069         _destroy: function() {
1070                 this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
1071                 this._mouseDestroy();
1072         },
1073
1074         _mouseCapture: function(event) {
1075
1076                 var o = this.options;
1077
1078                 // among others, prevent a drag on a resizable-handle
1079                 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
1080                         return false;
1081
1082                 //Quit if we're not on a valid handle
1083                 this.handle = this._getHandle(event);
1084                 if (!this.handle)
1085                         return false;
1086
1087                 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
1088                         $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
1089                         .css({
1090                                 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
1091                                 position: "absolute", opacity: "0.001", zIndex: 1000
1092                         })
1093                         .css($(this).offset())
1094                         .appendTo("body");
1095                 });
1096
1097                 return true;
1098
1099         },
1100
1101         _mouseStart: function(event) {
1102
1103                 var o = this.options;
1104
1105                 //Create and append the visible helper
1106                 this.helper = this._createHelper(event);
1107
1108                 this.helper.addClass("ui-draggable-dragging");
1109
1110                 //Cache the helper size
1111                 this._cacheHelperProportions();
1112
1113                 //If ddmanager is used for droppables, set the global draggable
1114                 if($.ui.ddmanager)
1115                         $.ui.ddmanager.current = this;
1116
1117                 /*
1118                  * - Position generation -
1119                  * This block generates everything position related - it's the core of draggables.
1120                  */
1121
1122                 //Cache the margins of the original element
1123                 this._cacheMargins();
1124
1125                 //Store the helper's css position
1126                 this.cssPosition = this.helper.css("position");
1127                 this.scrollParent = this.helper.scrollParent();
1128
1129                 //The element's absolute position on the page minus margins
1130                 this.offset = this.positionAbs = this.element.offset();
1131                 this.offset = {
1132                         top: this.offset.top - this.margins.top,
1133                         left: this.offset.left - this.margins.left
1134                 };
1135
1136                 $.extend(this.offset, {
1137                         click: { //Where the click happened, relative to the element
1138                                 left: event.pageX - this.offset.left,
1139                                 top: event.pageY - this.offset.top
1140                         },
1141                         parent: this._getParentOffset(),
1142                         relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
1143                 });
1144
1145                 //Generate the original position
1146                 this.originalPosition = this.position = this._generatePosition(event);
1147                 this.originalPageX = event.pageX;
1148                 this.originalPageY = event.pageY;
1149
1150                 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
1151                 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
1152
1153                 //Set a containment if given in the options
1154                 if(o.containment)
1155                         this._setContainment();
1156
1157                 //Trigger event + callbacks
1158                 if(this._trigger("start", event) === false) {
1159                         this._clear();
1160                         return false;
1161                 }
1162
1163                 //Recache the helper size
1164                 this._cacheHelperProportions();
1165
1166                 //Prepare the droppable offsets
1167                 if ($.ui.ddmanager && !o.dropBehaviour)
1168                         $.ui.ddmanager.prepareOffsets(this, event);
1169
1170
1171                 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
1172
1173                 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
1174                 if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event);
1175
1176                 return true;
1177         },
1178
1179         _mouseDrag: function(event, noPropagation) {
1180
1181                 //Compute the helpers position
1182                 this.position = this._generatePosition(event);
1183                 this.positionAbs = this._convertPositionTo("absolute");
1184
1185                 //Call plugins and callbacks and use the resulting position if something is returned
1186                 if (!noPropagation) {
1187                         var ui = this._uiHash();
1188                         if(this._trigger('drag', event, ui) === false) {
1189                                 this._mouseUp({});
1190                                 return false;
1191                         }
1192                         this.position = ui.position;
1193                 }
1194
1195                 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
1196                 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
1197                 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
1198
1199                 return false;
1200         },
1201
1202         _mouseStop: function(event) {
1203
1204                 //If we are using droppables, inform the manager about the drop
1205                 var dropped = false;
1206                 if ($.ui.ddmanager && !this.options.dropBehaviour)
1207                         dropped = $.ui.ddmanager.drop(this, event);
1208
1209                 //if a drop comes from outside (a sortable)
1210                 if(this.dropped) {
1211                         dropped = this.dropped;
1212                         this.dropped = false;
1213                 }
1214
1215                 //if the original element is no longer in the DOM don't bother to continue (see #8269)
1216                 var element = this.element[0], elementInDom = false;
1217                 while ( element && (element = element.parentNode) ) {
1218                         if (element == document ) {
1219                                 elementInDom = true;
1220                         }
1221                 }
1222                 if ( !elementInDom && this.options.helper === "original" )
1223                         return false;
1224
1225                 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))) {
1226                         var that = this;
1227                         $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
1228                                 if(that._trigger("stop", event) !== false) {
1229                                         that._clear();
1230                                 }
1231                         });
1232                 } else {
1233                         if(this._trigger("stop", event) !== false) {
1234                                 this._clear();
1235                         }
1236                 }
1237
1238                 return false;
1239         },
1240
1241         _mouseUp: function(event) {
1242                 //Remove frame helpers
1243                 $("div.ui-draggable-iframeFix").each(function() {
1244                         this.parentNode.removeChild(this);
1245                 });
1246
1247                 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
1248                 if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event);
1249
1250                 return $.ui.mouse.prototype._mouseUp.call(this, event);
1251         },
1252
1253         cancel: function() {
1254
1255                 if(this.helper.is(".ui-draggable-dragging")) {
1256                         this._mouseUp({});
1257                 } else {
1258                         this._clear();
1259                 }
1260
1261                 return this;
1262
1263         },
1264
1265         _getHandle: function(event) {
1266
1267                 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
1268                 $(this.options.handle, this.element)
1269                         .find("*")
1270                         .andSelf()
1271                         .each(function() {
1272                                 if(this == event.target) handle = true;
1273                         });
1274
1275                 return handle;
1276
1277         },
1278
1279         _createHelper: function(event) {
1280
1281                 var o = this.options;
1282                 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element);
1283
1284                 if(!helper.parents('body').length)
1285                         helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
1286
1287                 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
1288                         helper.css("position", "absolute");
1289
1290                 return helper;
1291
1292         },
1293
1294         _adjustOffsetFromHelper: function(obj) {
1295                 if (typeof obj == 'string') {
1296                         obj = obj.split(' ');
1297                 }
1298                 if ($.isArray(obj)) {
1299                         obj = {left: +obj[0], top: +obj[1] || 0};
1300                 }
1301                 if ('left' in obj) {
1302                         this.offset.click.left = obj.left + this.margins.left;
1303                 }
1304                 if ('right' in obj) {
1305                         this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1306                 }
1307                 if ('top' in obj) {
1308                         this.offset.click.top = obj.top + this.margins.top;
1309                 }
1310                 if ('bottom' in obj) {
1311                         this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1312                 }
1313         },
1314
1315         _getParentOffset: function() {
1316
1317                 //Get the offsetParent and cache its position
1318                 this.offsetParent = this.helper.offsetParent();
1319                 var po = this.offsetParent.offset();
1320
1321                 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1322                 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1323                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1324                 //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1325                 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
1326                         po.left += this.scrollParent.scrollLeft();
1327                         po.top += this.scrollParent.scrollTop();
1328                 }
1329
1330                 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
1331                 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.ui.ie)) //Ugly IE fix
1332                         po = { top: 0, left: 0 };
1333
1334                 return {
1335                         top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1336                         left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1337                 };
1338
1339         },
1340
1341         _getRelativeOffset: function() {
1342
1343                 if(this.cssPosition == "relative") {
1344                         var p = this.element.position();
1345                         return {
1346                                 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1347                                 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1348                         };
1349                 } else {
1350                         return { top: 0, left: 0 };
1351                 }
1352
1353         },
1354
1355         _cacheMargins: function() {
1356                 this.margins = {
1357                         left: (parseInt(this.element.css("marginLeft"),10) || 0),
1358                         top: (parseInt(this.element.css("marginTop"),10) || 0),
1359                         right: (parseInt(this.element.css("marginRight"),10) || 0),
1360                         bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
1361                 };
1362         },
1363
1364         _cacheHelperProportions: function() {
1365                 this.helperProportions = {
1366                         width: this.helper.outerWidth(),
1367                         height: this.helper.outerHeight()
1368                 };
1369         },
1370
1371         _setContainment: function() {
1372
1373                 var o = this.options;
1374                 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
1375                 if(o.containment == 'document' || o.containment == 'window') this.containment = [
1376                         o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
1377                         o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
1378                         (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
1379                         (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
1380                 ];
1381
1382                 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
1383                         var c = $(o.containment);
1384                         var ce = c[0]; if(!ce) return;
1385                         var co = c.offset();
1386                         var over = ($(ce).css("overflow") != 'hidden');
1387
1388                         this.containment = [
1389                                 (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
1390                                 (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
1391                                 (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,
1392                                 (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
1393                         ];
1394                         this.relative_container = c;
1395
1396                 } else if(o.containment.constructor == Array) {
1397                         this.containment = o.containment;
1398                 }
1399
1400         },
1401
1402         _convertPositionTo: function(d, pos) {
1403
1404                 if(!pos) pos = this.position;
1405                 var mod = d == "absolute" ? 1 : -1;
1406                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
1407
1408                 return {
1409                         top: (
1410                                 pos.top                                                                                                                                 // The absolute mouse position
1411                                 + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
1412                                 + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)
1413                                 - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
1414                         ),
1415                         left: (
1416                                 pos.left                                                                                                                                // The absolute mouse position
1417                                 + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
1418                                 + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)
1419                                 - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
1420                         )
1421                 };
1422
1423         },
1424
1425         _generatePosition: function(event) {
1426
1427                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
1428                 var pageX = event.pageX;
1429                 var pageY = event.pageY;
1430
1431                 /*
1432                  * - Position constraining -
1433                  * Constrain the position to a mix of grid, containment.
1434                  */
1435
1436                 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
1437                         var containment;
1438                         if(this.containment) {
1439                         if (this.relative_container){
1440                                 var co = this.relative_container.offset();
1441                                 containment = [ this.containment[0] + co.left,
1442                                         this.containment[1] + co.top,
1443                                         this.containment[2] + co.left,
1444                                         this.containment[3] + co.top ];
1445                         }
1446                         else {
1447                                 containment = this.containment;
1448                         }
1449
1450                                 if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left;
1451                                 if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top;
1452                                 if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left;
1453                                 if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top;
1454                         }
1455
1456                         if(o.grid) {
1457                                 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
1458                                 var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
1459                                 pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
1460
1461                                 var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
1462                                 pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
1463                         }
1464
1465                 }
1466
1467                 return {
1468                         top: (
1469                                 pageY                                                                                                                           // The absolute mouse position
1470                                 - this.offset.click.top                                                                                                 // Click offset (relative to the element)
1471                                 - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
1472                                 - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)
1473                                 + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
1474                         ),
1475                         left: (
1476                                 pageX                                                                                                                           // The absolute mouse position
1477                                 - this.offset.click.left                                                                                                // Click offset (relative to the element)
1478                                 - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
1479                                 - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)
1480                                 + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
1481                         )
1482                 };
1483
1484         },
1485
1486         _clear: function() {
1487                 this.helper.removeClass("ui-draggable-dragging");
1488                 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
1489                 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
1490                 this.helper = null;
1491                 this.cancelHelperRemoval = false;
1492         },
1493
1494         // From now on bulk stuff - mainly helpers
1495
1496         _trigger: function(type, event, ui) {
1497                 ui = ui || this._uiHash();
1498                 $.ui.plugin.call(this, type, [event, ui]);
1499                 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
1500                 return $.Widget.prototype._trigger.call(this, type, event, ui);
1501         },
1502
1503         plugins: {},
1504
1505         _uiHash: function(event) {
1506                 return {
1507                         helper: this.helper,
1508                         position: this.position,
1509                         originalPosition: this.originalPosition,
1510                         offset: this.positionAbs
1511                 };
1512         }
1513
1514 });
1515
1516 $.ui.plugin.add("draggable", "connectToSortable", {
1517         start: function(event, ui) {
1518
1519                 var inst = $(this).data("draggable"), o = inst.options,
1520                         uiSortable = $.extend({}, ui, { item: inst.element });
1521                 inst.sortables = [];
1522                 $(o.connectToSortable).each(function() {
1523                         var sortable = $.data(this, 'sortable');
1524                         if (sortable && !sortable.options.disabled) {
1525                                 inst.sortables.push({
1526                                         instance: sortable,
1527                                         shouldRevert: sortable.options.revert
1528                                 });
1529                                 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).
1530                                 sortable._trigger("activate", event, uiSortable);
1531                         }
1532                 });
1533
1534         },
1535         stop: function(event, ui) {
1536
1537                 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1538                 var inst = $(this).data("draggable"),
1539                         uiSortable = $.extend({}, ui, { item: inst.element });
1540
1541                 $.each(inst.sortables, function() {
1542                         if(this.instance.isOver) {
1543
1544                                 this.instance.isOver = 0;
1545
1546                                 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
1547                                 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1548
1549                                 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
1550                                 if(this.shouldRevert) this.instance.options.revert = true;
1551
1552                                 //Trigger the stop of the sortable
1553                                 this.instance._mouseStop(event);
1554
1555                                 this.instance.options.helper = this.instance.options._helper;
1556
1557                                 //If the helper has been the original item, restore properties in the sortable
1558                                 if(inst.options.helper == 'original')
1559                                         this.instance.currentItem.css({ top: 'auto', left: 'auto' });
1560
1561                         } else {
1562                                 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1563                                 this.instance._trigger("deactivate", event, uiSortable);
1564                         }
1565
1566                 });
1567
1568         },
1569         drag: function(event, ui) {
1570
1571                 var inst = $(this).data("draggable"), that = this;
1572
1573                 var checkPos = function(o) {
1574                         var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
1575                         var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
1576                         var itemHeight = o.height, itemWidth = o.width;
1577                         var itemTop = o.top, itemLeft = o.left;
1578
1579                         return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
1580                 };
1581
1582                 $.each(inst.sortables, function(i) {
1583
1584                         var innermostIntersecting = false;
1585                         var thisSortable = this;
1586                         //Copy over some variables to allow calling the sortable's native _intersectsWith
1587                         this.instance.positionAbs = inst.positionAbs;
1588                         this.instance.helperProportions = inst.helperProportions;
1589                         this.instance.offset.click = inst.offset.click;
1590
1591                         if(this.instance._intersectsWith(this.instance.containerCache)) {
1592                                 innermostIntersecting = true;
1593                                 $.each(inst.sortables, function () {
1594                                         this.instance.positionAbs = inst.positionAbs;
1595                                         this.instance.helperProportions = inst.helperProportions;
1596                                         this.instance.offset.click = inst.offset.click;
1597                                         if  (this != thisSortable
1598                                                 && this.instance._intersectsWith(this.instance.containerCache)
1599                                                 && $.ui.contains(thisSortable.instance.element[0], this.instance.element[0]))
1600                                                 innermostIntersecting = false;
1601                                                 return innermostIntersecting;
1602                                 });
1603                         }
1604
1605
1606                         if(innermostIntersecting) {
1607                                 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1608                                 if(!this.instance.isOver) {
1609
1610                                         this.instance.isOver = 1;
1611                                         //Now we fake the start of dragging for the sortable instance,
1612                                         //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1613                                         //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)
1614                                         this.instance.currentItem = $(that).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true);
1615                                         this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1616                                         this.instance.options.helper = function() { return ui.helper[0]; };
1617
1618                                         event.target = this.instance.currentItem[0];
1619                                         this.instance._mouseCapture(event, true);
1620                                         this.instance._mouseStart(event, true, true);
1621
1622                                         //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1623                                         this.instance.offset.click.top = inst.offset.click.top;
1624                                         this.instance.offset.click.left = inst.offset.click.left;
1625                                         this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1626                                         this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1627
1628                                         inst._trigger("toSortable", event);
1629                                         inst.dropped = this.instance.element; //draggable revert needs that
1630                                         //hack so receive/update callbacks work (mostly)
1631                                         inst.currentItem = inst.element;
1632                                         this.instance.fromOutside = inst;
1633
1634                                 }
1635
1636                                 //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
1637                                 if(this.instance.currentItem) this.instance._mouseDrag(event);
1638
1639                         } else {
1640
1641                                 //If it doesn't intersect with the sortable, and it intersected before,
1642                                 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1643                                 if(this.instance.isOver) {
1644
1645                                         this.instance.isOver = 0;
1646                                         this.instance.cancelHelperRemoval = true;
1647
1648                                         //Prevent reverting on this forced stop
1649                                         this.instance.options.revert = false;
1650
1651                                         // The out event needs to be triggered independently
1652                                         this.instance._trigger('out', event, this.instance._uiHash(this.instance));
1653
1654                                         this.instance._mouseStop(event, true);
1655                                         this.instance.options.helper = this.instance.options._helper;
1656
1657                                         //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1658                                         this.instance.currentItem.remove();
1659                                         if(this.instance.placeholder) this.instance.placeholder.remove();
1660
1661                                         inst._trigger("fromSortable", event);
1662                                         inst.dropped = false; //draggable revert needs that
1663                                 }
1664
1665                         };
1666
1667                 });
1668
1669         }
1670 });
1671
1672 $.ui.plugin.add("draggable", "cursor", {
1673         start: function(event, ui) {
1674                 var t = $('body'), o = $(this).data('draggable').options;
1675                 if (t.css("cursor")) o._cursor = t.css("cursor");
1676                 t.css("cursor", o.cursor);
1677         },
1678         stop: function(event, ui) {
1679                 var o = $(this).data('draggable').options;
1680                 if (o._cursor) $('body').css("cursor", o._cursor);
1681         }
1682 });
1683
1684 $.ui.plugin.add("draggable", "opacity", {
1685         start: function(event, ui) {
1686                 var t = $(ui.helper), o = $(this).data('draggable').options;
1687                 if(t.css("opacity")) o._opacity = t.css("opacity");
1688                 t.css('opacity', o.opacity);
1689         },
1690         stop: function(event, ui) {
1691                 var o = $(this).data('draggable').options;
1692                 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
1693         }
1694 });
1695
1696 $.ui.plugin.add("draggable", "scroll", {
1697         start: function(event, ui) {
1698                 var i = $(this).data("draggable");
1699                 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
1700         },
1701         drag: function(event, ui) {
1702
1703                 var i = $(this).data("draggable"), o = i.options, scrolled = false;
1704
1705                 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
1706
1707                         if(!o.axis || o.axis != 'x') {
1708                                 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
1709                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1710                                 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
1711                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1712                         }
1713
1714                         if(!o.axis || o.axis != 'y') {
1715                                 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
1716                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1717                                 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
1718                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1719                         }
1720
1721                 } else {
1722
1723                         if(!o.axis || o.axis != 'x') {
1724                                 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
1725                                         scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1726                                 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
1727                                         scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1728                         }
1729
1730                         if(!o.axis || o.axis != 'y') {
1731                                 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
1732                                         scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1733                                 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
1734                                         scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1735                         }
1736
1737                 }
1738
1739                 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
1740                         $.ui.ddmanager.prepareOffsets(i, event);
1741
1742         }
1743 });
1744
1745 $.ui.plugin.add("draggable", "snap", {
1746         start: function(event, ui) {
1747
1748                 var i = $(this).data("draggable"), o = i.options;
1749                 i.snapElements = [];
1750
1751                 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
1752                         var $t = $(this); var $o = $t.offset();
1753                         if(this != i.element[0]) i.snapElements.push({
1754                                 item: this,
1755                                 width: $t.outerWidth(), height: $t.outerHeight(),
1756                                 top: $o.top, left: $o.left
1757                         });
1758                 });
1759
1760         },
1761         drag: function(event, ui) {
1762
1763                 var inst = $(this).data("draggable"), o = inst.options;
1764                 var d = o.snapTolerance;
1765
1766                 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
1767                         y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
1768
1769                 for (var i = inst.snapElements.length - 1; i >= 0; i--){
1770
1771                         var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
1772                                 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
1773
1774                         //Yes, I know, this is insane ;)
1775                         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))) {
1776                                 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 })));
1777                                 inst.snapElements[i].snapping = false;
1778                                 continue;
1779                         }
1780
1781                         if(o.snapMode != 'inner') {
1782                                 var ts = Math.abs(t - y2) <= d;
1783                                 var bs = Math.abs(b - y1) <= d;
1784                                 var ls = Math.abs(l - x2) <= d;
1785                                 var rs = Math.abs(r - x1) <= d;
1786                                 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1787                                 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1788                                 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1789                                 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1790                         }
1791
1792                         var first = (ts || bs || ls || rs);
1793
1794                         if(o.snapMode != 'outer') {
1795                                 var ts = Math.abs(t - y1) <= d;
1796                                 var bs = Math.abs(b - y2) <= d;
1797                                 var ls = Math.abs(l - x1) <= d;
1798                                 var rs = Math.abs(r - x2) <= d;
1799                                 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1800                                 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1801                                 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1802                                 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1803                         }
1804
1805                         if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
1806                                 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1807                         inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1808
1809                 };
1810
1811         }
1812 });
1813
1814 $.ui.plugin.add("draggable", "stack", {
1815         start: function(event, ui) {
1816
1817                 var o = $(this).data("draggable").options;
1818
1819                 var group = $.makeArray($(o.stack)).sort(function(a,b) {
1820                         return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
1821                 });
1822                 if (!group.length) { return; }
1823
1824                 var min = parseInt(group[0].style.zIndex) || 0;
1825                 $(group).each(function(i) {
1826                         this.style.zIndex = min + i;
1827                 });
1828
1829                 this[0].style.zIndex = min + group.length;
1830
1831         }
1832 });
1833
1834 $.ui.plugin.add("draggable", "zIndex", {
1835         start: function(event, ui) {
1836                 var t = $(ui.helper), o = $(this).data("draggable").options;
1837                 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
1838                 t.css('zIndex', o.zIndex);
1839         },
1840         stop: function(event, ui) {
1841                 var o = $(this).data("draggable").options;
1842                 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
1843         }
1844 });
1845
1846 })(jQuery);
1847 (function( $, undefined ) {
1848
1849 $.widget("ui.droppable", {
1850         version: "1.9.2",
1851         widgetEventPrefix: "drop",
1852         options: {
1853                 accept: '*',
1854                 activeClass: false,
1855                 addClasses: true,
1856                 greedy: false,
1857                 hoverClass: false,
1858                 scope: 'default',
1859                 tolerance: 'intersect'
1860         },
1861         _create: function() {
1862
1863                 var o = this.options, accept = o.accept;
1864                 this.isover = 0; this.isout = 1;
1865
1866                 this.accept = $.isFunction(accept) ? accept : function(d) {
1867                         return d.is(accept);
1868                 };
1869
1870                 //Store the droppable's proportions
1871                 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
1872
1873                 // Add the reference and positions to the manager
1874                 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
1875                 $.ui.ddmanager.droppables[o.scope].push(this);
1876
1877                 (o.addClasses && this.element.addClass("ui-droppable"));
1878
1879         },
1880
1881         _destroy: function() {
1882                 var drop = $.ui.ddmanager.droppables[this.options.scope];
1883                 for ( var i = 0; i < drop.length; i++ )
1884                         if ( drop[i] == this )
1885                                 drop.splice(i, 1);
1886
1887                 this.element.removeClass("ui-droppable ui-droppable-disabled");
1888         },
1889
1890         _setOption: function(key, value) {
1891
1892                 if(key == 'accept') {
1893                         this.accept = $.isFunction(value) ? value : function(d) {
1894                                 return d.is(value);
1895                         };
1896                 }
1897                 $.Widget.prototype._setOption.apply(this, arguments);
1898         },
1899
1900         _activate: function(event) {
1901                 var draggable = $.ui.ddmanager.current;
1902                 if(this.options.activeClass) this.element.addClass(this.options.activeClass);
1903                 (draggable && this._trigger('activate', event, this.ui(draggable)));
1904         },
1905
1906         _deactivate: function(event) {
1907                 var draggable = $.ui.ddmanager.current;
1908                 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1909                 (draggable && this._trigger('deactivate', event, this.ui(draggable)));
1910         },
1911
1912         _over: function(event) {
1913
1914                 var draggable = $.ui.ddmanager.current;
1915                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1916
1917                 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1918                         if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
1919                         this._trigger('over', event, this.ui(draggable));
1920                 }
1921
1922         },
1923
1924         _out: function(event) {
1925
1926                 var draggable = $.ui.ddmanager.current;
1927                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
1928
1929                 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1930                         if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1931                         this._trigger('out', event, this.ui(draggable));
1932                 }
1933
1934         },
1935
1936         _drop: function(event,custom) {
1937
1938                 var draggable = custom || $.ui.ddmanager.current;
1939                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
1940
1941                 var childrenIntersection = false;
1942                 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
1943                         var inst = $.data(this, 'droppable');
1944                         if(
1945                                 inst.options.greedy
1946                                 && !inst.options.disabled
1947                                 && inst.options.scope == draggable.options.scope
1948                                 && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
1949                                 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
1950                         ) { childrenIntersection = true; return false; }
1951                 });
1952                 if(childrenIntersection) return false;
1953
1954                 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
1955                         if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
1956                         if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
1957                         this._trigger('drop', event, this.ui(draggable));
1958                         return this.element;
1959                 }
1960
1961                 return false;
1962
1963         },
1964
1965         ui: function(c) {
1966                 return {
1967                         draggable: (c.currentItem || c.element),
1968                         helper: c.helper,
1969                         position: c.position,
1970                         offset: c.positionAbs
1971                 };
1972         }
1973
1974 });
1975
1976 $.ui.intersect = function(draggable, droppable, toleranceMode) {
1977
1978         if (!droppable.offset) return false;
1979
1980         var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
1981                 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
1982         var l = droppable.offset.left, r = l + droppable.proportions.width,
1983                 t = droppable.offset.top, b = t + droppable.proportions.height;
1984
1985         switch (toleranceMode) {
1986                 case 'fit':
1987                         return (l <= x1 && x2 <= r
1988                                 && t <= y1 && y2 <= b);
1989                         break;
1990                 case 'intersect':
1991                         return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
1992                                 && x2 - (draggable.helperProportions.width / 2) < r // Left Half
1993                                 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
1994                                 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
1995                         break;
1996                 case 'pointer':
1997                         var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
1998                                 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
1999                                 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
2000                         return isOver;
2001                         break;
2002                 case 'touch':
2003                         return (
2004                                         (y1 >= t && y1 <= b) || // Top edge touching
2005                                         (y2 >= t && y2 <= b) || // Bottom edge touching
2006                                         (y1 < t && y2 > b)              // Surrounded vertically
2007                                 ) && (
2008                                         (x1 >= l && x1 <= r) || // Left edge touching
2009                                         (x2 >= l && x2 <= r) || // Right edge touching
2010                                         (x1 < l && x2 > r)              // Surrounded horizontally
2011                                 );
2012                         break;
2013                 default:
2014                         return false;
2015                         break;
2016                 }
2017
2018 };
2019
2020 /*
2021         This manager tracks offsets of draggables and droppables
2022 */
2023 $.ui.ddmanager = {
2024         current: null,
2025         droppables: { 'default': [] },
2026         prepareOffsets: function(t, event) {
2027
2028                 var m = $.ui.ddmanager.droppables[t.options.scope] || [];
2029                 var type = event ? event.type : null; // workaround for #2317
2030                 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
2031
2032                 droppablesLoop: for (var i = 0; i < m.length; i++) {
2033
2034                         if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;   //No disabled and non-accepted
2035                         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
2036                         m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue;                                                                       //If the element is not visible, continue
2037
2038                         if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
2039
2040                         m[i].offset = m[i].element.offset();
2041                         m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
2042
2043                 }
2044
2045         },
2046         drop: function(draggable, event) {
2047
2048                 var dropped = false;
2049                 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
2050
2051                         if(!this.options) return;
2052                         if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
2053                                 dropped = this._drop.call(this, event) || dropped;
2054
2055                         if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
2056                                 this.isout = 1; this.isover = 0;
2057                                 this._deactivate.call(this, event);
2058                         }
2059
2060                 });
2061                 return dropped;
2062
2063         },
2064         dragStart: function( draggable, event ) {
2065                 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
2066                 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
2067                         if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
2068                 });
2069         },
2070         drag: function(draggable, event) {
2071
2072                 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
2073                 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
2074
2075                 //Run through all droppables and check their positions based on specific tolerance options
2076                 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
2077
2078                         if(this.options.disabled || this.greedyChild || !this.visible) return;
2079                         var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
2080
2081                         var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
2082                         if(!c) return;
2083
2084                         var parentInstance;
2085                         if (this.options.greedy) {
2086                                 // find droppable parents with same scope
2087                                 var scope = this.options.scope;
2088                                 var parent = this.element.parents(':data(droppable)').filter(function () {
2089                                         return $.data(this, 'droppable').options.scope === scope;
2090                                 });
2091
2092                                 if (parent.length) {
2093                                         parentInstance = $.data(parent[0], 'droppable');
2094                                         parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
2095                                 }
2096                         }
2097
2098                         // we just moved into a greedy child
2099                         if (parentInstance && c == 'isover') {
2100                                 parentInstance['isover'] = 0;
2101                                 parentInstance['isout'] = 1;
2102                                 parentInstance._out.call(parentInstance, event);
2103                         }
2104
2105                         this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
2106                         this[c == "isover" ? "_over" : "_out"].call(this, event);
2107
2108                         // we just moved out of a greedy child
2109                         if (parentInstance && c == 'isout') {
2110                                 parentInstance['isout'] = 0;
2111                                 parentInstance['isover'] = 1;
2112                                 parentInstance._over.call(parentInstance, event);
2113                         }
2114                 });
2115
2116         },
2117         dragStop: function( draggable, event ) {
2118                 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
2119                 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
2120                 if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
2121         }
2122 };
2123
2124 })(jQuery);
2125 (function( $, undefined ) {
2126
2127 $.widget("ui.selectable", $.ui.mouse, {
2128         version: "1.9.2",
2129         options: {
2130                 appendTo: 'body',
2131                 autoRefresh: true,
2132                 distance: 0,
2133                 filter: '*',
2134                 tolerance: 'touch'
2135         },
2136         _create: function() {
2137                 var that = this;
2138
2139                 this.element.addClass("ui-selectable");
2140
2141                 this.dragged = false;
2142
2143                 // cache selectee children based on filter
2144                 var selectees;
2145                 this.refresh = function() {
2146                         selectees = $(that.options.filter, that.element[0]);
2147                         selectees.addClass("ui-selectee");
2148                         selectees.each(function() {
2149                                 var $this = $(this);
2150                                 var pos = $this.offset();
2151                                 $.data(this, "selectable-item", {
2152                                         element: this,
2153                                         $element: $this,
2154                                         left: pos.left,
2155                                         top: pos.top,
2156                                         right: pos.left + $this.outerWidth(),
2157                                         bottom: pos.top + $this.outerHeight(),
2158                                         startselected: false,
2159                                         selected: $this.hasClass('ui-selected'),
2160                                         selecting: $this.hasClass('ui-selecting'),
2161                                         unselecting: $this.hasClass('ui-unselecting')
2162                                 });
2163                         });
2164                 };
2165                 this.refresh();
2166
2167                 this.selectees = selectees.addClass("ui-selectee");
2168
2169                 this._mouseInit();
2170
2171                 this.helper = $("<div class='ui-selectable-helper'></div>");
2172         },
2173
2174         _destroy: function() {
2175                 this.selectees
2176                         .removeClass("ui-selectee")
2177                         .removeData("selectable-item");
2178                 this.element
2179                         .removeClass("ui-selectable ui-selectable-disabled");
2180                 this._mouseDestroy();
2181         },
2182
2183         _mouseStart: function(event) {
2184                 var that = this;
2185
2186                 this.opos = [event.pageX, event.pageY];
2187
2188                 if (this.options.disabled)
2189                         return;
2190
2191                 var options = this.options;
2192
2193                 this.selectees = $(options.filter, this.element[0]);
2194
2195                 this._trigger("start", event);
2196
2197                 $(options.appendTo).append(this.helper);
2198                 // position helper (lasso)
2199                 this.helper.css({
2200                         "left": event.clientX,
2201                         "top": event.clientY,
2202                         "width": 0,
2203                         "height": 0
2204                 });
2205
2206                 if (options.autoRefresh) {
2207                         this.refresh();
2208                 }
2209
2210                 this.selectees.filter('.ui-selected').each(function() {
2211                         var selectee = $.data(this, "selectable-item");
2212                         selectee.startselected = true;
2213                         if (!event.metaKey && !event.ctrlKey) {
2214                                 selectee.$element.removeClass('ui-selected');
2215                                 selectee.selected = false;
2216                                 selectee.$element.addClass('ui-unselecting');
2217                                 selectee.unselecting = true;
2218                                 // selectable UNSELECTING callback
2219                                 that._trigger("unselecting", event, {
2220                                         unselecting: selectee.element
2221                                 });
2222                         }
2223                 });
2224
2225                 $(event.target).parents().andSelf().each(function() {
2226                         var selectee = $.data(this, "selectable-item");
2227                         if (selectee) {
2228                                 var doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass('ui-selected');
2229                                 selectee.$element
2230                                         .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
2231                                         .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
2232                                 selectee.unselecting = !doSelect;
2233                                 selectee.selecting = doSelect;
2234                                 selectee.selected = doSelect;
2235                                 // selectable (UN)SELECTING callback
2236                                 if (doSelect) {
2237                                         that._trigger("selecting", event, {
2238                                                 selecting: selectee.element
2239                                         });
2240                                 } else {
2241                                         that._trigger("unselecting", event, {
2242                                                 unselecting: selectee.element
2243                                         });
2244                                 }
2245                                 return false;
2246                         }
2247                 });
2248
2249         },
2250
2251         _mouseDrag: function(event) {
2252                 var that = this;
2253                 this.dragged = true;
2254
2255                 if (this.options.disabled)
2256                         return;
2257
2258                 var options = this.options;
2259
2260                 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
2261                 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
2262                 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
2263                 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
2264
2265                 this.selectees.each(function() {
2266                         var selectee = $.data(this, "selectable-item");
2267                         //prevent helper from being selected if appendTo: selectable
2268                         if (!selectee || selectee.element == that.element[0])
2269                                 return;
2270                         var hit = false;
2271                         if (options.tolerance == 'touch') {
2272                                 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
2273                         } else if (options.tolerance == 'fit') {
2274                                 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
2275                         }
2276
2277                         if (hit) {
2278                                 // SELECT
2279                                 if (selectee.selected) {
2280                                         selectee.$element.removeClass('ui-selected');
2281                                         selectee.selected = false;
2282                                 }
2283                                 if (selectee.unselecting) {
2284                                         selectee.$element.removeClass('ui-unselecting');
2285                                         selectee.unselecting = false;
2286                                 }
2287                                 if (!selectee.selecting) {
2288                                         selectee.$element.addClass('ui-selecting');
2289                                         selectee.selecting = true;
2290                                         // selectable SELECTING callback
2291                                         that._trigger("selecting", event, {
2292                                                 selecting: selectee.element
2293                                         });
2294                                 }
2295                         } else {
2296                                 // UNSELECT
2297                                 if (selectee.selecting) {
2298                                         if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
2299                                                 selectee.$element.removeClass('ui-selecting');
2300                                                 selectee.selecting = false;
2301                                                 selectee.$element.addClass('ui-selected');
2302                                                 selectee.selected = true;
2303                                         } else {
2304                                                 selectee.$element.removeClass('ui-selecting');
2305                                                 selectee.selecting = false;
2306                                                 if (selectee.startselected) {
2307                                                         selectee.$element.addClass('ui-unselecting');
2308                                                         selectee.unselecting = true;
2309                                                 }
2310                                                 // selectable UNSELECTING callback
2311                                                 that._trigger("unselecting", event, {
2312                                                         unselecting: selectee.element
2313                                                 });
2314                                         }
2315                                 }
2316                                 if (selectee.selected) {
2317                                         if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
2318                                                 selectee.$element.removeClass('ui-selected');
2319                                                 selectee.selected = false;
2320
2321                                                 selectee.$element.addClass('ui-unselecting');
2322                                                 selectee.unselecting = true;
2323                                                 // selectable UNSELECTING callback
2324                                                 that._trigger("unselecting", event, {
2325                                                         unselecting: selectee.element
2326                                                 });
2327                                         }
2328                                 }
2329                         }
2330                 });
2331
2332                 return false;
2333         },
2334
2335         _mouseStop: function(event) {
2336                 var that = this;
2337
2338                 this.dragged = false;
2339
2340                 var options = this.options;
2341
2342                 $('.ui-unselecting', this.element[0]).each(function() {
2343                         var selectee = $.data(this, "selectable-item");
2344                         selectee.$element.removeClass('ui-unselecting');
2345                         selectee.unselecting = false;
2346                         selectee.startselected = false;
2347                         that._trigger("unselected", event, {
2348                                 unselected: selectee.element
2349                         });
2350                 });
2351                 $('.ui-selecting', this.element[0]).each(function() {
2352                         var selectee = $.data(this, "selectable-item");
2353                         selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
2354                         selectee.selecting = false;
2355                         selectee.selected = true;
2356                         selectee.startselected = true;
2357                         that._trigger("selected", event, {
2358                                 selected: selectee.element
2359                         });
2360                 });
2361                 this._trigger("stop", event);
2362
2363                 this.helper.remove();
2364
2365                 return false;
2366         }
2367
2368 });
2369
2370 })(jQuery);
2371 (function( $, undefined ) {
2372
2373 $.widget("ui.sortable", $.ui.mouse, {
2374         version: "1.9.2",
2375         widgetEventPrefix: "sort",
2376         ready: false,
2377         options: {
2378                 appendTo: "parent",
2379                 axis: false,
2380                 connectWith: false,
2381                 containment: false,
2382                 cursor: 'auto',
2383                 cursorAt: false,
2384                 dropOnEmpty: true,
2385                 forcePlaceholderSize: false,
2386                 forceHelperSize: false,
2387                 grid: false,
2388                 handle: false,
2389                 helper: "original",
2390                 items: '> *',
2391                 opacity: false,
2392                 placeholder: false,
2393                 revert: false,
2394                 scroll: true,
2395                 scrollSensitivity: 20,
2396                 scrollSpeed: 20,
2397                 scope: "default",
2398                 tolerance: "intersect",
2399                 zIndex: 1000
2400         },
2401         _create: function() {
2402
2403                 var o = this.options;
2404                 this.containerCache = {};
2405                 this.element.addClass("ui-sortable");
2406
2407                 //Get the items
2408                 this.refresh();
2409
2410                 //Let's determine if the items are being displayed horizontally
2411                 this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
2412
2413                 //Let's determine the parent's offset
2414                 this.offset = this.element.offset();
2415
2416                 //Initialize mouse events for interaction
2417                 this._mouseInit();
2418
2419                 //We're ready to go
2420                 this.ready = true
2421
2422         },
2423
2424         _destroy: function() {
2425                 this.element
2426                         .removeClass("ui-sortable ui-sortable-disabled");
2427                 this._mouseDestroy();
2428
2429                 for ( var i = this.items.length - 1; i >= 0; i-- )
2430                         this.items[i].item.removeData(this.widgetName + "-item");
2431
2432                 return this;
2433         },
2434
2435         _setOption: function(key, value){
2436                 if ( key === "disabled" ) {
2437                         this.options[ key ] = value;
2438
2439                         this.widget().toggleClass( "ui-sortable-disabled", !!value );
2440                 } else {
2441                         // Don't call widget base _setOption for disable as it adds ui-state-disabled class
2442                         $.Widget.prototype._setOption.apply(this, arguments);
2443                 }
2444         },
2445
2446         _mouseCapture: function(event, overrideHandle) {
2447                 var that = this;
2448
2449                 if (this.reverting) {
2450                         return false;
2451                 }
2452
2453                 if(this.options.disabled || this.options.type == 'static') return false;
2454
2455                 //We have to refresh the items data once first
2456                 this._refreshItems(event);
2457
2458                 //Find out if the clicked node (or one of its parents) is a actual item in this.items
2459                 var currentItem = null, nodes = $(event.target).parents().each(function() {
2460                         if($.data(this, that.widgetName + '-item') == that) {
2461                                 currentItem = $(this);
2462                                 return false;
2463                         }
2464                 });
2465                 if($.data(event.target, that.widgetName + '-item') == that) currentItem = $(event.target);
2466
2467                 if(!currentItem) return false;
2468                 if(this.options.handle && !overrideHandle) {
2469                         var validHandle = false;
2470
2471                         $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
2472                         if(!validHandle) return false;
2473                 }
2474
2475                 this.currentItem = currentItem;
2476                 this._removeCurrentsFromItems();
2477                 return true;
2478
2479         },
2480
2481         _mouseStart: function(event, overrideHandle, noActivation) {
2482
2483                 var o = this.options;
2484                 this.currentContainer = this;
2485
2486                 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
2487                 this.refreshPositions();
2488
2489                 //Create and append the visible helper
2490                 this.helper = this._createHelper(event);
2491
2492                 //Cache the helper size
2493                 this._cacheHelperProportions();
2494
2495                 /*
2496                  * - Position generation -
2497                  * This block generates everything position related - it's the core of draggables.
2498                  */
2499
2500                 //Cache the margins of the original element
2501                 this._cacheMargins();
2502
2503                 //Get the next scrolling parent
2504                 this.scrollParent = this.helper.scrollParent();
2505
2506                 //The element's absolute position on the page minus margins
2507                 this.offset = this.currentItem.offset();
2508                 this.offset = {
2509                         top: this.offset.top - this.margins.top,
2510                         left: this.offset.left - this.margins.left
2511                 };
2512
2513                 $.extend(this.offset, {
2514                         click: { //Where the click happened, relative to the element
2515                                 left: event.pageX - this.offset.left,
2516                                 top: event.pageY - this.offset.top
2517                         },
2518                         parent: this._getParentOffset(),
2519                         relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
2520                 });
2521
2522                 // Only after we got the offset, we can change the helper's position to absolute
2523                 // TODO: Still need to figure out a way to make relative sorting possible
2524                 this.helper.css("position", "absolute");
2525                 this.cssPosition = this.helper.css("position");
2526
2527                 //Generate the original position
2528                 this.originalPosition = this._generatePosition(event);
2529                 this.originalPageX = event.pageX;
2530                 this.originalPageY = event.pageY;
2531
2532                 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
2533                 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
2534
2535                 //Cache the former DOM position
2536                 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
2537
2538                 //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
2539                 if(this.helper[0] != this.currentItem[0]) {
2540                         this.currentItem.hide();
2541                 }
2542
2543                 //Create the placeholder
2544                 this._createPlaceholder();
2545
2546                 //Set a containment if given in the options
2547                 if(o.containment)
2548                         this._setContainment();
2549
2550                 if(o.cursor) { // cursor option
2551                         if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
2552                         $('body').css("cursor", o.cursor);
2553                 }
2554
2555                 if(o.opacity) { // opacity option
2556                         if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
2557                         this.helper.css("opacity", o.opacity);
2558                 }
2559
2560                 if(o.zIndex) { // zIndex option
2561                         if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
2562                         this.helper.css("zIndex", o.zIndex);
2563                 }
2564
2565                 //Prepare scrolling
2566                 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
2567                         this.overflowOffset = this.scrollParent.offset();
2568
2569                 //Call callbacks
2570                 this._trigger("start", event, this._uiHash());
2571
2572                 //Recache the helper size
2573                 if(!this._preserveHelperProportions)
2574                         this._cacheHelperProportions();
2575
2576
2577                 //Post 'activate' events to possible containers
2578                 if(!noActivation) {
2579                          for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, this._uiHash(this)); }
2580                 }
2581
2582                 //Prepare possible droppables
2583                 if($.ui.ddmanager)
2584                         $.ui.ddmanager.current = this;
2585
2586                 if ($.ui.ddmanager && !o.dropBehaviour)
2587                         $.ui.ddmanager.prepareOffsets(this, event);
2588
2589                 this.dragging = true;
2590
2591                 this.helper.addClass("ui-sortable-helper");
2592                 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
2593                 return true;
2594
2595         },
2596
2597         _mouseDrag: function(event) {
2598
2599                 //Compute the helpers position
2600                 this.position = this._generatePosition(event);
2601                 this.positionAbs = this._convertPositionTo("absolute");
2602
2603                 if (!this.lastPositionAbs) {
2604                         this.lastPositionAbs = this.positionAbs;
2605                 }
2606
2607                 //Do scrolling
2608                 if(this.options.scroll) {
2609                         var o = this.options, scrolled = false;
2610                         if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
2611
2612                                 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
2613                                         this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
2614                                 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
2615                                         this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
2616
2617                                 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
2618                                         this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
2619                                 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
2620                                         this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
2621
2622                         } else {
2623
2624                                 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
2625                                         scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
2626                                 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
2627                                         scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
2628
2629                                 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
2630                                         scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
2631                                 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
2632                                         scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
2633
2634                         }
2635
2636                         if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
2637                                 $.ui.ddmanager.prepareOffsets(this, event);
2638                 }
2639
2640                 //Regenerate the absolute position used for position checks
2641                 this.positionAbs = this._convertPositionTo("absolute");
2642
2643                 //Set the helper position
2644                 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
2645                 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
2646
2647                 //Rearrange
2648                 for (var i = this.items.length - 1; i >= 0; i--) {
2649
2650                         //Cache variables and intersection, continue if no intersection
2651                         var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
2652                         if (!intersection) continue;
2653
2654                         // Only put the placeholder inside the current Container, skip all
2655                         // items form other containers. This works because when moving
2656                         // an item from one container to another the
2657                         // currentContainer is switched before the placeholder is moved.
2658                         //
2659                         // Without this moving items in "sub-sortables" can cause the placeholder to jitter
2660                         // beetween the outer and inner container.
2661                         if (item.instance !== this.currentContainer) continue;
2662
2663                         if (itemElement != this.currentItem[0] //cannot intersect with itself
2664                                 &&      this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
2665                                 &&      !$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
2666                                 && (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true)
2667                                 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
2668                         ) {
2669
2670                                 this.direction = intersection == 1 ? "down" : "up";
2671
2672                                 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
2673                                         this._rearrange(event, item);
2674                                 } else {
2675                                         break;
2676                                 }
2677
2678                                 this._trigger("change", event, this._uiHash());
2679                                 break;
2680                         }
2681                 }
2682
2683                 //Post events to containers
2684                 this._contactContainers(event);
2685
2686                 //Interconnect with droppables
2687                 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
2688
2689                 //Call callbacks
2690                 this._trigger('sort', event, this._uiHash());
2691
2692                 this.lastPositionAbs = this.positionAbs;
2693                 return false;
2694
2695         },
2696
2697         _mouseStop: function(event, noPropagation) {
2698
2699                 if(!event) return;
2700
2701                 //If we are using droppables, inform the manager about the drop
2702                 if ($.ui.ddmanager && !this.options.dropBehaviour)
2703                         $.ui.ddmanager.drop(this, event);
2704
2705                 if(this.options.revert) {
2706                         var that = this;
2707                         var cur = this.placeholder.offset();
2708
2709                         this.reverting = true;
2710
2711                         $(this.helper).animate({
2712                                 left: cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
2713                                 top: cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
2714                         }, parseInt(this.options.revert, 10) || 500, function() {
2715                                 that._clear(event);
2716                         });
2717                 } else {
2718                         this._clear(event, noPropagation);
2719                 }
2720
2721                 return false;
2722
2723         },
2724
2725         cancel: function() {
2726
2727                 if(this.dragging) {
2728
2729                         this._mouseUp({ target: null });
2730
2731                         if(this.options.helper == "original")
2732                                 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
2733                         else
2734                                 this.currentItem.show();
2735
2736                         //Post deactivating events to containers
2737                         for (var i = this.containers.length - 1; i >= 0; i--){
2738                                 this.containers[i]._trigger("deactivate", null, this._uiHash(this));
2739                                 if(this.containers[i].containerCache.over) {
2740                                         this.containers[i]._trigger("out", null, this._uiHash(this));
2741                                         this.containers[i].containerCache.over = 0;
2742                                 }
2743                         }
2744
2745                 }
2746
2747                 if (this.placeholder) {
2748                         //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
2749                         if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
2750                         if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
2751
2752                         $.extend(this, {
2753                                 helper: null,
2754                                 dragging: false,
2755                                 reverting: false,
2756                                 _noFinalSort: null
2757                         });
2758
2759                         if(this.domPosition.prev) {
2760                                 $(this.domPosition.prev).after(this.currentItem);
2761                         } else {
2762                                 $(this.domPosition.parent).prepend(this.currentItem);
2763                         }
2764                 }
2765
2766                 return this;
2767
2768         },
2769
2770         serialize: function(o) {
2771
2772                 var items = this._getItemsAsjQuery(o && o.connected);
2773                 var str = []; o = o || {};
2774
2775                 $(items).each(function() {
2776                         var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
2777                         if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
2778                 });
2779
2780                 if(!str.length && o.key) {
2781                         str.push(o.key + '=');
2782                 }
2783
2784                 return str.join('&');
2785
2786         },
2787
2788         toArray: function(o) {
2789
2790                 var items = this._getItemsAsjQuery(o && o.connected);
2791                 var ret = []; o = o || {};
2792
2793                 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
2794                 return ret;
2795
2796         },
2797
2798         /* Be careful with the following core functions */
2799         _intersectsWith: function(item) {
2800
2801                 var x1 = this.positionAbs.left,
2802                         x2 = x1 + this.helperProportions.width,
2803                         y1 = this.positionAbs.top,
2804                         y2 = y1 + this.helperProportions.height;
2805
2806                 var l = item.left,
2807                         r = l + item.width,
2808                         t = item.top,
2809                         b = t + item.height;
2810
2811                 var dyClick = this.offset.click.top,
2812                         dxClick = this.offset.click.left;
2813
2814                 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
2815
2816                 if(        this.options.tolerance == "pointer"
2817                         || this.options.forcePointerForContainers
2818                         || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
2819                 ) {
2820                         return isOverElement;
2821                 } else {
2822
2823                         return (l < x1 + (this.helperProportions.width / 2) // Right Half
2824                                 && x2 - (this.helperProportions.width / 2) < r // Left Half
2825                                 && t < y1 + (this.helperProportions.height / 2) // Bottom Half
2826                                 && y2 - (this.helperProportions.height / 2) < b ); // Top Half
2827
2828                 }
2829         },
2830
2831         _intersectsWithPointer: function(item) {
2832
2833                 var isOverElementHeight = (this.options.axis === 'x') || $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
2834                         isOverElementWidth = (this.options.axis === 'y') || $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
2835                         isOverElement = isOverElementHeight && isOverElementWidth,
2836                         verticalDirection = this._getDragVerticalDirection(),
2837                         horizontalDirection = this._getDragHorizontalDirection();
2838
2839                 if (!isOverElement)
2840                         return false;
2841
2842                 return this.floating ?
2843                         ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
2844                         : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
2845
2846         },
2847
2848         _intersectsWithSides: function(item) {
2849
2850                 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
2851                         isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
2852                         verticalDirection = this._getDragVerticalDirection(),
2853                         horizontalDirection = this._getDragHorizontalDirection();
2854
2855                 if (this.floating && horizontalDirection) {
2856                         return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
2857                 } else {
2858                         return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
2859                 }
2860
2861         },
2862
2863         _getDragVerticalDirection: function() {
2864                 var delta = this.positionAbs.top - this.lastPositionAbs.top;
2865                 return delta != 0 && (delta > 0 ? "down" : "up");
2866         },
2867
2868         _getDragHorizontalDirection: function() {
2869                 var delta = this.positionAbs.left - this.lastPositionAbs.left;
2870                 return delta != 0 && (delta > 0 ? "right" : "left");
2871         },
2872
2873         refresh: function(event) {
2874                 this._refreshItems(event);
2875                 this.refreshPositions();
2876                 return this;
2877         },
2878
2879         _connectWith: function() {
2880                 var options = this.options;
2881                 return options.connectWith.constructor == String
2882                         ? [options.connectWith]
2883                         : options.connectWith;
2884         },
2885
2886         _getItemsAsjQuery: function(connected) {
2887
2888                 var items = [];
2889                 var queries = [];
2890                 var connectWith = this._connectWith();
2891
2892                 if(connectWith && connected) {
2893                         for (var i = connectWith.length - 1; i >= 0; i--){
2894                                 var cur = $(connectWith[i]);
2895                                 for (var j = cur.length - 1; j >= 0; j--){
2896                                         var inst = $.data(cur[j], this.widgetName);
2897                                         if(inst && inst != this && !inst.options.disabled) {
2898                                                 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]);
2899                                         }
2900                                 };
2901                         };
2902                 }
2903
2904                 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]);
2905
2906                 for (var i = queries.length - 1; i >= 0; i--){
2907                         queries[i][0].each(function() {
2908                                 items.push(this);
2909                         });
2910                 };
2911
2912                 return $(items);
2913
2914         },
2915
2916         _removeCurrentsFromItems: function() {
2917
2918                 var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
2919
2920                 this.items = $.grep(this.items, function (item) {
2921                         for (var j=0; j < list.length; j++) {
2922                                 if(list[j] == item.item[0])
2923                                         return false;
2924                         };
2925                         return true;
2926                 });
2927
2928         },
2929
2930         _refreshItems: function(event) {
2931
2932                 this.items = [];
2933                 this.containers = [this];
2934                 var items = this.items;
2935                 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
2936                 var connectWith = this._connectWith();
2937
2938                 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
2939                         for (var i = connectWith.length - 1; i >= 0; i--){
2940                                 var cur = $(connectWith[i]);
2941                                 for (var j = cur.length - 1; j >= 0; j--){
2942                                         var inst = $.data(cur[j], this.widgetName);
2943                                         if(inst && inst != this && !inst.options.disabled) {
2944                                                 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
2945                                                 this.containers.push(inst);
2946                                         }
2947                                 };
2948                         };
2949                 }
2950
2951                 for (var i = queries.length - 1; i >= 0; i--) {
2952                         var targetData = queries[i][1];
2953                         var _queries = queries[i][0];
2954
2955                         for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
2956                                 var item = $(_queries[j]);
2957
2958                                 item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager)
2959
2960                                 items.push({
2961                                         item: item,
2962                                         instance: targetData,
2963                                         width: 0, height: 0,
2964                                         left: 0, top: 0
2965                                 });
2966                         };
2967                 };
2968
2969         },
2970
2971         refreshPositions: function(fast) {
2972
2973                 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
2974                 if(this.offsetParent && this.helper) {
2975                         this.offset.parent = this._getParentOffset();
2976                 }
2977
2978                 for (var i = this.items.length - 1; i >= 0; i--){
2979                         var item = this.items[i];
2980
2981                         //We ignore calculating positions of all connected containers when we're not over them
2982                         if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
2983                                 continue;
2984
2985                         var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
2986
2987                         if (!fast) {
2988                                 item.width = t.outerWidth();
2989                                 item.height = t.outerHeight();
2990                         }
2991
2992                         var p = t.offset();
2993                         item.left = p.left;
2994                         item.top = p.top;
2995                 };
2996
2997                 if(this.options.custom && this.options.custom.refreshContainers) {
2998                         this.options.custom.refreshContainers.call(this);
2999                 } else {
3000                         for (var i = this.containers.length - 1; i >= 0; i--){
3001                                 var p = this.containers[i].element.offset();
3002                                 this.containers[i].containerCache.left = p.left;
3003                                 this.containers[i].containerCache.top = p.top;
3004                                 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
3005                                 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
3006                         };
3007                 }
3008
3009                 return this;
3010         },
3011
3012         _createPlaceholder: function(that) {
3013                 that = that || this;
3014                 var o = that.options;
3015
3016                 if(!o.placeholder || o.placeholder.constructor == String) {
3017                         var className = o.placeholder;
3018                         o.placeholder = {
3019                                 element: function() {
3020
3021                                         var el = $(document.createElement(that.currentItem[0].nodeName))
3022                                                 .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
3023                                                 .removeClass("ui-sortable-helper")[0];
3024
3025                                         if(!className)
3026                                                 el.style.visibility = "hidden";
3027
3028                                         return el;
3029                                 },
3030                                 update: function(container, p) {
3031
3032                                         // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
3033                                         // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
3034                                         if(className && !o.forcePlaceholderSize) return;
3035
3036                                         //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
3037                                         if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css('paddingTop')||0, 10) - parseInt(that.currentItem.css('paddingBottom')||0, 10)); };
3038                                         if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css('paddingLeft')||0, 10) - parseInt(that.currentItem.css('paddingRight')||0, 10)); };
3039                                 }
3040                         };
3041                 }
3042
3043                 //Create the placeholder
3044                 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
3045
3046                 //Append it after the actual current item
3047                 that.currentItem.after(that.placeholder);
3048
3049                 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
3050                 o.placeholder.update(that, that.placeholder);
3051
3052         },
3053
3054         _contactContainers: function(event) {
3055
3056                 // get innermost container that intersects with item
3057                 var innermostContainer = null, innermostIndex = null;
3058
3059
3060                 for (var i = this.containers.length - 1; i >= 0; i--){
3061
3062                         // never consider a container that's located within the item itself
3063                         if($.contains(this.currentItem[0], this.containers[i].element[0]))
3064                                 continue;
3065
3066                         if(this._intersectsWith(this.containers[i].containerCache)) {
3067
3068                                 // if we've already found a container and it's more "inner" than this, then continue
3069                                 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0]))
3070                                         continue;
3071
3072                                 innermostContainer = this.containers[i];
3073                                 innermostIndex = i;
3074
3075                         } else {
3076                                 // container doesn't intersect. trigger "out" event if necessary
3077                                 if(this.containers[i].containerCache.over) {
3078                                         this.containers[i]._trigger("out", event, this._uiHash(this));
3079                                         this.containers[i].containerCache.over = 0;
3080                                 }
3081                         }
3082
3083                 }
3084
3085                 // if no intersecting containers found, return
3086                 if(!innermostContainer) return;
3087
3088                 // move the item into the container if it's not there already
3089                 if(this.containers.length === 1) {
3090                         this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3091                         this.containers[innermostIndex].containerCache.over = 1;
3092                 } else {
3093
3094                         //When entering a new container, we will find the item with the least distance and append our item near it
3095                         var dist = 10000; var itemWithLeastDistance = null;
3096                         var posProperty = this.containers[innermostIndex].floating ? 'left' : 'top';
3097                         var sizeProperty = this.containers[innermostIndex].floating ? 'width' : 'height';
3098                         var base = this.positionAbs[posProperty] + this.offset.click[posProperty];
3099                         for (var j = this.items.length - 1; j >= 0; j--) {
3100                                 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
3101                                 if(this.items[j].item[0] == this.currentItem[0]) continue;
3102                                 var cur = this.items[j].item.offset()[posProperty];
3103                                 var nearBottom = false;
3104                                 if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){
3105                                         nearBottom = true;
3106                                         cur += this.items[j][sizeProperty];
3107                                 }
3108
3109                                 if(Math.abs(cur - base) < dist) {
3110                                         dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
3111                                         this.direction = nearBottom ? "up": "down";
3112                                 }
3113                         }
3114
3115                         if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
3116                                 return;
3117
3118                         this.currentContainer = this.containers[innermostIndex];
3119                         itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
3120                         this._trigger("change", event, this._uiHash());
3121                         this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
3122
3123                         //Update the placeholder
3124                         this.options.placeholder.update(this.currentContainer, this.placeholder);
3125
3126                         this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
3127                         this.containers[innermostIndex].containerCache.over = 1;
3128                 }
3129
3130
3131         },
3132
3133         _createHelper: function(event) {
3134
3135                 var o = this.options;
3136                 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
3137
3138                 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
3139                         $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
3140
3141                 if(helper[0] == this.currentItem[0])
3142                         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") };
3143
3144                 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
3145                 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
3146
3147                 return helper;
3148
3149         },
3150
3151         _adjustOffsetFromHelper: function(obj) {
3152                 if (typeof obj == 'string') {
3153                         obj = obj.split(' ');
3154                 }
3155                 if ($.isArray(obj)) {
3156                         obj = {left: +obj[0], top: +obj[1] || 0};
3157                 }
3158                 if ('left' in obj) {
3159                         this.offset.click.left = obj.left + this.margins.left;
3160                 }
3161                 if ('right' in obj) {
3162                         this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
3163                 }
3164                 if ('top' in obj) {
3165                         this.offset.click.top = obj.top + this.margins.top;
3166                 }
3167                 if ('bottom' in obj) {
3168                         this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
3169                 }
3170         },
3171
3172         _getParentOffset: function() {
3173
3174
3175                 //Get the offsetParent and cache its position
3176                 this.offsetParent = this.helper.offsetParent();
3177                 var po = this.offsetParent.offset();
3178
3179                 // This is a special case where we need to modify a offset calculated on start, since the following happened:
3180                 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
3181                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
3182                 //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
3183                 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
3184                         po.left += this.scrollParent.scrollLeft();
3185                         po.top += this.scrollParent.scrollTop();
3186                 }
3187
3188                 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
3189                 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.ui.ie)) //Ugly IE fix
3190                         po = { top: 0, left: 0 };
3191
3192                 return {
3193                         top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
3194                         left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
3195                 };
3196
3197         },
3198
3199         _getRelativeOffset: function() {
3200
3201                 if(this.cssPosition == "relative") {
3202                         var p = this.currentItem.position();
3203                         return {
3204                                 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
3205                                 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
3206                         };
3207                 } else {
3208                         return { top: 0, left: 0 };
3209                 }
3210
3211         },
3212
3213         _cacheMargins: function() {
3214                 this.margins = {
3215                         left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
3216                         top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
3217                 };
3218         },
3219
3220         _cacheHelperProportions: function() {
3221                 this.helperProportions = {
3222                         width: this.helper.outerWidth(),
3223                         height: this.helper.outerHeight()
3224                 };
3225         },
3226
3227         _setContainment: function() {
3228
3229                 var o = this.options;
3230                 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
3231                 if(o.containment == 'document' || o.containment == 'window') this.containment = [
3232                         0 - this.offset.relative.left - this.offset.parent.left,
3233                         0 - this.offset.relative.top - this.offset.parent.top,
3234                         $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
3235                         ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
3236                 ];
3237
3238                 if(!(/^(document|window|parent)$/).test(o.containment)) {
3239                         var ce = $(o.containment)[0];
3240                         var co = $(o.containment).offset();
3241                         var over = ($(ce).css("overflow") != 'hidden');
3242
3243                         this.containment = [
3244                                 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
3245                                 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
3246                                 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,
3247                                 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
3248                         ];
3249                 }
3250
3251         },
3252
3253         _convertPositionTo: function(d, pos) {
3254
3255                 if(!pos) pos = this.position;
3256                 var mod = d == "absolute" ? 1 : -1;
3257                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
3258
3259                 return {
3260                         top: (
3261                                 pos.top                                                                                                                                 // The absolute mouse position
3262                                 + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
3263                                 + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)
3264                                 - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
3265                         ),
3266                         left: (
3267                                 pos.left                                                                                                                                // The absolute mouse position
3268                                 + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
3269                                 + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)
3270                                 - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
3271                         )
3272                 };
3273
3274         },
3275
3276         _generatePosition: function(event) {
3277
3278                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
3279
3280                 // This is another very weird special case that only happens for relative elements:
3281                 // 1. If the css position is relative
3282                 // 2. and the scroll parent is the document or similar to the offset parent
3283                 // we have to refresh the relative offset during the scroll so there are no jumps
3284                 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
3285                         this.offset.relative = this._getRelativeOffset();
3286                 }
3287
3288                 var pageX = event.pageX;
3289                 var pageY = event.pageY;
3290
3291                 /*
3292                  * - Position constraining -
3293                  * Constrain the position to a mix of grid, containment.
3294                  */
3295
3296                 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
3297
3298                         if(this.containment) {
3299                                 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
3300                                 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
3301                                 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
3302                                 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
3303                         }
3304
3305                         if(o.grid) {
3306                                 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
3307                                 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;
3308
3309                                 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
3310                                 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;
3311                         }
3312
3313                 }
3314
3315                 return {
3316                         top: (
3317                                 pageY                                                                                                                           // The absolute mouse position
3318                                 - this.offset.click.top                                                                                                 // Click offset (relative to the element)
3319                                 - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
3320                                 - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)
3321                                 + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
3322                         ),
3323                         left: (
3324                                 pageX                                                                                                                           // The absolute mouse position
3325                                 - this.offset.click.left                                                                                                // Click offset (relative to the element)
3326                                 - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
3327                                 - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)
3328                                 + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
3329                         )
3330                 };
3331
3332         },
3333
3334         _rearrange: function(event, i, a, hardRefresh) {
3335
3336                 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));
3337
3338                 //Various things done here to improve the performance:
3339                 // 1. we create a setTimeout, that calls refreshPositions
3340                 // 2. on the instance, we have a counter variable, that get's higher after every append
3341                 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
3342                 // 4. this lets only the last addition to the timeout stack through
3343                 this.counter = this.counter ? ++this.counter : 1;
3344                 var counter = this.counter;
3345
3346                 this._delay(function() {
3347                         if(counter == this.counter) this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
3348                 });
3349
3350         },
3351
3352         _clear: function(event, noPropagation) {
3353
3354                 this.reverting = false;
3355                 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
3356                 // everything else normalized again
3357                 var delayedTriggers = [];
3358
3359                 // We first have to update the dom position of the actual currentItem
3360                 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
3361                 if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem);
3362                 this._noFinalSort = null;
3363
3364                 if(this.helper[0] == this.currentItem[0]) {
3365                         for(var i in this._storedCSS) {
3366                                 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
3367                         }
3368                         this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
3369                 } else {
3370                         this.currentItem.show();
3371                 }
3372
3373                 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
3374                 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
3375
3376                 // Check if the items Container has Changed and trigger appropriate
3377                 // events.
3378                 if (this !== this.currentContainer) {
3379                         if(!noPropagation) {
3380                                 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
3381                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.currentContainer));
3382                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.currentContainer));
3383                         }
3384                 }
3385
3386
3387                 //Post events to containers
3388                 for (var i = this.containers.length - 1; i >= 0; i--){
3389                         if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
3390                         if(this.containers[i].containerCache.over) {
3391                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
3392                                 this.containers[i].containerCache.over = 0;
3393                         }
3394                 }
3395
3396                 //Do what was originally in plugins
3397                 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
3398                 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
3399                 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
3400
3401                 this.dragging = false;
3402                 if(this.cancelHelperRemoval) {
3403                         if(!noPropagation) {
3404                                 this._trigger("beforeStop", event, this._uiHash());
3405                                 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
3406                                 this._trigger("stop", event, this._uiHash());
3407                         }
3408
3409                         this.fromOutside = false;
3410                         return false;
3411                 }
3412
3413                 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
3414
3415                 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
3416                 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
3417
3418                 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
3419
3420                 if(!noPropagation) {
3421                         for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
3422                         this._trigger("stop", event, this._uiHash());
3423                 }
3424
3425                 this.fromOutside = false;
3426                 return true;
3427
3428         },
3429
3430         _trigger: function() {
3431                 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
3432                         this.cancel();
3433                 }
3434         },
3435
3436         _uiHash: function(_inst) {
3437                 var inst = _inst || this;
3438                 return {
3439                         helper: inst.helper,
3440                         placeholder: inst.placeholder || $([]),
3441                         position: inst.position,
3442                         originalPosition: inst.originalPosition,
3443                         offset: inst.positionAbs,
3444                         item: inst.currentItem,
3445                         sender: _inst ? _inst.element : null
3446                 };
3447         }
3448
3449 });
3450
3451 })(jQuery);