拖拽js

( function ( factory) {
if ( typeof define === 'function' && define. amd) {
// AMD. Register as an anonymous module.
define([ 'jquery'], factory);
} else {
// Browser globals
factory( jQuery);
}
}( function ( $) {
var IS_TOUCH_DEVICE = ( 'ontouchstart' in document. documentElement);
/**
* mouse move threshold (in px) until drag action starts
* @type {Number}
*/
var DRAG_THRESHOLD = 5;
/**
* to generate event namespace
* @type {Number}
*/
var counter = 0;

/**
* Javascript events for touch device/desktop
* @return {Object}
*/
var dragEvents = ( function () {
if ( IS_TOUCH_DEVICE) {
return {
START: 'touchstart',
MOVE: 'touchmove',
END: 'touchend'
};
}
else {
return {
START: 'mousedown',
MOVE: 'mousemove',
END: 'mouseup'
};
}
}());

$. fn. arrangeable = function ( options) {
var dragging = false;
var $clone;
var dragElement;
var originalClientX, originalClientY; // client(X|Y) position before drag starts
var $elements; // list of elements to shift between
var touchDown = false;
var leftOffset, topOffset;
var eventNamespace;

if ( typeof options === "string") {
// check if want to destroy drag-arrange
if ( options === 'destroy') {
if ( this. eq( 0). data( 'drag-arrange-destroy')) {
this. eq( 0). data( 'drag-arrange-destroy')();
}

return this;
}
}

options = $. extend({
"dragEndEvent" : "drag.end.arrangeable"
}, options);

var dragEndEvent = options[ "dragEndEvent"];

$elements = this;
eventNamespace = getEventNamespace();

this. each( function () {
// bindings to trigger drag on element
var dragSelector = options. dragSelector;
var self = this;
var $this = $( this);

if ( dragSelector) {
$this. on( dragEvents. START + eventNamespace, dragSelector, dragStartHandler);
} else {
$this. on( dragEvents. START + eventNamespace, dragStartHandler);
}

function dragStartHandler( e) {
// a mouse down/touchstart event, but still drag doesn't start till threshold reaches
// stopPropagation is compulsory, otherwise touchmove fires only once (android < 4 issue)
e. stopPropagation();
touchDown = true;
originalClientX = e. clientX || e. originalEvent. touches[ 0]. clientX;
originalClientY = e. clientY || e. originalEvent. touches[ 0]. clientY;
dragElement = self;
}
});

// bind mouse-move/touchmove on document
// (as it is not compulsory that event will trigger on dragging element)
$( document). on( dragEvents. MOVE + eventNamespace, dragMoveHandler)
. on( dragEvents. END + eventNamespace, dragEndHandler);

function dragMoveHandler( e) {
if (! touchDown) { return; }

var $dragElement = $( dragElement);
var dragDistanceX = ( e. clientX || e. originalEvent. touches[ 0]. clientX) - originalClientX;
var dragDistanceY = ( e. clientY || e. originalEvent. touches[ 0]. clientY) - originalClientY;

if ( dragging) {
e. stopPropagation();

$clone. css({
left: leftOffset + dragDistanceX,
top: topOffset + dragDistanceY
});

shiftHoveredElement( $clone, $dragElement, $elements);

// check for drag threshold (drag has not started yet)
} else if ( Math. abs( dragDistanceX) > DRAG_THRESHOLD ||
Math. abs( dragDistanceY) > DRAG_THRESHOLD) {
$clone = clone( $dragElement);

// initialize left offset and top offset
// will be used in successive calls of this function
leftOffset = dragElement. offsetLeft - parseInt( $dragElement. css( 'margin-left')) -
parseInt( $dragElement. css( 'padding-left'));
topOffset = dragElement. offsetTop - parseInt( $dragElement. css( 'margin-top')) -
parseInt( $dragElement. css( 'padding-top'));

// put cloned element just above the dragged element
// and move it instead of original element
$clone. css({
left: leftOffset,
top: topOffset
});
$dragElement. parent(). append( $clone);

// hide original dragged element
$dragElement. css( 'visibility', 'hidden');

dragging = true;
}
}

function dragEndHandler( e) {
if ( dragging) {
// remove the cloned dragged element and
// show original element back
e. stopPropagation();
dragging = false;
$clone. remove();
dragElement. style. visibility = 'visible';

$( dragElement). parent(). trigger( dragEndEvent, [ $( dragElement)]);
}

touchDown = false;
}

function destroy() {
$elements. each( function () {
// bindings to trigger drag on element
var dragSelector = options. dragSelector;
var $this = $( this);

if ( dragSelector) {
$this. off( dragEvents. START + eventNamespace, dragSelector);
} else {
$this. off( dragEvents. START + eventNamespace);
}
});

$( document). off( dragEvents. MOVE + eventNamespace)
. off( dragEvents. END + eventNamespace);

// remove data
$elements. eq( 0). data( 'drag-arrange-destroy', null);

// clear variables
$elements = null;
dragMoveHandler = null;
dragEndHandler = null;
}

this. eq( 0). data( 'drag-arrange-destroy', destroy);
};

function clone( $element) {
var $clone = $element. clone();

$clone. css({
position: 'absolute',
width: $element. width(),
height: $element. height(),
'z-index' : 100000 // very high value to prevent it to hide below other element(s)
});

return $clone;
}

/**
* find the element on which the dragged element is hovering
* @return {DOM Object} hovered element
*/
function getHoveredElement( $clone, $dragElement, $movableElements) {
var cloneOffset = $clone. offset();
var cloneWidth = $clone. width();
var cloneHeight = $clone. height();
var cloneLeftPosition = cloneOffset. left;
var cloneRightPosition = cloneOffset. left + cloneWidth;
var cloneTopPosition = cloneOffset. top;
var cloneBottomPosition = cloneOffset. top + cloneHeight;
var $currentElement;
var horizontalMidPosition, verticalMidPosition;
var offset, overlappingX, overlappingY, inRange;

for ( var i = 0; i < $movableElements. length; i++) {
$currentElement = $movableElements. eq( i);

if ( $currentElement[ 0] === $dragElement[ 0]) { continue; }

offset = $currentElement. offset();

// current element width and draggable element(clone) width or height can be different
horizontalMidPosition = offset. left + 0.5 * $currentElement. width();
verticalMidPosition = offset. top + 0.5 * $currentElement. height();

// check if this element position is overlapping with dragged element
overlappingX = ( horizontalMidPosition < cloneRightPosition) &&
( horizontalMidPosition > cloneLeftPosition);

overlappingY = ( verticalMidPosition < cloneBottomPosition) &&
( verticalMidPosition > cloneTopPosition);

inRange = overlappingX && overlappingY;

if ( inRange) {
return $currentElement[ 0];
}
}
}

function shiftHoveredElement( $clone, $dragElement, $movableElements) {
var hoveredElement = getHoveredElement( $clone, $dragElement, $movableElements);

if ( hoveredElement !== $dragElement[ 0]) {
// shift all other elements to make space for the dragged element
var hoveredElementIndex = $movableElements. index( hoveredElement);
var dragElementIndex = $movableElements. index( $dragElement);
if ( hoveredElementIndex < dragElementIndex) {
$( hoveredElement). before( $dragElement);
} else {
$( hoveredElement). after( $dragElement);
}

// since elements order have changed, need to change order in jQuery Object too
shiftElementPosition( $movableElements, dragElementIndex, hoveredElementIndex);
}
}

function shiftElementPosition( arr, fromIndex, toIndex) {
var temp = arr. splice( fromIndex, 1)[ 0];
return arr. splice( toIndex, 0, temp);
}

function getEventNamespace() {
counter += 1;

return '.drag-arrange-' + counter;
}

}));

猜你喜欢

转载自blog.csdn.net/qq_25236657/article/details/80134996