[SPIP] +spip v3.0.17
[lhc/web/clavette_www.git] / www / prive / formulaires / selecteur / jquery-ui-1.8.custom.js
1 /*!
2 * jQuery UI 1.8.21
3 *
4 * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT or GPL Version 2 licenses.
6 * http://jquery.org/license
7 *
8 * http://docs.jquery.com/UI
9 */
10 (function( $, undefined ) {
11
12 // prevent duplicate loading
13 // this is only a problem because we proxy existing functions
14 // and we don't want to double proxy them
15 $.ui = $.ui || {};
16 if ( $.ui.version ) {
17 return;
18 }
19
20 $.extend( $.ui, {
21 version: "1.8.21",
22
23 keyCode: {
24 ALT: 18,
25 BACKSPACE: 8,
26 CAPS_LOCK: 20,
27 COMMA: 188,
28 COMMAND: 91,
29 COMMAND_LEFT: 91, // COMMAND
30 COMMAND_RIGHT: 93,
31 CONTROL: 17,
32 DELETE: 46,
33 DOWN: 40,
34 END: 35,
35 ENTER: 13,
36 ESCAPE: 27,
37 HOME: 36,
38 INSERT: 45,
39 LEFT: 37,
40 MENU: 93, // COMMAND_RIGHT
41 NUMPAD_ADD: 107,
42 NUMPAD_DECIMAL: 110,
43 NUMPAD_DIVIDE: 111,
44 NUMPAD_ENTER: 108,
45 NUMPAD_MULTIPLY: 106,
46 NUMPAD_SUBTRACT: 109,
47 PAGE_DOWN: 34,
48 PAGE_UP: 33,
49 PERIOD: 190,
50 RIGHT: 39,
51 SHIFT: 16,
52 SPACE: 32,
53 TAB: 9,
54 UP: 38,
55 WINDOWS: 91 // COMMAND
56 }
57 });
58
59 // plugins
60 $.fn.extend({
61 propAttr: $.fn.prop || $.fn.attr,
62
63 _focus: $.fn.focus,
64 focus: function( delay, fn ) {
65 return typeof delay === "number" ?
66 this.each(function() {
67 var elem = this;
68 setTimeout(function() {
69 $( elem ).focus();
70 if ( fn ) {
71 fn.call( elem );
72 }
73 }, delay );
74 }) :
75 this._focus.apply( this, arguments );
76 },
77
78 scrollParent: function() {
79 var scrollParent;
80 if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
81 scrollParent = this.parents().filter(function() {
82 return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
83 }).eq(0);
84 } else {
85 scrollParent = this.parents().filter(function() {
86 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
87 }).eq(0);
88 }
89
90 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
91 },
92
93 zIndex: function( zIndex ) {
94 if ( zIndex !== undefined ) {
95 return this.css( "zIndex", zIndex );
96 }
97
98 if ( this.length ) {
99 var elem = $( this[ 0 ] ), position, value;
100 while ( elem.length && elem[ 0 ] !== document ) {
101 // Ignore z-index if position is set to a value where z-index is ignored by the browser
102 // This makes behavior of this function consistent across browsers
103 // WebKit always returns auto if the element is positioned
104 position = elem.css( "position" );
105 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
106 // IE returns 0 when zIndex is not specified
107 // other browsers return a string
108 // we ignore the case of nested elements with an explicit value of 0
109 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
110 value = parseInt( elem.css( "zIndex" ), 10 );
111 if ( !isNaN( value ) && value !== 0 ) {
112 return value;
113 }
114 }
115 elem = elem.parent();
116 }
117 }
118
119 return 0;
120 },
121
122 disableSelection: function() {
123 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
124 ".ui-disableSelection", function( event ) {
125 event.preventDefault();
126 });
127 },
128
129 enableSelection: function() {
130 return this.unbind( ".ui-disableSelection" );
131 }
132 });
133
134 $.each( [ "Width", "Height" ], function( i, name ) {
135 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
136 type = name.toLowerCase(),
137 orig = {
138 innerWidth: $.fn.innerWidth,
139 innerHeight: $.fn.innerHeight,
140 outerWidth: $.fn.outerWidth,
141 outerHeight: $.fn.outerHeight
142 };
143
144 function reduce( elem, size, border, margin ) {
145 $.each( side, function() {
146 size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
147 if ( border ) {
148 size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
149 }
150 if ( margin ) {
151 size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
152 }
153 });
154 return size;
155 }
156
157 $.fn[ "inner" + name ] = function( size ) {
158 if ( size === undefined ) {
159 return orig[ "inner" + name ].call( this );
160 }
161
162 return this.each(function() {
163 $( this ).css( type, reduce( this, size ) + "px" );
164 });
165 };
166
167 $.fn[ "outer" + name] = function( size, margin ) {
168 if ( typeof size !== "number" ) {
169 return orig[ "outer" + name ].call( this, size );
170 }
171
172 return this.each(function() {
173 $( this).css( type, reduce( this, size, true, margin ) + "px" );
174 });
175 };
176 });
177
178 // selectors
179 function focusable( element, isTabIndexNotNaN ) {
180 var nodeName = element.nodeName.toLowerCase();
181 if ( "area" === nodeName ) {
182 var map = element.parentNode,
183 mapName = map.name,
184 img;
185 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
186 return false;
187 }
188 img = $( "img[usemap=#" + mapName + "]" )[0];
189 return !!img && visible( img );
190 }
191 return ( /input|select|textarea|button|object/.test( nodeName )
192 ? !element.disabled
193 : "a" == nodeName
194 ? element.href || isTabIndexNotNaN
195 : isTabIndexNotNaN)
196 // the element and all of its ancestors must be visible
197 && visible( element );
198 }
199
200 function visible( element ) {
201 return !$( element ).parents().andSelf().filter(function() {
202 return $.curCSS( this, "visibility" ) === "hidden" ||
203 $.expr.filters.hidden( this );
204 }).length;
205 }
206
207 $.extend( $.expr[ ":" ], {
208 data: function( elem, i, match ) {
209 return !!$.data( elem, match[ 3 ] );
210 },
211
212 focusable: function( element ) {
213 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
214 },
215
216 tabbable: function( element ) {
217 var tabIndex = $.attr( element, "tabindex" ),
218 isTabIndexNaN = isNaN( tabIndex );
219 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
220 }
221 });
222
223 // support
224 $(function() {
225 var body = document.body,
226 div = body.appendChild( div = document.createElement( "div" ) );
227
228 // access offsetHeight before setting the style to prevent a layout bug
229 // in IE 9 which causes the elemnt to continue to take up space even
230 // after it is removed from the DOM (#8026)
231 div.offsetHeight;
232
233 $.extend( div.style, {
234 minHeight: "100px",
235 height: "auto",
236 padding: 0,
237 borderWidth: 0
238 });
239
240 $.support.minHeight = div.offsetHeight === 100;
241 $.support.selectstart = "onselectstart" in div;
242
243 // set display to none to avoid a layout bug in IE
244 // http://dev.jquery.com/ticket/4014
245 body.removeChild( div ).style.display = "none";
246 });
247
248
249
250
251
252 // deprecated
253 $.extend( $.ui, {
254 // $.ui.plugin is deprecated. Use the proxy pattern instead.
255 plugin: {
256 add: function( module, option, set ) {
257 var proto = $.ui[ module ].prototype;
258 for ( var i in set ) {
259 proto.plugins[ i ] = proto.plugins[ i ] || [];
260 proto.plugins[ i ].push( [ option, set[ i ] ] );
261 }
262 },
263 call: function( instance, name, args ) {
264 var set = instance.plugins[ name ];
265 if ( !set || !instance.element[ 0 ].parentNode ) {
266 return;
267 }
268
269 for ( var i = 0; i < set.length; i++ ) {
270 if ( instance.options[ set[ i ][ 0 ] ] ) {
271 set[ i ][ 1 ].apply( instance.element, args );
272 }
273 }
274 }
275 },
276
277 // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
278 contains: function( a, b ) {
279 return document.compareDocumentPosition ?
280 a.compareDocumentPosition( b ) & 16 :
281 a !== b && a.contains( b );
282 },
283
284 // only used by resizable
285 hasScroll: function( el, a ) {
286
287 //If overflow is hidden, the element might have extra content, but the user wants to hide it
288 if ( $( el ).css( "overflow" ) === "hidden") {
289 return false;
290 }
291
292 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
293 has = false;
294
295 if ( el[ scroll ] > 0 ) {
296 return true;
297 }
298
299 // TODO: determine which cases actually cause this to happen
300 // if the element doesn't have the scroll set, see if it's possible to
301 // set the scroll
302 el[ scroll ] = 1;
303 has = ( el[ scroll ] > 0 );
304 el[ scroll ] = 0;
305 return has;
306 },
307
308 // these are odd functions, fix the API or move into individual plugins
309 isOverAxis: function( x, reference, size ) {
310 //Determines when x coordinate is over "b" element axis
311 return ( x > reference ) && ( x < ( reference + size ) );
312 },
313 isOver: function( y, x, top, left, height, width ) {
314 //Determines when x, y coordinates is over "b" element
315 return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
316 }
317 });
318
319 })( jQuery );
320 /*!
321 * jQuery UI Widget 1.8.21
322 *
323 * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
324 * Dual licensed under the MIT or GPL Version 2 licenses.
325 * http://jquery.org/license
326 *
327 * http://docs.jquery.com/UI/Widget
328 */
329 (function( $, undefined ) {
330
331 // jQuery 1.4+
332 if ( $.cleanData ) {
333 var _cleanData = $.cleanData;
334 $.cleanData = function( elems ) {
335 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
336 try {
337 $( elem ).triggerHandler( "remove" );
338 // http://bugs.jquery.com/ticket/8235
339 } catch( e ) {}
340 }
341 _cleanData( elems );
342 };
343 } else {
344 var _remove = $.fn.remove;
345 $.fn.remove = function( selector, keepData ) {
346 return this.each(function() {
347 if ( !keepData ) {
348 if ( !selector || $.filter( selector, [ this ] ).length ) {
349 $( "*", this ).add( [ this ] ).each(function() {
350 try {
351 $( this ).triggerHandler( "remove" );
352 // http://bugs.jquery.com/ticket/8235
353 } catch( e ) {}
354 });
355 }
356 }
357 return _remove.call( $(this), selector, keepData );
358 });
359 };
360 }
361
362 $.widget = function( name, base, prototype ) {
363 var namespace = name.split( "." )[ 0 ],
364 fullName;
365 name = name.split( "." )[ 1 ];
366 fullName = namespace + "-" + name;
367
368 if ( !prototype ) {
369 prototype = base;
370 base = $.Widget;
371 }
372
373 // create selector for plugin
374 $.expr[ ":" ][ fullName ] = function( elem ) {
375 return !!$.data( elem, name );
376 };
377
378 $[ namespace ] = $[ namespace ] || {};
379 $[ namespace ][ name ] = function( options, element ) {
380 // allow instantiation without initializing for simple inheritance
381 if ( arguments.length ) {
382 this._createWidget( options, element );
383 }
384 };
385
386 var basePrototype = new base();
387 // we need to make the options hash a property directly on the new instance
388 // otherwise we'll modify the options hash on the prototype that we're
389 // inheriting from
390 // $.each( basePrototype, function( key, val ) {
391 // if ( $.isPlainObject(val) ) {
392 // basePrototype[ key ] = $.extend( {}, val );
393 // }
394 // });
395 basePrototype.options = $.extend( true, {}, basePrototype.options );
396 $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
397 namespace: namespace,
398 widgetName: name,
399 widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
400 widgetBaseClass: fullName
401 }, prototype );
402
403 $.widget.bridge( name, $[ namespace ][ name ] );
404 };
405
406 $.widget.bridge = function( name, object ) {
407 $.fn[ name ] = function( options ) {
408 var isMethodCall = typeof options === "string",
409 args = Array.prototype.slice.call( arguments, 1 ),
410 returnValue = this;
411
412 // allow multiple hashes to be passed on init
413 options = !isMethodCall && args.length ?
414 $.extend.apply( null, [ true, options ].concat(args) ) :
415 options;
416
417 // prevent calls to internal methods
418 if ( isMethodCall && options.charAt( 0 ) === "_" ) {
419 return returnValue;
420 }
421
422 if ( isMethodCall ) {
423 this.each(function() {
424 var instance = $.data( this, name ),
425 methodValue = instance && $.isFunction( instance[options] ) ?
426 instance[ options ].apply( instance, args ) :
427 instance;
428 // TODO: add this back in 1.9 and use $.error() (see #5972)
429 // if ( !instance ) {
430 // throw "cannot call methods on " + name + " prior to initialization; " +
431 // "attempted to call method '" + options + "'";
432 // }
433 // if ( !$.isFunction( instance[options] ) ) {
434 // throw "no such method '" + options + "' for " + name + " widget instance";
435 // }
436 // var methodValue = instance[ options ].apply( instance, args );
437 if ( methodValue !== instance && methodValue !== undefined ) {
438 returnValue = methodValue;
439 return false;
440 }
441 });
442 } else {
443 this.each(function() {
444 var instance = $.data( this, name );
445 if ( instance ) {
446 instance.option( options || {} )._init();
447 } else {
448 $.data( this, name, new object( options, this ) );
449 }
450 });
451 }
452
453 return returnValue;
454 };
455 };
456
457 $.Widget = function( options, element ) {
458 // allow instantiation without initializing for simple inheritance
459 if ( arguments.length ) {
460 this._createWidget( options, element );
461 }
462 };
463
464 $.Widget.prototype = {
465 widgetName: "widget",
466 widgetEventPrefix: "",
467 options: {
468 disabled: false
469 },
470 _createWidget: function( options, element ) {
471 // $.widget.bridge stores the plugin instance, but we do it anyway
472 // so that it's stored even before the _create function runs
473 $.data( element, this.widgetName, this );
474 this.element = $( element );
475 this.options = $.extend( true, {},
476 this.options,
477 this._getCreateOptions(),
478 options );
479
480 var self = this;
481 this.element.bind( "remove." + this.widgetName, function() {
482 self.destroy();
483 });
484
485 this._create();
486 this._trigger( "create" );
487 this._init();
488 },
489 _getCreateOptions: function() {
490 return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
491 },
492 _create: function() {},
493 _init: function() {},
494
495 destroy: function() {
496 this.element
497 .unbind( "." + this.widgetName )
498 .removeData( this.widgetName );
499 this.widget()
500 .unbind( "." + this.widgetName )
501 .removeAttr( "aria-disabled" )
502 .removeClass(
503 this.widgetBaseClass + "-disabled " +
504 "ui-state-disabled" );
505 },
506
507 widget: function() {
508 return this.element;
509 },
510
511 option: function( key, value ) {
512 var options = key;
513
514 if ( arguments.length === 0 ) {
515 // don't return a reference to the internal hash
516 return $.extend( {}, this.options );
517 }
518
519 if (typeof key === "string" ) {
520 if ( value === undefined ) {
521 return this.options[ key ];
522 }
523 options = {};
524 options[ key ] = value;
525 }
526
527 this._setOptions( options );
528
529 return this;
530 },
531 _setOptions: function( options ) {
532 var self = this;
533 $.each( options, function( key, value ) {
534 self._setOption( key, value );
535 });
536
537 return this;
538 },
539 _setOption: function( key, value ) {
540 this.options[ key ] = value;
541
542 if ( key === "disabled" ) {
543 this.widget()
544 [ value ? "addClass" : "removeClass"](
545 this.widgetBaseClass + "-disabled" + " " +
546 "ui-state-disabled" )
547 .attr( "aria-disabled", value );
548 }
549
550 return this;
551 },
552
553 enable: function() {
554 return this._setOption( "disabled", false );
555 },
556 disable: function() {
557 return this._setOption( "disabled", true );
558 },
559
560 _trigger: function( type, event, data ) {
561 var prop, orig,
562 callback = this.options[ type ];
563
564 data = data || {};
565 event = $.Event( event );
566 event.type = ( type === this.widgetEventPrefix ?
567 type :
568 this.widgetEventPrefix + type ).toLowerCase();
569 // the original event may come from any element
570 // so we need to reset the target on the new event
571 event.target = this.element[ 0 ];
572
573 // copy original event properties over to the new event
574 orig = event.originalEvent;
575 if ( orig ) {
576 for ( prop in orig ) {
577 if ( !( prop in event ) ) {
578 event[ prop ] = orig[ prop ];
579 }
580 }
581 }
582
583 this.element.trigger( event, data );
584
585 return !( $.isFunction(callback) &&
586 callback.call( this.element[0], event, data ) === false ||
587 event.isDefaultPrevented() );
588 }
589 };
590
591 })( jQuery );
592 /*!
593 * jQuery UI Mouse 1.8.21
594 *
595 * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
596 * Dual licensed under the MIT or GPL Version 2 licenses.
597 * http://jquery.org/license
598 *
599 * http://docs.jquery.com/UI/Mouse
600 *
601 * Depends:
602 * jquery.ui.widget.js
603 */
604 (function( $, undefined ) {
605
606 var mouseHandled = false;
607 $( document ).mouseup( function( e ) {
608 mouseHandled = false;
609 });
610
611 $.widget("ui.mouse", {
612 options: {
613 cancel: ':input,option',
614 distance: 1,
615 delay: 0
616 },
617 _mouseInit: function() {
618 var self = this;
619
620 this.element
621 .bind('mousedown.'+this.widgetName, function(event) {
622 return self._mouseDown(event);
623 })
624 .bind('click.'+this.widgetName, function(event) {
625 if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
626 $.removeData(event.target, self.widgetName + '.preventClickEvent');
627 event.stopImmediatePropagation();
628 return false;
629 }
630 });
631
632 this.started = false;
633 },
634
635 // TODO: make sure destroying one instance of mouse doesn't mess with
636 // other instances of mouse
637 _mouseDestroy: function() {
638 this.element.unbind('.'+this.widgetName);
639 $(document)
640 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
641 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
642 },
643
644 _mouseDown: function(event) {
645 // don't let more than one widget handle mouseStart
646 if( mouseHandled ) { return };
647
648 // we may have missed mouseup (out of window)
649 (this._mouseStarted && this._mouseUp(event));
650
651 this._mouseDownEvent = event;
652
653 var self = this,
654 btnIsLeft = (event.which == 1),
655 // event.target.nodeName works around a bug in IE 8 with
656 // disabled inputs (#7620)
657 elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
658 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
659 return true;
660 }
661
662 this.mouseDelayMet = !this.options.delay;
663 if (!this.mouseDelayMet) {
664 this._mouseDelayTimer = setTimeout(function() {
665 self.mouseDelayMet = true;
666 }, this.options.delay);
667 }
668
669 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
670 this._mouseStarted = (this._mouseStart(event) !== false);
671 if (!this._mouseStarted) {
672 event.preventDefault();
673 return true;
674 }
675 }
676
677 // Click event may never have fired (Gecko & Opera)
678 if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
679 $.removeData(event.target, this.widgetName + '.preventClickEvent');
680 }
681
682 // these delegates are required to keep context
683 this._mouseMoveDelegate = function(event) {
684 return self._mouseMove(event);
685 };
686 this._mouseUpDelegate = function(event) {
687 return self._mouseUp(event);
688 };
689 $(document)
690 .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
691 .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
692
693 event.preventDefault();
694
695 mouseHandled = true;
696 return true;
697 },
698
699 _mouseMove: function(event) {
700 // IE mouseup check - mouseup happened when mouse was out of window
701 if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
702 return this._mouseUp(event);
703 }
704
705 if (this._mouseStarted) {
706 this._mouseDrag(event);
707 return event.preventDefault();
708 }
709
710 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
711 this._mouseStarted =
712 (this._mouseStart(this._mouseDownEvent, event) !== false);
713 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
714 }
715
716 return !this._mouseStarted;
717 },
718
719 _mouseUp: function(event) {
720 $(document)
721 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
722 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
723
724 if (this._mouseStarted) {
725 this._mouseStarted = false;
726
727 if (event.target == this._mouseDownEvent.target) {
728 $.data(event.target, this.widgetName + '.preventClickEvent', true);
729 }
730
731 this._mouseStop(event);
732 }
733
734 return false;
735 },
736
737 _mouseDistanceMet: function(event) {
738 return (Math.max(
739 Math.abs(this._mouseDownEvent.pageX - event.pageX),
740 Math.abs(this._mouseDownEvent.pageY - event.pageY)
741 ) >= this.options.distance
742 );
743 },
744
745 _mouseDelayMet: function(event) {
746 return this.mouseDelayMet;
747 },
748
749 // These are placeholder methods, to be overriden by extending plugin
750 _mouseStart: function(event) {},
751 _mouseDrag: function(event) {},
752 _mouseStop: function(event) {},
753 _mouseCapture: function(event) { return true; }
754 });
755
756 })(jQuery);
757 /*!
758 * jQuery UI Draggable 1.8.21
759 *
760 * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
761 * Dual licensed under the MIT or GPL Version 2 licenses.
762 * http://jquery.org/license
763 *
764 * http://docs.jquery.com/UI/Draggables
765 *
766 * Depends:
767 * jquery.ui.core.js
768 * jquery.ui.mouse.js
769 * jquery.ui.widget.js
770 */
771 (function( $, undefined ) {
772
773 $.widget("ui.draggable", $.ui.mouse, {
774 widgetEventPrefix: "drag",
775 options: {
776 addClasses: true,
777 appendTo: "parent",
778 axis: false,
779 connectToSortable: false,
780 containment: false,
781 cursor: "auto",
782 cursorAt: false,
783 grid: false,
784 handle: false,
785 helper: "original",
786 iframeFix: false,
787 opacity: false,
788 refreshPositions: false,
789 revert: false,
790 revertDuration: 500,
791 scope: "default",
792 scroll: true,
793 scrollSensitivity: 20,
794 scrollSpeed: 20,
795 snap: false,
796 snapMode: "both",
797 snapTolerance: 20,
798 stack: false,
799 zIndex: false
800 },
801 _create: function() {
802
803 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
804 this.element[0].style.position = 'relative';
805
806 (this.options.addClasses && this.element.addClass("ui-draggable"));
807 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
808
809 this._mouseInit();
810
811 },
812
813 destroy: function() {
814 if(!this.element.data('draggable')) return;
815 this.element
816 .removeData("draggable")
817 .unbind(".draggable")
818 .removeClass("ui-draggable"
819 + " ui-draggable-dragging"
820 + " ui-draggable-disabled");
821 this._mouseDestroy();
822
823 return this;
824 },
825
826 _mouseCapture: function(event) {
827
828 var o = this.options;
829
830 // among others, prevent a drag on a resizable-handle
831 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
832 return false;
833
834 //Quit if we're not on a valid handle
835 this.handle = this._getHandle(event);
836 if (!this.handle)
837 return false;
838
839 if ( o.iframeFix ) {
840 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
841 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
842 .css({
843 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
844 position: "absolute", opacity: "0.001", zIndex: 1000
845 })
846 .css($(this).offset())
847 .appendTo("body");
848 });
849 }
850
851 return true;
852
853 },
854
855 _mouseStart: function(event) {
856
857 var o = this.options;
858
859 //Create and append the visible helper
860 this.helper = this._createHelper(event);
861
862 this.helper.addClass("ui-draggable-dragging");
863
864 //Cache the helper size
865 this._cacheHelperProportions();
866
867 //If ddmanager is used for droppables, set the global draggable
868 if($.ui.ddmanager)
869 $.ui.ddmanager.current = this;
870
871 /*
872 * - Position generation -
873 * This block generates everything position related - it's the core of draggables.
874 */
875
876 //Cache the margins of the original element
877 this._cacheMargins();
878
879 //Store the helper's css position
880 this.cssPosition = this.helper.css("position");
881 this.scrollParent = this.helper.scrollParent();
882
883 //The element's absolute position on the page minus margins
884 this.offset = this.positionAbs = this.element.offset();
885 this.offset = {
886 top: this.offset.top - this.margins.top,
887 left: this.offset.left - this.margins.left
888 };
889
890 $.extend(this.offset, {
891 click: { //Where the click happened, relative to the element
892 left: event.pageX - this.offset.left,
893 top: event.pageY - this.offset.top
894 },
895 parent: this._getParentOffset(),
896 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
897 });
898
899 //Generate the original position
900 this.originalPosition = this.position = this._generatePosition(event);
901 this.originalPageX = event.pageX;
902 this.originalPageY = event.pageY;
903
904 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
905 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
906
907 //Set a containment if given in the options
908 if(o.containment)
909 this._setContainment();
910
911 //Trigger event + callbacks
912 if(this._trigger("start", event) === false) {
913 this._clear();
914 return false;
915 }
916
917 //Recache the helper size
918 this._cacheHelperProportions();
919
920 //Prepare the droppable offsets
921 if ($.ui.ddmanager && !o.dropBehaviour)
922 $.ui.ddmanager.prepareOffsets(this, event);
923
924
925 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
926
927 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
928 if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event);
929
930 return true;
931 },
932
933 _mouseDrag: function(event, noPropagation) {
934
935 //Compute the helpers position
936 this.position = this._generatePosition(event);
937 this.positionAbs = this._convertPositionTo("absolute");
938
939 //Call plugins and callbacks and use the resulting position if something is returned
940 if (!noPropagation) {
941 var ui = this._uiHash();
942 if(this._trigger('drag', event, ui) === false) {
943 this._mouseUp({});
944 return false;
945 }
946 this.position = ui.position;
947 }
948
949 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
950 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
951 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
952
953 return false;
954 },
955
956 _mouseStop: function(event) {
957
958 //If we are using droppables, inform the manager about the drop
959 var dropped = false;
960 if ($.ui.ddmanager && !this.options.dropBehaviour)
961 dropped = $.ui.ddmanager.drop(this, event);
962
963 //if a drop comes from outside (a sortable)
964 if(this.dropped) {
965 dropped = this.dropped;
966 this.dropped = false;
967 }
968
969 //if the original element is no longer in the DOM don't bother to continue (see #8269)
970 var element = this.element[0], elementInDom = false;
971 while ( element && (element = element.parentNode) ) {
972 if (element == document ) {
973 elementInDom = true;
974 }
975 }
976 if ( !elementInDom && this.options.helper === "original" )
977 return false;
978
979 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))) {
980 var self = this;
981 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
982 if(self._trigger("stop", event) !== false) {
983 self._clear();
984 }
985 });
986 } else {
987 if(this._trigger("stop", event) !== false) {
988 this._clear();
989 }
990 }
991
992 return false;
993 },
994
995 _mouseUp: function(event) {
996 if (this.options.iframeFix === true) {
997 $("div.ui-draggable-iframeFix").each(function() {
998 this.parentNode.removeChild(this);
999 }); //Remove frame helpers
1000 }
1001
1002 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
1003 if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event);
1004
1005 return $.ui.mouse.prototype._mouseUp.call(this, event);
1006 },
1007
1008 cancel: function() {
1009
1010 if(this.helper.is(".ui-draggable-dragging")) {
1011 this._mouseUp({});
1012 } else {
1013 this._clear();
1014 }
1015
1016 return this;
1017
1018 },
1019
1020 _getHandle: function(event) {
1021
1022 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
1023 $(this.options.handle, this.element)
1024 .find("*")
1025 .andSelf()
1026 .each(function() {
1027 if(this == event.target) handle = true;
1028 });
1029
1030 return handle;
1031
1032 },
1033
1034 _createHelper: function(event) {
1035
1036 var o = this.options;
1037 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element);
1038
1039 if(!helper.parents('body').length)
1040 helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
1041
1042 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
1043 helper.css("position", "absolute");
1044
1045 return helper;
1046
1047 },
1048
1049 _adjustOffsetFromHelper: function(obj) {
1050 if (typeof obj == 'string') {
1051 obj = obj.split(' ');
1052 }
1053 if ($.isArray(obj)) {
1054 obj = {left: +obj[0], top: +obj[1] || 0};
1055 }
1056 if ('left' in obj) {
1057 this.offset.click.left = obj.left + this.margins.left;
1058 }
1059 if ('right' in obj) {
1060 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
1061 }
1062 if ('top' in obj) {
1063 this.offset.click.top = obj.top + this.margins.top;
1064 }
1065 if ('bottom' in obj) {
1066 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
1067 }
1068 },
1069
1070 _getParentOffset: function() {
1071
1072 //Get the offsetParent and cache its position
1073 this.offsetParent = this.helper.offsetParent();
1074 var po = this.offsetParent.offset();
1075
1076 // This is a special case where we need to modify a offset calculated on start, since the following happened:
1077 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
1078 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
1079 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
1080 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
1081 po.left += this.scrollParent.scrollLeft();
1082 po.top += this.scrollParent.scrollTop();
1083 }
1084
1085 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
1086 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
1087 po = { top: 0, left: 0 };
1088
1089 return {
1090 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
1091 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
1092 };
1093
1094 },
1095
1096 _getRelativeOffset: function() {
1097
1098 if(this.cssPosition == "relative") {
1099 var p = this.element.position();
1100 return {
1101 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
1102 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
1103 };
1104 } else {
1105 return { top: 0, left: 0 };
1106 }
1107
1108 },
1109
1110 _cacheMargins: function() {
1111 this.margins = {
1112 left: (parseInt(this.element.css("marginLeft"),10) || 0),
1113 top: (parseInt(this.element.css("marginTop"),10) || 0),
1114 right: (parseInt(this.element.css("marginRight"),10) || 0),
1115 bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
1116 };
1117 },
1118
1119 _cacheHelperProportions: function() {
1120 this.helperProportions = {
1121 width: this.helper.outerWidth(),
1122 height: this.helper.outerHeight()
1123 };
1124 },
1125
1126 _setContainment: function() {
1127
1128 var o = this.options;
1129 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
1130 if(o.containment == 'document' || o.containment == 'window') this.containment = [
1131 o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
1132 o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
1133 (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
1134 (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
1135 ];
1136
1137 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
1138 var c = $(o.containment);
1139 var ce = c[0]; if(!ce) return;
1140 var co = c.offset();
1141 var over = ($(ce).css("overflow") != 'hidden');
1142
1143 this.containment = [
1144 (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
1145 (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
1146 (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,
1147 (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
1148 ];
1149 this.relative_container = c;
1150
1151 } else if(o.containment.constructor == Array) {
1152 this.containment = o.containment;
1153 }
1154
1155 },
1156
1157 _convertPositionTo: function(d, pos) {
1158
1159 if(!pos) pos = this.position;
1160 var mod = d == "absolute" ? 1 : -1;
1161 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
1162
1163 return {
1164 top: (
1165 pos.top // The absolute mouse position
1166 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1167 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
1168 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
1169 ),
1170 left: (
1171 pos.left // The absolute mouse position
1172 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
1173 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
1174 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
1175 )
1176 };
1177
1178 },
1179
1180 _generatePosition: function(event) {
1181
1182 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
1183 var pageX = event.pageX;
1184 var pageY = event.pageY;
1185
1186 /*
1187 * - Position constraining -
1188 * Constrain the position to a mix of grid, containment.
1189 */
1190
1191 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
1192 var containment;
1193 if(this.containment) {
1194 if (this.relative_container){
1195 var co = this.relative_container.offset();
1196 containment = [ this.containment[0] + co.left,
1197 this.containment[1] + co.top,
1198 this.containment[2] + co.left,
1199 this.containment[3] + co.top ];
1200 }
1201 else {
1202 containment = this.containment;
1203 }
1204
1205 if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left;
1206 if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top;
1207 if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left;
1208 if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top;
1209 }
1210
1211 if(o.grid) {
1212 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
1213 var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
1214 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;
1215
1216 var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
1217 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;
1218 }
1219
1220 }
1221
1222 return {
1223 top: (
1224 pageY // The absolute mouse position
1225 - this.offset.click.top // Click offset (relative to the element)
1226 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
1227 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
1228 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
1229 ),
1230 left: (
1231 pageX // The absolute mouse position
1232 - this.offset.click.left // Click offset (relative to the element)
1233 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
1234 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
1235 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
1236 )
1237 };
1238
1239 },
1240
1241 _clear: function() {
1242 this.helper.removeClass("ui-draggable-dragging");
1243 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
1244 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
1245 this.helper = null;
1246 this.cancelHelperRemoval = false;
1247 },
1248
1249 // From now on bulk stuff - mainly helpers
1250
1251 _trigger: function(type, event, ui) {
1252 ui = ui || this._uiHash();
1253 $.ui.plugin.call(this, type, [event, ui]);
1254 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
1255 return $.Widget.prototype._trigger.call(this, type, event, ui);
1256 },
1257
1258 plugins: {},
1259
1260 _uiHash: function(event) {
1261 return {
1262 helper: this.helper,
1263 position: this.position,
1264 originalPosition: this.originalPosition,
1265 offset: this.positionAbs
1266 };
1267 }
1268
1269 });
1270
1271 $.extend($.ui.draggable, {
1272 version: "1.8.21"
1273 });
1274
1275 $.ui.plugin.add("draggable", "connectToSortable", {
1276 start: function(event, ui) {
1277
1278 var inst = $(this).data("draggable"), o = inst.options,
1279 uiSortable = $.extend({}, ui, { item: inst.element });
1280 inst.sortables = [];
1281 $(o.connectToSortable).each(function() {
1282 var sortable = $.data(this, 'sortable');
1283 if (sortable && !sortable.options.disabled) {
1284 inst.sortables.push({
1285 instance: sortable,
1286 shouldRevert: sortable.options.revert
1287 });
1288 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).
1289 sortable._trigger("activate", event, uiSortable);
1290 }
1291 });
1292
1293 },
1294 stop: function(event, ui) {
1295
1296 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
1297 var inst = $(this).data("draggable"),
1298 uiSortable = $.extend({}, ui, { item: inst.element });
1299
1300 $.each(inst.sortables, function() {
1301 if(this.instance.isOver) {
1302
1303 this.instance.isOver = 0;
1304
1305 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
1306 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
1307
1308 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
1309 if(this.shouldRevert) this.instance.options.revert = true;
1310
1311 //Trigger the stop of the sortable
1312 this.instance._mouseStop(event);
1313
1314 this.instance.options.helper = this.instance.options._helper;
1315
1316 //If the helper has been the original item, restore properties in the sortable
1317 if(inst.options.helper == 'original')
1318 this.instance.currentItem.css({ top: 'auto', left: 'auto' });
1319
1320 } else {
1321 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
1322 this.instance._trigger("deactivate", event, uiSortable);
1323 }
1324
1325 });
1326
1327 },
1328 drag: function(event, ui) {
1329
1330 var inst = $(this).data("draggable"), self = this;
1331
1332 var checkPos = function(o) {
1333 var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
1334 var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
1335 var itemHeight = o.height, itemWidth = o.width;
1336 var itemTop = o.top, itemLeft = o.left;
1337
1338 return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
1339 };
1340
1341 $.each(inst.sortables, function(i) {
1342
1343 //Copy over some variables to allow calling the sortable's native _intersectsWith
1344 this.instance.positionAbs = inst.positionAbs;
1345 this.instance.helperProportions = inst.helperProportions;
1346 this.instance.offset.click = inst.offset.click;
1347
1348 if(this.instance._intersectsWith(this.instance.containerCache)) {
1349
1350 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
1351 if(!this.instance.isOver) {
1352
1353 this.instance.isOver = 1;
1354 //Now we fake the start of dragging for the sortable instance,
1355 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
1356 //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)
1357 this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true);
1358 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
1359 this.instance.options.helper = function() { return ui.helper[0]; };
1360
1361 event.target = this.instance.currentItem[0];
1362 this.instance._mouseCapture(event, true);
1363 this.instance._mouseStart(event, true, true);
1364
1365 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
1366 this.instance.offset.click.top = inst.offset.click.top;
1367 this.instance.offset.click.left = inst.offset.click.left;
1368 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
1369 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
1370
1371 inst._trigger("toSortable", event);
1372 inst.dropped = this.instance.element; //draggable revert needs that
1373 //hack so receive/update callbacks work (mostly)
1374 inst.currentItem = inst.element;
1375 this.instance.fromOutside = inst;
1376
1377 }
1378
1379 //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
1380 if(this.instance.currentItem) this.instance._mouseDrag(event);
1381
1382 } else {
1383
1384 //If it doesn't intersect with the sortable, and it intersected before,
1385 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
1386 if(this.instance.isOver) {
1387
1388 this.instance.isOver = 0;
1389 this.instance.cancelHelperRemoval = true;
1390
1391 //Prevent reverting on this forced stop
1392 this.instance.options.revert = false;
1393
1394 // The out event needs to be triggered independently
1395 this.instance._trigger('out', event, this.instance._uiHash(this.instance));
1396
1397 this.instance._mouseStop(event, true);
1398 this.instance.options.helper = this.instance.options._helper;
1399
1400 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
1401 this.instance.currentItem.remove();
1402 if(this.instance.placeholder) this.instance.placeholder.remove();
1403
1404 inst._trigger("fromSortable", event);
1405 inst.dropped = false; //draggable revert needs that
1406 }
1407
1408 };
1409
1410 });
1411
1412 }
1413 });
1414
1415 $.ui.plugin.add("draggable", "cursor", {
1416 start: function(event, ui) {
1417 var t = $('body'), o = $(this).data('draggable').options;
1418 if (t.css("cursor")) o._cursor = t.css("cursor");
1419 t.css("cursor", o.cursor);
1420 },
1421 stop: function(event, ui) {
1422 var o = $(this).data('draggable').options;
1423 if (o._cursor) $('body').css("cursor", o._cursor);
1424 }
1425 });
1426
1427 $.ui.plugin.add("draggable", "opacity", {
1428 start: function(event, ui) {
1429 var t = $(ui.helper), o = $(this).data('draggable').options;
1430 if(t.css("opacity")) o._opacity = t.css("opacity");
1431 t.css('opacity', o.opacity);
1432 },
1433 stop: function(event, ui) {
1434 var o = $(this).data('draggable').options;
1435 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
1436 }
1437 });
1438
1439 $.ui.plugin.add("draggable", "scroll", {
1440 start: function(event, ui) {
1441 var i = $(this).data("draggable");
1442 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
1443 },
1444 drag: function(event, ui) {
1445
1446 var i = $(this).data("draggable"), o = i.options, scrolled = false;
1447
1448 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
1449
1450 if(!o.axis || o.axis != 'x') {
1451 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
1452 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
1453 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
1454 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
1455 }
1456
1457 if(!o.axis || o.axis != 'y') {
1458 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
1459 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
1460 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
1461 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
1462 }
1463
1464 } else {
1465
1466 if(!o.axis || o.axis != 'x') {
1467 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
1468 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1469 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
1470 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1471 }
1472
1473 if(!o.axis || o.axis != 'y') {
1474 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
1475 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1476 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
1477 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1478 }
1479
1480 }
1481
1482 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
1483 $.ui.ddmanager.prepareOffsets(i, event);
1484
1485 }
1486 });
1487
1488 $.ui.plugin.add("draggable", "snap", {
1489 start: function(event, ui) {
1490
1491 var i = $(this).data("draggable"), o = i.options;
1492 i.snapElements = [];
1493
1494 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
1495 var $t = $(this); var $o = $t.offset();
1496 if(this != i.element[0]) i.snapElements.push({
1497 item: this,
1498 width: $t.outerWidth(), height: $t.outerHeight(),
1499 top: $o.top, left: $o.left
1500 });
1501 });
1502
1503 },
1504 drag: function(event, ui) {
1505
1506 var inst = $(this).data("draggable"), o = inst.options;
1507 var d = o.snapTolerance;
1508
1509 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
1510 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
1511
1512 for (var i = inst.snapElements.length - 1; i >= 0; i--){
1513
1514 var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
1515 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
1516
1517 //Yes, I know, this is insane ;)
1518 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))) {
1519 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 })));
1520 inst.snapElements[i].snapping = false;
1521 continue;
1522 }
1523
1524 if(o.snapMode != 'inner') {
1525 var ts = Math.abs(t - y2) <= d;
1526 var bs = Math.abs(b - y1) <= d;
1527 var ls = Math.abs(l - x2) <= d;
1528 var rs = Math.abs(r - x1) <= d;
1529 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1530 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
1531 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
1532 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
1533 }
1534
1535 var first = (ts || bs || ls || rs);
1536
1537 if(o.snapMode != 'outer') {
1538 var ts = Math.abs(t - y1) <= d;
1539 var bs = Math.abs(b - y2) <= d;
1540 var ls = Math.abs(l - x1) <= d;
1541 var rs = Math.abs(r - x2) <= d;
1542 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
1543 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
1544 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
1545 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
1546 }
1547
1548 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
1549 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
1550 inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
1551
1552 };
1553
1554 }
1555 });
1556
1557 $.ui.plugin.add("draggable", "stack", {
1558 start: function(event, ui) {
1559
1560 var o = $(this).data("draggable").options;
1561
1562 var group = $.makeArray($(o.stack)).sort(function(a,b) {
1563 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
1564 });
1565 if (!group.length) { return; }
1566
1567 var min = parseInt(group[0].style.zIndex) || 0;
1568 $(group).each(function(i) {
1569 this.style.zIndex = min + i;
1570 });
1571
1572 this[0].style.zIndex = min + group.length;
1573
1574 }
1575 });
1576
1577 $.ui.plugin.add("draggable", "zIndex", {
1578 start: function(event, ui) {
1579 var t = $(ui.helper), o = $(this).data("draggable").options;
1580 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
1581 t.css('zIndex', o.zIndex);
1582 },
1583 stop: function(event, ui) {
1584 var o = $(this).data("draggable").options;
1585 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
1586 }
1587 });
1588
1589 })(jQuery);
1590 /*!
1591 * jQuery UI Sortable 1.8.21
1592 *
1593 * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
1594 * Dual licensed under the MIT or GPL Version 2 licenses.
1595 * http://jquery.org/license
1596 *
1597 * http://docs.jquery.com/UI/Sortables
1598 *
1599 * Depends:
1600 * jquery.ui.core.js
1601 * jquery.ui.mouse.js
1602 * jquery.ui.widget.js
1603 */
1604 (function( $, undefined ) {
1605
1606 $.widget("ui.sortable", $.ui.mouse, {
1607 widgetEventPrefix: "sort",
1608 ready: false,
1609 options: {
1610 appendTo: "parent",
1611 axis: false,
1612 connectWith: false,
1613 containment: false,
1614 cursor: 'auto',
1615 cursorAt: false,
1616 dropOnEmpty: true,
1617 forcePlaceholderSize: false,
1618 forceHelperSize: false,
1619 grid: false,
1620 handle: false,
1621 helper: "original",
1622 items: '> *',
1623 opacity: false,
1624 placeholder: false,
1625 revert: false,
1626 scroll: true,
1627 scrollSensitivity: 20,
1628 scrollSpeed: 20,
1629 scope: "default",
1630 tolerance: "intersect",
1631 zIndex: 1000
1632 },
1633 _create: function() {
1634
1635 var o = this.options;
1636 this.containerCache = {};
1637 this.element.addClass("ui-sortable");
1638
1639 //Get the items
1640 this.refresh();
1641
1642 //Let's determine if the items are being displayed horizontally
1643 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;
1644
1645 //Let's determine the parent's offset
1646 this.offset = this.element.offset();
1647
1648 //Initialize mouse events for interaction
1649 this._mouseInit();
1650
1651 //We're ready to go
1652 this.ready = true
1653
1654 },
1655
1656 destroy: function() {
1657 $.Widget.prototype.destroy.call( this );
1658 this.element
1659 .removeClass("ui-sortable ui-sortable-disabled");
1660 this._mouseDestroy();
1661
1662 for ( var i = this.items.length - 1; i >= 0; i-- )
1663 this.items[i].item.removeData(this.widgetName + "-item");
1664
1665 return this;
1666 },
1667
1668 _setOption: function(key, value){
1669 if ( key === "disabled" ) {
1670 this.options[ key ] = value;
1671
1672 this.widget()
1673 [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
1674 } else {
1675 // Don't call widget base _setOption for disable as it adds ui-state-disabled class
1676 $.Widget.prototype._setOption.apply(this, arguments);
1677 }
1678 },
1679
1680 _mouseCapture: function(event, overrideHandle) {
1681 var that = this;
1682
1683 if (this.reverting) {
1684 return false;
1685 }
1686
1687 if(this.options.disabled || this.options.type == 'static') return false;
1688
1689 //We have to refresh the items data once first
1690 this._refreshItems(event);
1691
1692 //Find out if the clicked node (or one of its parents) is a actual item in this.items
1693 var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
1694 if($.data(this, that.widgetName + '-item') == self) {
1695 currentItem = $(this);
1696 return false;
1697 }
1698 });
1699 if($.data(event.target, that.widgetName + '-item') == self) currentItem = $(event.target);
1700
1701 if(!currentItem) return false;
1702 if(this.options.handle && !overrideHandle) {
1703 var validHandle = false;
1704
1705 $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
1706 if(!validHandle) return false;
1707 }
1708
1709 this.currentItem = currentItem;
1710 this._removeCurrentsFromItems();
1711 return true;
1712
1713 },
1714
1715 _mouseStart: function(event, overrideHandle, noActivation) {
1716
1717 var o = this.options, self = this;
1718 this.currentContainer = this;
1719
1720 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
1721 this.refreshPositions();
1722
1723 //Create and append the visible helper
1724 this.helper = this._createHelper(event);
1725
1726 //Cache the helper size
1727 this._cacheHelperProportions();
1728
1729 /*
1730 * - Position generation -
1731 * This block generates everything position related - it's the core of draggables.
1732 */
1733
1734 //Cache the margins of the original element
1735 this._cacheMargins();
1736
1737 //Get the next scrolling parent
1738 this.scrollParent = this.helper.scrollParent();
1739
1740 //The element's absolute position on the page minus margins
1741 this.offset = this.currentItem.offset();
1742 this.offset = {
1743 top: this.offset.top - this.margins.top,
1744 left: this.offset.left - this.margins.left
1745 };
1746
1747 $.extend(this.offset, {
1748 click: { //Where the click happened, relative to the element
1749 left: event.pageX - this.offset.left,
1750 top: event.pageY - this.offset.top
1751 },
1752 parent: this._getParentOffset(),
1753 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
1754 });
1755
1756 // Only after we got the offset, we can change the helper's position to absolute
1757 // TODO: Still need to figure out a way to make relative sorting possible
1758 this.helper.css("position", "absolute");
1759 this.cssPosition = this.helper.css("position");
1760
1761 //Generate the original position
1762 this.originalPosition = this._generatePosition(event);
1763 this.originalPageX = event.pageX;
1764 this.originalPageY = event.pageY;
1765
1766 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
1767 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
1768
1769 //Cache the former DOM position
1770 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
1771
1772 //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
1773 if(this.helper[0] != this.currentItem[0]) {
1774 this.currentItem.hide();
1775 }
1776
1777 //Create the placeholder
1778 this._createPlaceholder();
1779
1780 //Set a containment if given in the options
1781 if(o.containment)
1782 this._setContainment();
1783
1784 if(o.cursor) { // cursor option
1785 if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
1786 $('body').css("cursor", o.cursor);
1787 }
1788
1789 if(o.opacity) { // opacity option
1790 if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
1791 this.helper.css("opacity", o.opacity);
1792 }
1793
1794 if(o.zIndex) { // zIndex option
1795 if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
1796 this.helper.css("zIndex", o.zIndex);
1797 }
1798
1799 //Prepare scrolling
1800 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
1801 this.overflowOffset = this.scrollParent.offset();
1802
1803 //Call callbacks
1804 this._trigger("start", event, this._uiHash());
1805
1806 //Recache the helper size
1807 if(!this._preserveHelperProportions)
1808 this._cacheHelperProportions();
1809
1810
1811 //Post 'activate' events to possible containers
1812 if(!noActivation) {
1813 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
1814 }
1815
1816 //Prepare possible droppables
1817 if($.ui.ddmanager)
1818 $.ui.ddmanager.current = this;
1819
1820 if ($.ui.ddmanager && !o.dropBehaviour)
1821 $.ui.ddmanager.prepareOffsets(this, event);
1822
1823 this.dragging = true;
1824
1825 this.helper.addClass("ui-sortable-helper");
1826 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
1827 return true;
1828
1829 },
1830
1831 _mouseDrag: function(event) {
1832
1833 //Compute the helpers position
1834 this.position = this._generatePosition(event);
1835 this.positionAbs = this._convertPositionTo("absolute");
1836
1837 if (!this.lastPositionAbs) {
1838 this.lastPositionAbs = this.positionAbs;
1839 }
1840
1841 //Do scrolling
1842 if(this.options.scroll) {
1843 var o = this.options, scrolled = false;
1844 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
1845
1846 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
1847 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
1848 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
1849 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
1850
1851 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
1852 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
1853 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
1854 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
1855
1856 } else {
1857
1858 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
1859 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
1860 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
1861 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
1862
1863 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
1864 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
1865 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
1866 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
1867
1868 }
1869
1870 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
1871 $.ui.ddmanager.prepareOffsets(this, event);
1872 }
1873
1874 //Regenerate the absolute position used for position checks
1875 this.positionAbs = this._convertPositionTo("absolute");
1876
1877 //Set the helper position
1878 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
1879 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
1880
1881 //Rearrange
1882 for (var i = this.items.length - 1; i >= 0; i--) {
1883
1884 //Cache variables and intersection, continue if no intersection
1885 var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
1886 if (!intersection) continue;
1887
1888 if(itemElement != this.currentItem[0] //cannot intersect with itself
1889 && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
1890 && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
1891 && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
1892 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
1893 ) {
1894
1895 this.direction = intersection == 1 ? "down" : "up";
1896
1897 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
1898 this._rearrange(event, item);
1899 } else {
1900 break;
1901 }
1902
1903 this._trigger("change", event, this._uiHash());
1904 break;
1905 }
1906 }
1907
1908 //Post events to containers
1909 this._contactContainers(event);
1910
1911 //Interconnect with droppables
1912 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
1913
1914 //Call callbacks
1915 this._trigger('sort', event, this._uiHash());
1916
1917 this.lastPositionAbs = this.positionAbs;
1918 return false;
1919
1920 },
1921
1922 _mouseStop: function(event, noPropagation) {
1923
1924 if(!event) return;
1925
1926 //If we are using droppables, inform the manager about the drop
1927 if ($.ui.ddmanager && !this.options.dropBehaviour)
1928 $.ui.ddmanager.drop(this, event);
1929
1930 if(this.options.revert) {
1931 var self = this;
1932 var cur = self.placeholder.offset();
1933
1934 self.reverting = true;
1935
1936 $(this.helper).animate({
1937 left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
1938 top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
1939 }, parseInt(this.options.revert, 10) || 500, function() {
1940 self._clear(event);
1941 });
1942 } else {
1943 this._clear(event, noPropagation);
1944 }
1945
1946 return false;
1947
1948 },
1949
1950 cancel: function() {
1951
1952 var self = this;
1953
1954 if(this.dragging) {
1955
1956 this._mouseUp({ target: null });
1957
1958 if(this.options.helper == "original")
1959 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
1960 else
1961 this.currentItem.show();
1962
1963 //Post deactivating events to containers
1964 for (var i = this.containers.length - 1; i >= 0; i--){
1965 this.containers[i]._trigger("deactivate", null, self._uiHash(this));
1966 if(this.containers[i].containerCache.over) {
1967 this.containers[i]._trigger("out", null, self._uiHash(this));
1968 this.containers[i].containerCache.over = 0;
1969 }
1970 }
1971
1972 }
1973
1974 if (this.placeholder) {
1975 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
1976 if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
1977 if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
1978
1979 $.extend(this, {
1980 helper: null,
1981 dragging: false,
1982 reverting: false,
1983 _noFinalSort: null
1984 });
1985
1986 if(this.domPosition.prev) {
1987 $(this.domPosition.prev).after(this.currentItem);
1988 } else {
1989 $(this.domPosition.parent).prepend(this.currentItem);
1990 }
1991 }
1992
1993 return this;
1994
1995 },
1996
1997 serialize: function(o) {
1998
1999 var items = this._getItemsAsjQuery(o && o.connected);
2000 var str = []; o = o || {};
2001
2002 $(items).each(function() {
2003 var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
2004 if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
2005 });
2006
2007 if(!str.length && o.key) {
2008 str.push(o.key + '=');
2009 }
2010
2011 return str.join('&');
2012
2013 },
2014
2015 toArray: function(o) {
2016
2017 var items = this._getItemsAsjQuery(o && o.connected);
2018 var ret = []; o = o || {};
2019
2020 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
2021 return ret;
2022
2023 },
2024
2025 /* Be careful with the following core functions */
2026 _intersectsWith: function(item) {
2027
2028 var x1 = this.positionAbs.left,
2029 x2 = x1 + this.helperProportions.width,
2030 y1 = this.positionAbs.top,
2031 y2 = y1 + this.helperProportions.height;
2032
2033 var l = item.left,
2034 r = l + item.width,
2035 t = item.top,
2036 b = t + item.height;
2037
2038 var dyClick = this.offset.click.top,
2039 dxClick = this.offset.click.left;
2040
2041 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
2042
2043 if( this.options.tolerance == "pointer"
2044 || this.options.forcePointerForContainers
2045 || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
2046 ) {
2047 return isOverElement;
2048 } else {
2049
2050 return (l < x1 + (this.helperProportions.width / 2) // Right Half
2051 && x2 - (this.helperProportions.width / 2) < r // Left Half
2052 && t < y1 + (this.helperProportions.height / 2) // Bottom Half
2053 && y2 - (this.helperProportions.height / 2) < b ); // Top Half
2054
2055 }
2056 },
2057
2058 _intersectsWithPointer: function(item) {
2059
2060 var isOverElementHeight = (this.options.axis === 'x') || $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
2061 isOverElementWidth = (this.options.axis === 'y') || $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
2062 isOverElement = isOverElementHeight && isOverElementWidth,
2063 verticalDirection = this._getDragVerticalDirection(),
2064 horizontalDirection = this._getDragHorizontalDirection();
2065
2066 if (!isOverElement)
2067 return false;
2068
2069 return this.floating ?
2070 ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
2071 : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
2072
2073 },
2074
2075 _intersectsWithSides: function(item) {
2076
2077 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
2078 isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
2079 verticalDirection = this._getDragVerticalDirection(),
2080 horizontalDirection = this._getDragHorizontalDirection();
2081
2082 if (this.floating && horizontalDirection) {
2083 return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
2084 } else {
2085 return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
2086 }
2087
2088 },
2089
2090 _getDragVerticalDirection: function() {
2091 var delta = this.positionAbs.top - this.lastPositionAbs.top;
2092 return delta != 0 && (delta > 0 ? "down" : "up");
2093 },
2094
2095 _getDragHorizontalDirection: function() {
2096 var delta = this.positionAbs.left - this.lastPositionAbs.left;
2097 return delta != 0 && (delta > 0 ? "right" : "left");
2098 },
2099
2100 refresh: function(event) {
2101 this._refreshItems(event);
2102 this.refreshPositions();
2103 return this;
2104 },
2105
2106 _connectWith: function() {
2107 var options = this.options;
2108 return options.connectWith.constructor == String
2109 ? [options.connectWith]
2110 : options.connectWith;
2111 },
2112
2113 _getItemsAsjQuery: function(connected) {
2114
2115 var self = this;
2116 var items = [];
2117 var queries = [];
2118 var connectWith = this._connectWith();
2119
2120 if(connectWith && connected) {
2121 for (var i = connectWith.length - 1; i >= 0; i--){
2122 var cur = $(connectWith[i]);
2123 for (var j = cur.length - 1; j >= 0; j--){
2124 var inst = $.data(cur[j], this.widgetName);
2125 if(inst && inst != this && !inst.options.disabled) {
2126 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]);
2127 }
2128 };
2129 };
2130 }
2131
2132 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]);
2133
2134 for (var i = queries.length - 1; i >= 0; i--){
2135 queries[i][0].each(function() {
2136 items.push(this);
2137 });
2138 };
2139
2140 return $(items);
2141
2142 },
2143
2144 _removeCurrentsFromItems: function() {
2145
2146 var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
2147
2148 for (var i=0; i < this.items.length; i++) {
2149
2150 for (var j=0; j < list.length; j++) {
2151 if(list[j] == this.items[i].item[0])
2152 this.items.splice(i,1);
2153 };
2154
2155 };
2156
2157 },
2158
2159 _refreshItems: function(event) {
2160
2161 this.items = [];
2162 this.containers = [this];
2163 var items = this.items;
2164 var self = this;
2165 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
2166 var connectWith = this._connectWith();
2167
2168 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
2169 for (var i = connectWith.length - 1; i >= 0; i--){
2170 var cur = $(connectWith[i]);
2171 for (var j = cur.length - 1; j >= 0; j--){
2172 var inst = $.data(cur[j], this.widgetName);
2173 if(inst && inst != this && !inst.options.disabled) {
2174 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
2175 this.containers.push(inst);
2176 }
2177 };
2178 };
2179 }
2180
2181 for (var i = queries.length - 1; i >= 0; i--) {
2182 var targetData = queries[i][1];
2183 var _queries = queries[i][0];
2184
2185 for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
2186 var item = $(_queries[j]);
2187
2188 item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager)
2189
2190 items.push({
2191 item: item,
2192 instance: targetData,
2193 width: 0, height: 0,
2194 left: 0, top: 0
2195 });
2196 };
2197 };
2198
2199 },
2200
2201 refreshPositions: function(fast) {
2202
2203 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
2204 if(this.offsetParent && this.helper) {
2205 this.offset.parent = this._getParentOffset();
2206 }
2207
2208 for (var i = this.items.length - 1; i >= 0; i--){
2209 var item = this.items[i];
2210
2211 //We ignore calculating positions of all connected containers when we're not over them
2212 if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
2213 continue;
2214
2215 var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
2216
2217 if (!fast) {
2218 item.width = t.outerWidth();
2219 item.height = t.outerHeight();
2220 }
2221
2222 var p = t.offset();
2223 item.left = p.left;
2224 item.top = p.top;
2225 };
2226
2227 if(this.options.custom && this.options.custom.refreshContainers) {
2228 this.options.custom.refreshContainers.call(this);
2229 } else {
2230 for (var i = this.containers.length - 1; i >= 0; i--){
2231 var p = this.containers[i].element.offset();
2232 this.containers[i].containerCache.left = p.left;
2233 this.containers[i].containerCache.top = p.top;
2234 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
2235 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
2236 };
2237 }
2238
2239 return this;
2240 },
2241
2242 _createPlaceholder: function(that) {
2243
2244 var self = that || this, o = self.options;
2245
2246 if(!o.placeholder || o.placeholder.constructor == String) {
2247 var className = o.placeholder;
2248 o.placeholder = {
2249 element: function() {
2250
2251 var el = $(document.createElement(self.currentItem[0].nodeName))
2252 .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
2253 .removeClass("ui-sortable-helper")[0];
2254
2255 if(!className)
2256 el.style.visibility = "hidden";
2257
2258 return el;
2259 },
2260 update: function(container, p) {
2261
2262 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
2263 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
2264 if(className && !o.forcePlaceholderSize) return;
2265
2266 //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
2267 if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
2268 if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
2269 }
2270 };
2271 }
2272
2273 //Create the placeholder
2274 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
2275
2276 //Append it after the actual current item
2277 self.currentItem.after(self.placeholder);
2278
2279 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
2280 o.placeholder.update(self, self.placeholder);
2281
2282 },
2283
2284 _contactContainers: function(event) {
2285
2286 // get innermost container that intersects with item
2287 var innermostContainer = null, innermostIndex = null;
2288
2289
2290 for (var i = this.containers.length - 1; i >= 0; i--){
2291
2292 // never consider a container that's located within the item itself
2293 if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
2294 continue;
2295
2296 if(this._intersectsWith(this.containers[i].containerCache)) {
2297
2298 // if we've already found a container and it's more "inner" than this, then continue
2299 if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
2300 continue;
2301
2302 innermostContainer = this.containers[i];
2303 innermostIndex = i;
2304
2305 } else {
2306 // container doesn't intersect. trigger "out" event if necessary
2307 if(this.containers[i].containerCache.over) {
2308 this.containers[i]._trigger("out", event, this._uiHash(this));
2309 this.containers[i].containerCache.over = 0;
2310 }
2311 }
2312
2313 }
2314
2315 // if no intersecting containers found, return
2316 if(!innermostContainer) return;
2317
2318 // move the item into the container if it's not there already
2319 if(this.containers.length === 1) {
2320 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
2321 this.containers[innermostIndex].containerCache.over = 1;
2322 } else if(this.currentContainer != this.containers[innermostIndex]) {
2323
2324 //When entering a new container, we will find the item with the least distance and append our item near it
2325 var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
2326 for (var j = this.items.length - 1; j >= 0; j--) {
2327 if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
2328 var cur = this.containers[innermostIndex].floating ? this.items[j].item.offset().left : this.items[j].item.offset().top;
2329 if(Math.abs(cur - base) < dist) {
2330 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
2331 this.direction = (cur - base > 0) ? 'down' : 'up';
2332 }
2333 }
2334
2335 if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
2336 return;
2337
2338 this.currentContainer = this.containers[innermostIndex];
2339 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
2340 this._trigger("change", event, this._uiHash());
2341 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
2342
2343 //Update the placeholder
2344 this.options.placeholder.update(this.currentContainer, this.placeholder);
2345
2346 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
2347 this.containers[innermostIndex].containerCache.over = 1;
2348 }
2349
2350
2351 },
2352
2353 _createHelper: function(event) {
2354
2355 var o = this.options;
2356 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
2357
2358 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
2359 $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
2360
2361 if(helper[0] == this.currentItem[0])
2362 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") };
2363
2364 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
2365 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
2366
2367 return helper;
2368
2369 },
2370
2371 _adjustOffsetFromHelper: function(obj) {
2372 if (typeof obj == 'string') {
2373 obj = obj.split(' ');
2374 }
2375 if ($.isArray(obj)) {
2376 obj = {left: +obj[0], top: +obj[1] || 0};
2377 }
2378 if ('left' in obj) {
2379 this.offset.click.left = obj.left + this.margins.left;
2380 }
2381 if ('right' in obj) {
2382 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
2383 }
2384 if ('top' in obj) {
2385 this.offset.click.top = obj.top + this.margins.top;
2386 }
2387 if ('bottom' in obj) {
2388 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
2389 }
2390 },
2391
2392 _getParentOffset: function() {
2393
2394
2395 //Get the offsetParent and cache its position
2396 this.offsetParent = this.helper.offsetParent();
2397 var po = this.offsetParent.offset();
2398
2399 // This is a special case where we need to modify a offset calculated on start, since the following happened:
2400 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
2401 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
2402 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
2403 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
2404 po.left += this.scrollParent.scrollLeft();
2405 po.top += this.scrollParent.scrollTop();
2406 }
2407
2408 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
2409 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
2410 po = { top: 0, left: 0 };
2411
2412 return {
2413 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
2414 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
2415 };
2416
2417 },
2418
2419 _getRelativeOffset: function() {
2420
2421 if(this.cssPosition == "relative") {
2422 var p = this.currentItem.position();
2423 return {
2424 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
2425 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
2426 };
2427 } else {
2428 return { top: 0, left: 0 };
2429 }
2430
2431 },
2432
2433 _cacheMargins: function() {
2434 this.margins = {
2435 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
2436 top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
2437 };
2438 },
2439
2440 _cacheHelperProportions: function() {
2441 this.helperProportions = {
2442 width: this.helper.outerWidth(),
2443 height: this.helper.outerHeight()
2444 };
2445 },
2446
2447 _setContainment: function() {
2448
2449 var o = this.options;
2450 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
2451 if(o.containment == 'document' || o.containment == 'window') this.containment = [
2452 0 - this.offset.relative.left - this.offset.parent.left,
2453 0 - this.offset.relative.top - this.offset.parent.top,
2454 $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
2455 ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
2456 ];
2457
2458 if(!(/^(document|window|parent)$/).test(o.containment)) {
2459 var ce = $(o.containment)[0];
2460 var co = $(o.containment).offset();
2461 var over = ($(ce).css("overflow") != 'hidden');
2462
2463 this.containment = [
2464 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
2465 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
2466 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,
2467 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
2468 ];
2469 }
2470
2471 },
2472
2473 _convertPositionTo: function(d, pos) {
2474
2475 if(!pos) pos = this.position;
2476 var mod = d == "absolute" ? 1 : -1;
2477 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
2478
2479 return {
2480 top: (
2481 pos.top // The absolute mouse position
2482 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
2483 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
2484 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
2485 ),
2486 left: (
2487 pos.left // The absolute mouse position
2488 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
2489 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
2490 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
2491 )
2492 };
2493
2494 },
2495
2496 _generatePosition: function(event) {
2497
2498 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
2499
2500 // This is another very weird special case that only happens for relative elements:
2501 // 1. If the css position is relative
2502 // 2. and the scroll parent is the document or similar to the offset parent
2503 // we have to refresh the relative offset during the scroll so there are no jumps
2504 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
2505 this.offset.relative = this._getRelativeOffset();
2506 }
2507
2508 var pageX = event.pageX;
2509 var pageY = event.pageY;
2510
2511 /*
2512 * - Position constraining -
2513 * Constrain the position to a mix of grid, containment.
2514 */
2515
2516 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
2517
2518 if(this.containment) {
2519 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
2520 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
2521 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
2522 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
2523 }
2524
2525 if(o.grid) {
2526 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
2527 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;
2528
2529 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
2530 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;
2531 }
2532
2533 }
2534
2535 return {
2536 top: (
2537 pageY // The absolute mouse position
2538 - this.offset.click.top // Click offset (relative to the element)
2539 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
2540 - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
2541 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
2542 ),
2543 left: (
2544 pageX // The absolute mouse position
2545 - this.offset.click.left // Click offset (relative to the element)
2546 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
2547 - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
2548 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
2549 )
2550 };
2551
2552 },
2553
2554 _rearrange: function(event, i, a, hardRefresh) {
2555
2556 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));
2557
2558 //Various things done here to improve the performance:
2559 // 1. we create a setTimeout, that calls refreshPositions
2560 // 2. on the instance, we have a counter variable, that get's higher after every append
2561 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
2562 // 4. this lets only the last addition to the timeout stack through
2563 this.counter = this.counter ? ++this.counter : 1;
2564 var self = this, counter = this.counter;
2565
2566 window.setTimeout(function() {
2567 if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
2568 },0);
2569
2570 },
2571
2572 _clear: function(event, noPropagation) {
2573
2574 this.reverting = false;
2575 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
2576 // everything else normalized again
2577 var delayedTriggers = [], self = this;
2578
2579 // We first have to update the dom position of the actual currentItem
2580 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
2581 if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem);
2582 this._noFinalSort = null;
2583
2584 if(this.helper[0] == this.currentItem[0]) {
2585 for(var i in this._storedCSS) {
2586 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
2587 }
2588 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
2589 } else {
2590 this.currentItem.show();
2591 }
2592
2593 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
2594 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
2595 if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
2596 if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
2597 for (var i = this.containers.length - 1; i >= 0; i--){
2598 if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
2599 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
2600 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
2601 }
2602 };
2603 };
2604
2605 //Post events to containers
2606 for (var i = this.containers.length - 1; i >= 0; i--){
2607 if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
2608 if(this.containers[i].containerCache.over) {
2609 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
2610 this.containers[i].containerCache.over = 0;
2611 }
2612 }
2613
2614 //Do what was originally in plugins
2615 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
2616 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
2617 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
2618
2619 this.dragging = false;
2620 if(this.cancelHelperRemoval) {
2621 if(!noPropagation) {
2622 this._trigger("beforeStop", event, this._uiHash());
2623 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
2624 this._trigger("stop", event, this._uiHash());
2625 }
2626 return false;
2627 }
2628
2629 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
2630
2631 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
2632 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
2633
2634 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
2635
2636 if(!noPropagation) {
2637 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
2638 this._trigger("stop", event, this._uiHash());
2639 }
2640
2641 this.fromOutside = false;
2642 return true;
2643
2644 },
2645
2646 _trigger: function() {
2647 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
2648 this.cancel();
2649 }
2650 },
2651
2652 _uiHash: function(inst) {
2653 var self = inst || this;
2654 return {
2655 helper: self.helper,
2656 placeholder: self.placeholder || $([]),
2657 position: self.position,
2658 originalPosition: self.originalPosition,
2659 offset: self.positionAbs,
2660 item: self.currentItem,
2661 sender: inst ? inst.element : null
2662 };
2663 }
2664
2665 });
2666
2667 $.extend($.ui.sortable, {
2668 version: "1.8.21"
2669 });
2670
2671 })(jQuery);