拖拽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;
}

}));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值