218 $.extend( this.offset, { |
223 $.extend( this.offset, { |
219 click: { //Where the click happened, relative to the element |
224 click: { //Where the click happened, relative to the element |
220 left: event.pageX - this.offset.left, |
225 left: event.pageX - this.offset.left, |
221 top: event.pageY - this.offset.top |
226 top: event.pageY - this.offset.top |
222 }, |
227 }, |
223 parent: this._getParentOffset(), |
|
224 |
228 |
225 // This is a relative to absolute position minus the actual position calculation - |
229 // This is a relative to absolute position minus the actual position calculation - |
226 // only used for relative positioned helper |
230 // only used for relative positioned helper |
227 relative: this._getRelativeOffset() |
231 relative: this._getRelativeOffset() |
228 } ); |
232 } ); |
229 |
233 |
230 // Only after we got the offset, we can change the helper's position to absolute |
234 // After we get the helper offset, but before we get the parent offset we can |
|
235 // change the helper's position to absolute |
231 // TODO: Still need to figure out a way to make relative sorting possible |
236 // TODO: Still need to figure out a way to make relative sorting possible |
232 this.helper.css( "position", "absolute" ); |
237 this.helper.css( "position", "absolute" ); |
233 this.cssPosition = this.helper.css( "position" ); |
238 this.cssPosition = this.helper.css( "position" ); |
234 |
239 |
235 //Generate the original position |
|
236 this.originalPosition = this._generatePosition( event ); |
|
237 this.originalPageX = event.pageX; |
|
238 this.originalPageY = event.pageY; |
|
239 |
|
240 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied |
240 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied |
241 ( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) ); |
241 if ( o.cursorAt ) { |
|
242 this._adjustOffsetFromHelper( o.cursorAt ); |
|
243 } |
242 |
244 |
243 //Cache the former DOM position |
245 //Cache the former DOM position |
244 this.domPosition = { |
246 this.domPosition = { |
245 prev: this.currentItem.prev()[ 0 ], |
247 prev: this.currentItem.prev()[ 0 ], |
246 parent: this.currentItem.parent()[ 0 ] |
248 parent: this.currentItem.parent()[ 0 ] |
269 |
278 |
270 this.storedStylesheet = |
279 this.storedStylesheet = |
271 $( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body ); |
280 $( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body ); |
272 } |
281 } |
273 |
282 |
|
283 // We need to make sure to grab the zIndex before setting the |
|
284 // opacity, because setting the opacity to anything lower than 1 |
|
285 // causes the zIndex to change from "auto" to 0. |
|
286 if ( o.zIndex ) { // zIndex option |
|
287 if ( this.helper.css( "zIndex" ) ) { |
|
288 this._storedZIndex = this.helper.css( "zIndex" ); |
|
289 } |
|
290 this.helper.css( "zIndex", o.zIndex ); |
|
291 } |
|
292 |
274 if ( o.opacity ) { // opacity option |
293 if ( o.opacity ) { // opacity option |
275 if ( this.helper.css( "opacity" ) ) { |
294 if ( this.helper.css( "opacity" ) ) { |
276 this._storedOpacity = this.helper.css( "opacity" ); |
295 this._storedOpacity = this.helper.css( "opacity" ); |
277 } |
296 } |
278 this.helper.css( "opacity", o.opacity ); |
297 this.helper.css( "opacity", o.opacity ); |
279 } |
298 } |
280 |
299 |
281 if ( o.zIndex ) { // zIndex option |
|
282 if ( this.helper.css( "zIndex" ) ) { |
|
283 this._storedZIndex = this.helper.css( "zIndex" ); |
|
284 } |
|
285 this.helper.css( "zIndex", o.zIndex ); |
|
286 } |
|
287 |
|
288 //Prepare scrolling |
300 //Prepare scrolling |
289 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && |
301 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && |
290 this.scrollParent[ 0 ].tagName !== "HTML" ) { |
302 this.scrollParent[ 0 ].tagName !== "HTML" ) { |
291 this.overflowOffset = this.scrollParent.offset(); |
303 this.overflowOffset = this.scrollParent.offset(); |
292 } |
304 } |
293 |
305 |
294 //Call callbacks |
306 //Call callbacks |
295 this._trigger( "start", event, this._uiHash() ); |
307 this._trigger( "start", event, this._uiHash() ); |
317 |
329 |
318 this.dragging = true; |
330 this.dragging = true; |
319 |
331 |
320 this._addClass( this.helper, "ui-sortable-helper" ); |
332 this._addClass( this.helper, "ui-sortable-helper" ); |
321 |
333 |
322 // Execute the drag once - this causes the helper not to be visiblebefore getting its |
334 //Move the helper, if needed |
323 // correct position |
335 if ( !this.helper.parent().is( this.appendTo ) ) { |
|
336 this.helper.detach().appendTo( this.appendTo ); |
|
337 |
|
338 //Update position |
|
339 this.offset.parent = this._getParentOffset(); |
|
340 } |
|
341 |
|
342 //Generate the original position |
|
343 this.position = this.originalPosition = this._generatePosition( event ); |
|
344 this.originalPageX = event.pageX; |
|
345 this.originalPageY = event.pageY; |
|
346 this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" ); |
|
347 |
324 this._mouseDrag( event ); |
348 this._mouseDrag( event ); |
|
349 |
325 return true; |
350 return true; |
326 |
351 |
|
352 }, |
|
353 |
|
354 _scroll: function( event ) { |
|
355 var o = this.options, |
|
356 scrolled = false; |
|
357 |
|
358 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && |
|
359 this.scrollParent[ 0 ].tagName !== "HTML" ) { |
|
360 |
|
361 if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) - |
|
362 event.pageY < o.scrollSensitivity ) { |
|
363 this.scrollParent[ 0 ].scrollTop = |
|
364 scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed; |
|
365 } else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) { |
|
366 this.scrollParent[ 0 ].scrollTop = |
|
367 scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed; |
|
368 } |
|
369 |
|
370 if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) - |
|
371 event.pageX < o.scrollSensitivity ) { |
|
372 this.scrollParent[ 0 ].scrollLeft = scrolled = |
|
373 this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed; |
|
374 } else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) { |
|
375 this.scrollParent[ 0 ].scrollLeft = scrolled = |
|
376 this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed; |
|
377 } |
|
378 |
|
379 } else { |
|
380 |
|
381 if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) { |
|
382 scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed ); |
|
383 } else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) < |
|
384 o.scrollSensitivity ) { |
|
385 scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed ); |
|
386 } |
|
387 |
|
388 if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) { |
|
389 scrolled = this.document.scrollLeft( |
|
390 this.document.scrollLeft() - o.scrollSpeed |
|
391 ); |
|
392 } else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) < |
|
393 o.scrollSensitivity ) { |
|
394 scrolled = this.document.scrollLeft( |
|
395 this.document.scrollLeft() + o.scrollSpeed |
|
396 ); |
|
397 } |
|
398 |
|
399 } |
|
400 |
|
401 return scrolled; |
327 }, |
402 }, |
328 |
403 |
329 _mouseDrag: function( event ) { |
404 _mouseDrag: function( event ) { |
330 var i, item, itemElement, intersection, |
405 var i, item, itemElement, intersection, |
331 o = this.options, |
406 o = this.options; |
332 scrolled = false; |
|
333 |
407 |
334 //Compute the helpers position |
408 //Compute the helpers position |
335 this.position = this._generatePosition( event ); |
409 this.position = this._generatePosition( event ); |
336 this.positionAbs = this._convertPositionTo( "absolute" ); |
410 this.positionAbs = this._convertPositionTo( "absolute" ); |
337 |
411 |
338 if ( !this.lastPositionAbs ) { |
|
339 this.lastPositionAbs = this.positionAbs; |
|
340 } |
|
341 |
|
342 //Do scrolling |
|
343 if ( this.options.scroll ) { |
|
344 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && |
|
345 this.scrollParent[ 0 ].tagName !== "HTML" ) { |
|
346 |
|
347 if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) - |
|
348 event.pageY < o.scrollSensitivity ) { |
|
349 this.scrollParent[ 0 ].scrollTop = |
|
350 scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed; |
|
351 } else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) { |
|
352 this.scrollParent[ 0 ].scrollTop = |
|
353 scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed; |
|
354 } |
|
355 |
|
356 if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) - |
|
357 event.pageX < o.scrollSensitivity ) { |
|
358 this.scrollParent[ 0 ].scrollLeft = scrolled = |
|
359 this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed; |
|
360 } else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) { |
|
361 this.scrollParent[ 0 ].scrollLeft = scrolled = |
|
362 this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed; |
|
363 } |
|
364 |
|
365 } else { |
|
366 |
|
367 if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) { |
|
368 scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed ); |
|
369 } else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) < |
|
370 o.scrollSensitivity ) { |
|
371 scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed ); |
|
372 } |
|
373 |
|
374 if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) { |
|
375 scrolled = this.document.scrollLeft( |
|
376 this.document.scrollLeft() - o.scrollSpeed |
|
377 ); |
|
378 } else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) < |
|
379 o.scrollSensitivity ) { |
|
380 scrolled = this.document.scrollLeft( |
|
381 this.document.scrollLeft() + o.scrollSpeed |
|
382 ); |
|
383 } |
|
384 |
|
385 } |
|
386 |
|
387 if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) { |
|
388 $.ui.ddmanager.prepareOffsets( this, event ); |
|
389 } |
|
390 } |
|
391 |
|
392 //Regenerate the absolute position used for position checks |
|
393 this.positionAbs = this._convertPositionTo( "absolute" ); |
|
394 |
|
395 //Set the helper position |
412 //Set the helper position |
396 if ( !this.options.axis || this.options.axis !== "y" ) { |
413 if ( !this.options.axis || this.options.axis !== "y" ) { |
397 this.helper[ 0 ].style.left = this.position.left + "px"; |
414 this.helper[ 0 ].style.left = this.position.left + "px"; |
398 } |
415 } |
399 if ( !this.options.axis || this.options.axis !== "x" ) { |
416 if ( !this.options.axis || this.options.axis !== "x" ) { |
400 this.helper[ 0 ].style.top = this.position.top + "px"; |
417 this.helper[ 0 ].style.top = this.position.top + "px"; |
401 } |
418 } |
|
419 |
|
420 //Do scrolling |
|
421 if ( o.scroll ) { |
|
422 if ( this._scroll( event ) !== false ) { |
|
423 |
|
424 //Update item positions used in position checks |
|
425 this._refreshItemPositions( true ); |
|
426 |
|
427 if ( $.ui.ddmanager && !o.dropBehaviour ) { |
|
428 $.ui.ddmanager.prepareOffsets( this, event ); |
|
429 } |
|
430 } |
|
431 } |
|
432 |
|
433 this.dragDirection = { |
|
434 vertical: this._getDragVerticalDirection(), |
|
435 horizontal: this._getDragHorizontalDirection() |
|
436 }; |
402 |
437 |
403 //Rearrange |
438 //Rearrange |
404 for ( i = this.items.length - 1; i >= 0; i-- ) { |
439 for ( i = this.items.length - 1; i >= 0; i-- ) { |
405 |
440 |
406 //Cache variables and intersection, continue if no intersection |
441 //Cache variables and intersection, continue if no intersection |
424 |
459 |
425 // Cannot intersect with itself |
460 // Cannot intersect with itself |
426 // no useless actions that have been done before |
461 // no useless actions that have been done before |
427 // no action if the item moved is the parent of the item checked |
462 // no action if the item moved is the parent of the item checked |
428 if ( itemElement !== this.currentItem[ 0 ] && |
463 if ( itemElement !== this.currentItem[ 0 ] && |
429 this.placeholder[ intersection === 1 ? "next" : "prev" ]()[ 0 ] !== itemElement && |
464 this.placeholder[ intersection === 1 ? |
|
465 "next" : "prev" ]()[ 0 ] !== itemElement && |
430 !$.contains( this.placeholder[ 0 ], itemElement ) && |
466 !$.contains( this.placeholder[ 0 ], itemElement ) && |
431 ( this.options.type === "semi-dynamic" ? |
467 ( this.options.type === "semi-dynamic" ? |
432 !$.contains( this.element[ 0 ], itemElement ) : |
468 !$.contains( this.element[ 0 ], itemElement ) : |
433 true |
469 true |
434 ) |
470 ) |
435 ) { |
471 ) { |
436 |
472 |
437 this.direction = intersection === 1 ? "down" : "up"; |
473 this.direction = intersection === 1 ? "down" : "up"; |
438 |
474 |
439 if ( this.options.tolerance === "pointer" || this._intersectsWithSides( item ) ) { |
475 if ( this.options.tolerance === "pointer" || |
|
476 this._intersectsWithSides( item ) ) { |
440 this._rearrange( event, item ); |
477 this._rearrange( event, item ); |
441 } else { |
478 } else { |
442 break; |
479 break; |
443 } |
480 } |
444 |
481 |
650 |
687 |
651 if ( !isOverElement ) { |
688 if ( !isOverElement ) { |
652 return false; |
689 return false; |
653 } |
690 } |
654 |
691 |
655 verticalDirection = this._getDragVerticalDirection(); |
692 verticalDirection = this.dragDirection.vertical; |
656 horizontalDirection = this._getDragHorizontalDirection(); |
693 horizontalDirection = this.dragDirection.horizontal; |
657 |
694 |
658 return this.floating ? |
695 return this.floating ? |
659 ( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) |
696 ( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) : |
660 : ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) ); |
697 ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) ); |
661 |
698 |
662 }, |
699 }, |
663 |
700 |
664 _intersectsWithSides: function( item ) { |
701 _intersectsWithSides: function( item ) { |
665 |
702 |
666 var isOverBottomHalf = this._isOverAxis( this.positionAbs.top + |
703 var isOverBottomHalf = this._isOverAxis( this.positionAbs.top + |
667 this.offset.click.top, item.top + ( item.height / 2 ), item.height ), |
704 this.offset.click.top, item.top + ( item.height / 2 ), item.height ), |
668 isOverRightHalf = this._isOverAxis( this.positionAbs.left + |
705 isOverRightHalf = this._isOverAxis( this.positionAbs.left + |
669 this.offset.click.left, item.left + ( item.width / 2 ), item.width ), |
706 this.offset.click.left, item.left + ( item.width / 2 ), item.width ), |
670 verticalDirection = this._getDragVerticalDirection(), |
707 verticalDirection = this.dragDirection.vertical, |
671 horizontalDirection = this._getDragHorizontalDirection(); |
708 horizontalDirection = this.dragDirection.horizontal; |
672 |
709 |
673 if ( this.floating && horizontalDirection ) { |
710 if ( this.floating && horizontalDirection ) { |
674 return ( ( horizontalDirection === "right" && isOverRightHalf ) || |
711 return ( ( horizontalDirection === "right" && isOverRightHalf ) || |
675 ( horizontalDirection === "left" && !isOverRightHalf ) ); |
712 ( horizontalDirection === "left" && !isOverRightHalf ) ); |
676 } else { |
713 } else { |
715 for ( i = connectWith.length - 1; i >= 0; i-- ) { |
752 for ( i = connectWith.length - 1; i >= 0; i-- ) { |
716 cur = $( connectWith[ i ], this.document[ 0 ] ); |
753 cur = $( connectWith[ i ], this.document[ 0 ] ); |
717 for ( j = cur.length - 1; j >= 0; j-- ) { |
754 for ( j = cur.length - 1; j >= 0; j-- ) { |
718 inst = $.data( cur[ j ], this.widgetFullName ); |
755 inst = $.data( cur[ j ], this.widgetFullName ); |
719 if ( inst && inst !== this && !inst.options.disabled ) { |
756 if ( inst && inst !== this && !inst.options.disabled ) { |
720 queries.push( [ $.isFunction( inst.options.items ) ? |
757 queries.push( [ typeof inst.options.items === "function" ? |
721 inst.options.items.call( inst.element ) : |
758 inst.options.items.call( inst.element ) : |
722 $( inst.options.items, inst.element ) |
759 $( inst.options.items, inst.element ) |
723 .not( ".ui-sortable-helper" ) |
760 .not( ".ui-sortable-helper" ) |
724 .not( ".ui-sortable-placeholder" ), inst ] ); |
761 .not( ".ui-sortable-placeholder" ), inst ] ); |
725 } |
762 } |
726 } |
763 } |
727 } |
764 } |
728 } |
765 } |
729 |
766 |
730 queries.push( [ $.isFunction( this.options.items ) ? |
767 queries.push( [ typeof this.options.items === "function" ? |
731 this.options.items |
768 this.options.items |
732 .call( this.element, null, { options: this.options, item: this.currentItem } ) : |
769 .call( this.element, null, { options: this.options, item: this.currentItem } ) : |
733 $( this.options.items, this.element ) |
770 $( this.options.items, this.element ) |
734 .not( ".ui-sortable-helper" ) |
771 .not( ".ui-sortable-helper" ) |
735 .not( ".ui-sortable-placeholder" ), this ] ); |
772 .not( ".ui-sortable-placeholder" ), this ] ); |
765 this.items = []; |
802 this.items = []; |
766 this.containers = [ this ]; |
803 this.containers = [ this ]; |
767 |
804 |
768 var i, j, cur, inst, targetData, _queries, item, queriesLength, |
805 var i, j, cur, inst, targetData, _queries, item, queriesLength, |
769 items = this.items, |
806 items = this.items, |
770 queries = [ [ $.isFunction( this.options.items ) ? |
807 queries = [ [ typeof this.options.items === "function" ? |
771 this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) : |
808 this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) : |
772 $( this.options.items, this.element ), this ] ], |
809 $( this.options.items, this.element ), this ] ], |
773 connectWith = this._connectWith(); |
810 connectWith = this._connectWith(); |
774 |
811 |
775 //Shouldn't be run the first time through due to massive slow-down |
812 //Shouldn't be run the first time through due to massive slow-down |
808 } |
845 } |
809 } |
846 } |
810 |
847 |
811 }, |
848 }, |
812 |
849 |
|
850 _refreshItemPositions: function( fast ) { |
|
851 var i, item, t, p; |
|
852 |
|
853 for ( i = this.items.length - 1; i >= 0; i-- ) { |
|
854 item = this.items[ i ]; |
|
855 |
|
856 //We ignore calculating positions of all connected containers when we're not over them |
|
857 if ( this.currentContainer && item.instance !== this.currentContainer && |
|
858 item.item[ 0 ] !== this.currentItem[ 0 ] ) { |
|
859 continue; |
|
860 } |
|
861 |
|
862 t = this.options.toleranceElement ? |
|
863 $( this.options.toleranceElement, item.item ) : |
|
864 item.item; |
|
865 |
|
866 if ( !fast ) { |
|
867 item.width = t.outerWidth(); |
|
868 item.height = t.outerHeight(); |
|
869 } |
|
870 |
|
871 p = t.offset(); |
|
872 item.left = p.left; |
|
873 item.top = p.top; |
|
874 } |
|
875 }, |
|
876 |
813 refreshPositions: function( fast ) { |
877 refreshPositions: function( fast ) { |
814 |
878 |
815 // Determine whether items are being displayed horizontally |
879 // Determine whether items are being displayed horizontally |
816 this.floating = this.items.length ? |
880 this.floating = this.items.length ? |
817 this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) : |
881 this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) : |
818 false; |
882 false; |
819 |
883 |
820 //This has to be redone because due to the item being moved out/into the offsetParent, |
884 // This has to be redone because due to the item being moved out/into the offsetParent, |
821 // the offsetParent's position will change |
885 // the offsetParent's position will change |
822 if ( this.offsetParent && this.helper ) { |
886 if ( this.offsetParent && this.helper ) { |
823 this.offset.parent = this._getParentOffset(); |
887 this.offset.parent = this._getParentOffset(); |
824 } |
888 } |
825 |
889 |
826 var i, item, t, p; |
890 this._refreshItemPositions( fast ); |
827 |
891 |
828 for ( i = this.items.length - 1; i >= 0; i-- ) { |
892 var i, p; |
829 item = this.items[ i ]; |
|
830 |
|
831 //We ignore calculating positions of all connected containers when we're not over them |
|
832 if ( item.instance !== this.currentContainer && this.currentContainer && |
|
833 item.item[ 0 ] !== this.currentItem[ 0 ] ) { |
|
834 continue; |
|
835 } |
|
836 |
|
837 t = this.options.toleranceElement ? |
|
838 $( this.options.toleranceElement, item.item ) : |
|
839 item.item; |
|
840 |
|
841 if ( !fast ) { |
|
842 item.width = t.outerWidth(); |
|
843 item.height = t.outerHeight(); |
|
844 } |
|
845 |
|
846 p = t.offset(); |
|
847 item.left = p.left; |
|
848 item.top = p.top; |
|
849 } |
|
850 |
893 |
851 if ( this.options.custom && this.options.custom.refreshContainers ) { |
894 if ( this.options.custom && this.options.custom.refreshContainers ) { |
852 this.options.custom.refreshContainers.call( this ); |
895 this.options.custom.refreshContainers.call( this ); |
853 } else { |
896 } else { |
854 for ( i = this.containers.length - 1; i >= 0; i-- ) { |
897 for ( i = this.containers.length - 1; i >= 0; i-- ) { |
865 return this; |
908 return this; |
866 }, |
909 }, |
867 |
910 |
868 _createPlaceholder: function( that ) { |
911 _createPlaceholder: function( that ) { |
869 that = that || this; |
912 that = that || this; |
870 var className, |
913 var className, nodeName, |
871 o = that.options; |
914 o = that.options; |
872 |
915 |
873 if ( !o.placeholder || o.placeholder.constructor === String ) { |
916 if ( !o.placeholder || o.placeholder.constructor === String ) { |
874 className = o.placeholder; |
917 className = o.placeholder; |
|
918 nodeName = that.currentItem[ 0 ].nodeName.toLowerCase(); |
875 o.placeholder = { |
919 o.placeholder = { |
876 element: function() { |
920 element: function() { |
877 |
921 |
878 var nodeName = that.currentItem[ 0 ].nodeName.toLowerCase(), |
922 var element = $( "<" + nodeName + ">", that.document[ 0 ] ); |
879 element = $( "<" + nodeName + ">", that.document[ 0 ] ); |
923 |
880 |
924 that._addClass( element, "ui-sortable-placeholder", |
881 that._addClass( element, "ui-sortable-placeholder", |
925 className || that.currentItem[ 0 ].className ) |
882 className || that.currentItem[ 0 ].className ) |
926 ._removeClass( element, "ui-sortable-helper" ); |
883 ._removeClass( element, "ui-sortable-helper" ); |
|
884 |
927 |
885 if ( nodeName === "tbody" ) { |
928 if ( nodeName === "tbody" ) { |
886 that._createTrPlaceholder( |
929 that._createTrPlaceholder( |
887 that.currentItem.find( "tr" ).eq( 0 ), |
930 that.currentItem.find( "tr" ).eq( 0 ), |
888 $( "<tr>", that.document[ 0 ] ).appendTo( element ) |
931 $( "<tr>", that.document[ 0 ] ).appendTo( element ) |
907 // class name is specified |
950 // class name is specified |
908 if ( className && !o.forcePlaceholderSize ) { |
951 if ( className && !o.forcePlaceholderSize ) { |
909 return; |
952 return; |
910 } |
953 } |
911 |
954 |
912 //If the element doesn't have a actual height by itself (without styles coming |
955 // If the element doesn't have a actual height or width by itself (without |
913 // from a stylesheet), it receives the inline height from the dragged item |
956 // styles coming from a stylesheet), it receives the inline height and width |
914 if ( !p.height() ) { |
957 // from the dragged item. Or, if it's a tbody or tr, it's going to have a height |
|
958 // anyway since we're populating them with <td>s above, but they're unlikely to |
|
959 // be the correct height on their own if the row heights are dynamic, so we'll |
|
960 // always assign the height of the dragged item given forcePlaceholderSize |
|
961 // is true. |
|
962 if ( !p.height() || ( o.forcePlaceholderSize && |
|
963 ( nodeName === "tbody" || nodeName === "tr" ) ) ) { |
915 p.height( |
964 p.height( |
916 that.currentItem.innerHeight() - |
965 that.currentItem.innerHeight() - |
917 parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) - |
966 parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) - |
918 parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) ); |
967 parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) ); |
919 } |
968 } |
1042 this.currentContainer.containerCache.over = 1; |
1091 this.currentContainer.containerCache.over = 1; |
1043 } |
1092 } |
1044 return; |
1093 return; |
1045 } |
1094 } |
1046 |
1095 |
1047 itemWithLeastDistance ? |
1096 if ( itemWithLeastDistance ) { |
1048 this._rearrange( event, itemWithLeastDistance, null, true ) : |
1097 this._rearrange( event, itemWithLeastDistance, null, true ); |
|
1098 } else { |
1049 this._rearrange( event, null, this.containers[ innermostIndex ].element, true ); |
1099 this._rearrange( event, null, this.containers[ innermostIndex ].element, true ); |
|
1100 } |
1050 this._trigger( "change", event, this._uiHash() ); |
1101 this._trigger( "change", event, this._uiHash() ); |
1051 this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) ); |
1102 this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) ); |
1052 this.currentContainer = this.containers[ innermostIndex ]; |
1103 this.currentContainer = this.containers[ innermostIndex ]; |
1053 |
1104 |
1054 //Update the placeholder |
1105 //Update the placeholder |
1055 this.options.placeholder.update( this.currentContainer, this.placeholder ); |
1106 this.options.placeholder.update( this.currentContainer, this.placeholder ); |
1056 |
1107 |
|
1108 //Update scrollParent |
|
1109 this.scrollParent = this.placeholder.scrollParent(); |
|
1110 |
|
1111 //Update overflowOffset |
|
1112 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && |
|
1113 this.scrollParent[ 0 ].tagName !== "HTML" ) { |
|
1114 this.overflowOffset = this.scrollParent.offset(); |
|
1115 } |
|
1116 |
1057 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) ); |
1117 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) ); |
1058 this.containers[ innermostIndex ].containerCache.over = 1; |
1118 this.containers[ innermostIndex ].containerCache.over = 1; |
1059 } |
1119 } |
1060 |
1120 |
1061 }, |
1121 }, |
1062 |
1122 |
1063 _createHelper: function( event ) { |
1123 _createHelper: function( event ) { |
1064 |
1124 |
1065 var o = this.options, |
1125 var o = this.options, |
1066 helper = $.isFunction( o.helper ) ? |
1126 helper = typeof o.helper === "function" ? |
1067 $( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) : |
1127 $( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) : |
1068 ( o.helper === "clone" ? this.currentItem.clone() : this.currentItem ); |
1128 ( o.helper === "clone" ? this.currentItem.clone() : this.currentItem ); |
1069 |
1129 |
1070 //Add the helper to the DOM if that didn't happen already |
1130 //Add the helper to the DOM if that didn't happen already |
1071 if ( !helper.parents( "body" ).length ) { |
1131 if ( !helper.parents( "body" ).length ) { |
1072 $( o.appendTo !== "parent" ? |
1132 this.appendTo[ 0 ].appendChild( helper[ 0 ] ); |
1073 o.appendTo : |
|
1074 this.currentItem[ 0 ].parentNode )[ 0 ].appendChild( helper[ 0 ] ); |
|
1075 } |
1133 } |
1076 |
1134 |
1077 if ( helper[ 0 ] === this.currentItem[ 0 ] ) { |
1135 if ( helper[ 0 ] === this.currentItem[ 0 ] ) { |
1078 this._storedCSS = { |
1136 this._storedCSS = { |
1079 width: this.currentItem[ 0 ].style.width, |
1137 width: this.currentItem[ 0 ].style.width, |
1128 // next positioned parent |
1186 // next positioned parent |
1129 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't |
1187 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't |
1130 // the document, which means that the scroll is included in the initial calculation of the |
1188 // the document, which means that the scroll is included in the initial calculation of the |
1131 // offset of the parent, and never recalculated upon drag |
1189 // offset of the parent, and never recalculated upon drag |
1132 if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] && |
1190 if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] && |
1133 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) { |
1191 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) { |
1134 po.left += this.scrollParent.scrollLeft(); |
1192 po.left += this.scrollParent.scrollLeft(); |
1135 po.top += this.scrollParent.scrollTop(); |
1193 po.top += this.scrollParent.scrollTop(); |
1136 } |
1194 } |
1137 |
1195 |
1138 // This needs to be actually done for all browsers, since pageX/pageY includes this |
1196 // This needs to be actually done for all browsers, since pageX/pageY includes this |
1139 // information with an ugly IE fix |
1197 // information with an ugly IE fix |
1140 if ( this.offsetParent[ 0 ] === this.document[ 0 ].body || |
1198 if ( this.offsetParent[ 0 ] === this.document[ 0 ].body || |
1141 ( this.offsetParent[ 0 ].tagName && |
1199 ( this.offsetParent[ 0 ].tagName && |
1142 this.offsetParent[ 0 ].tagName.toLowerCase() === "html" && $.ui.ie ) ) { |
1200 this.offsetParent[ 0 ].tagName.toLowerCase() === "html" && $.ui.ie ) ) { |
1143 po = { top: 0, left: 0 }; |
1201 po = { top: 0, left: 0 }; |
1144 } |
1202 } |
1145 |
1203 |
1146 return { |
1204 return { |
1206 co = $( o.containment ).offset(); |
1264 co = $( o.containment ).offset(); |
1207 over = ( $( ce ).css( "overflow" ) !== "hidden" ); |
1265 over = ( $( ce ).css( "overflow" ) !== "hidden" ); |
1208 |
1266 |
1209 this.containment = [ |
1267 this.containment = [ |
1210 co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) + |
1268 co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) + |
1211 ( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left, |
1269 ( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left, |
1212 co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) + |
1270 co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) + |
1213 ( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top, |
1271 ( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top, |
1214 co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - |
1272 co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - |
1215 ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) - |
1273 ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) - |
1216 ( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) - |
1274 ( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) - |
1217 this.helperProportions.width - this.margins.left, |
1275 this.helperProportions.width - this.margins.left, |
1218 co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - |
1276 co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - |
1219 ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) - |
1277 ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) - |
1220 ( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) - |
1278 ( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) - |
1221 this.helperProportions.height - this.margins.top |
1279 this.helperProportions.height - this.margins.top |
1222 ]; |
1280 ]; |
1223 } |
1281 } |
1224 |
1282 |
1225 }, |
1283 }, |
1226 |
1284 |
1275 var top, left, |
1333 var top, left, |
1276 o = this.options, |
1334 o = this.options, |
1277 pageX = event.pageX, |
1335 pageX = event.pageX, |
1278 pageY = event.pageY, |
1336 pageY = event.pageY, |
1279 scroll = this.cssPosition === "absolute" && |
1337 scroll = this.cssPosition === "absolute" && |
1280 !( this.scrollParent[ 0 ] !== this.document[ 0 ] && |
1338 !( this.scrollParent[ 0 ] !== this.document[ 0 ] && |
1281 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? |
1339 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? |
1282 this.offsetParent : |
1340 this.offsetParent : |
1283 this.scrollParent, |
1341 this.scrollParent, |
1284 scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName ); |
1342 scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName ); |
1285 |
1343 |
1286 // This is another very weird special case that only happens for relative elements: |
1344 // This is another very weird special case that only happens for relative elements: |
1287 // 1. If the css position is relative |
1345 // 1. If the css position is relative |
1288 // 2. and the scroll parent is the document or similar to the offset parent |
1346 // 2. and the scroll parent is the document or similar to the offset parent |
1289 // we have to refresh the relative offset during the scroll so there are no jumps |
1347 // we have to refresh the relative offset during the scroll so there are no jumps |
1290 if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] && |
1348 if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] && |
1291 this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) { |
1349 this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) { |
1292 this.offset.relative = this._getRelativeOffset(); |
1350 this.offset.relative = this._getRelativeOffset(); |
1293 } |
1351 } |
1294 |
1352 |
1295 /* |
1353 /* |
1296 * - Position constraining - |
1354 * - Position constraining - |
1318 top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) / |
1376 top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) / |
1319 o.grid[ 1 ] ) * o.grid[ 1 ]; |
1377 o.grid[ 1 ] ) * o.grid[ 1 ]; |
1320 pageY = this.containment ? |
1378 pageY = this.containment ? |
1321 ( ( top - this.offset.click.top >= this.containment[ 1 ] && |
1379 ( ( top - this.offset.click.top >= this.containment[ 1 ] && |
1322 top - this.offset.click.top <= this.containment[ 3 ] ) ? |
1380 top - this.offset.click.top <= this.containment[ 3 ] ) ? |
1323 top : |
1381 top : |
1324 ( ( top - this.offset.click.top >= this.containment[ 1 ] ) ? |
1382 ( ( top - this.offset.click.top >= this.containment[ 1 ] ) ? |
1325 top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : |
1383 top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : |
1326 top; |
1384 top; |
1327 |
1385 |
1328 left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) / |
1386 left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) / |
1329 o.grid[ 0 ] ) * o.grid[ 0 ]; |
1387 o.grid[ 0 ] ) * o.grid[ 0 ]; |
1330 pageX = this.containment ? |
1388 pageX = this.containment ? |
1331 ( ( left - this.offset.click.left >= this.containment[ 0 ] && |
1389 ( ( left - this.offset.click.left >= this.containment[ 0 ] && |
1332 left - this.offset.click.left <= this.containment[ 2 ] ) ? |
1390 left - this.offset.click.left <= this.containment[ 2 ] ) ? |
1333 left : |
1391 left : |
1334 ( ( left - this.offset.click.left >= this.containment[ 0 ] ) ? |
1392 ( ( left - this.offset.click.left >= this.containment[ 0 ] ) ? |
1335 left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : |
1393 left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : |
1336 left; |
1394 left; |
1337 } |
1395 } |
1338 |
1396 |
1339 } |
1397 } |
1340 |
1398 |
1341 return { |
1399 return { |
1377 |
1435 |
1378 }, |
1436 }, |
1379 |
1437 |
1380 _rearrange: function( event, i, a, hardRefresh ) { |
1438 _rearrange: function( event, i, a, hardRefresh ) { |
1381 |
1439 |
1382 a ? a[ 0 ].appendChild( this.placeholder[ 0 ] ) : |
1440 if ( a ) { |
|
1441 a[ 0 ].appendChild( this.placeholder[ 0 ] ); |
|
1442 } else { |
1383 i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ], |
1443 i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ], |
1384 ( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) ); |
1444 ( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) ); |
|
1445 } |
1385 |
1446 |
1386 //Various things done here to improve the performance: |
1447 //Various things done here to improve the performance: |
1387 // 1. we create a setTimeout, that calls refreshPositions |
1448 // 1. we create a setTimeout, that calls refreshPositions |
1388 // 2. on the instance, we have a counter variable, that get's higher after every append |
1449 // 2. on the instance, we have a counter variable, that get's higher after every append |
1389 // 3. on the local scope, we copy the counter variable, and check in the timeout, |
1450 // 3. on the local scope, we copy the counter variable, and check in the timeout, |