You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
365 lines
14 KiB
365 lines
14 KiB
4 years ago
|
/// 脚本引用
|
||
|
/// <reference path="/Scripts/jquery.1.11.0.min.js"/>
|
||
|
|
||
|
/// <summary>
|
||
|
/// 功能模块:启明js拖拽类
|
||
|
/// 作者:黄顺权
|
||
|
/// 编码日期:2014年09月23日
|
||
|
/// </summary>
|
||
|
(function ($) {
|
||
|
/// <summary>
|
||
|
/// jQuery对象的扩展方法
|
||
|
/// </summary>
|
||
|
$.fn.extend({
|
||
|
/// 获得对象的绝对布局
|
||
|
getLayout: function () {
|
||
|
var pos = this.css("position") == "static" ? this.offset() : this.position();
|
||
|
var w = this.width();
|
||
|
var h = this.height()
|
||
|
return { left: pos.left, top: pos.top, right: pos.left + w, bottom: pos.top + h, width: w, height: h };
|
||
|
},
|
||
|
|
||
|
/// 获得对象的偏移布局
|
||
|
getOffsetLayout: function () {
|
||
|
var pos = this.offset();
|
||
|
var w = this.width();
|
||
|
var h = this.height()
|
||
|
return { left: pos.left, top: pos.top, right: pos.left + w, bottom: pos.top + h, width: w, height: h };
|
||
|
}
|
||
|
});
|
||
|
|
||
|
/// 定义$.qm命名空间
|
||
|
if (typeof ($.qm) != "object") $.qm = {};
|
||
|
|
||
|
/// <summary>
|
||
|
/// 定义拖放匿名类,最后将该类绑定到$.qm命名空间下
|
||
|
/// </summary>
|
||
|
(function () {
|
||
|
|
||
|
/// 拖拽状态标志
|
||
|
var _isDragging = false;
|
||
|
|
||
|
/// 拖放对象
|
||
|
var _dropObjects = [];
|
||
|
|
||
|
/// 默认拖拽配置
|
||
|
var _defaultDragOptions = {
|
||
|
container: null,
|
||
|
handle: null,
|
||
|
proxy: null,
|
||
|
revert: false,
|
||
|
delay: 0,
|
||
|
cursor: 'pointer',
|
||
|
onStartDrag: function (e) { },
|
||
|
onDrag: function (e) { },
|
||
|
onStopDrag: function (e) { },
|
||
|
onClick: function (e) { }
|
||
|
};
|
||
|
|
||
|
/// 默认拖放配置
|
||
|
var _defaultDropOptions = {
|
||
|
onDropOver: function (e) { },
|
||
|
onDrop: function (e, source, target) { }
|
||
|
};
|
||
|
|
||
|
/// 单击事件代理函数
|
||
|
var onclickHook = function (e) {
|
||
|
if (_isDragging) return;
|
||
|
var dragInfo = $.data(this, "qm_drag");
|
||
|
if (dragInfo.onclick instanceof Function) dragInfo.onclick.call(this, e);
|
||
|
};
|
||
|
|
||
|
/// 双击事件代理函数
|
||
|
var ondblclickHook = function (e) {
|
||
|
if (_isDragging) return;
|
||
|
var dragInfo = $.data(this, "qm_drag");
|
||
|
if (dragInfo.ondblclick instanceof Function) dragInfo.ondblclick.call(this, e);
|
||
|
};
|
||
|
|
||
|
/// 获得鼠标位置
|
||
|
var getMousePos = function (e) {
|
||
|
//return { x: e.originalEvent.x || e.originalEvent.layerX || 0, y: e.originalEvent.y || e.originalEvent.layerY || 0 };
|
||
|
return { x: e.pageX, y: e.pageY };
|
||
|
};
|
||
|
|
||
|
/// 判断坐标点是否在矩形内
|
||
|
var ptInRect = function (pt, rect) {
|
||
|
return pt.x > rect.left && pt.x < rect.right && pt.y > rect.top && pt.y < rect.bottom;
|
||
|
};
|
||
|
|
||
|
/// 判断第一个矩形是否在第二个矩形内
|
||
|
var rectInRect = function (rect1, rect2) {
|
||
|
return rect1.left > rect2.left && rect1.top > rect2.top && rect1.right < rect2.right && rect1.bottom < rect2.bottom;
|
||
|
};
|
||
|
|
||
|
/// 鼠标按下事件检测函数
|
||
|
var mouseDownCheck = function (e) {
|
||
|
//获得鼠标事件参数
|
||
|
var eventArgs = $.extend(true, {}, e);
|
||
|
//获得运行时参数
|
||
|
var dragInfo = $.data(e.data.srcElement, "qm_drag");
|
||
|
var opts = dragInfo.options;
|
||
|
var source = this;
|
||
|
//判断是否需要延时触发拖拽事件
|
||
|
if (opts.delay > 0) { //延时触发
|
||
|
this.setCapture();
|
||
|
var theElementLayout = $(this).getLayout();
|
||
|
var timerID = setTimeout(function () {
|
||
|
_isDragging = true;
|
||
|
$(document).unbind(".dragCheck");
|
||
|
mouseDownHandler.call(source, eventArgs);
|
||
|
}, opts.delay);
|
||
|
$(document).bind("mousemove.dragCheck", { srcElement: this }, function (e) {
|
||
|
var mousePos = getMousePos(e);
|
||
|
eventArgs = $.extend(true, {}, e); //获得鼠标事件参数
|
||
|
if (!ptInRect(mousePos, theElementLayout)) {
|
||
|
clearTimeout(timerID);
|
||
|
e.data.srcElement.releaseCapture();
|
||
|
$(document).unbind(".dragCheck");
|
||
|
}
|
||
|
});
|
||
|
$(document).bind("mouseup.dragCheck", { srcElement: this }, function (e) {
|
||
|
clearTimeout(timerID);
|
||
|
e.data.srcElement.releaseCapture();
|
||
|
$(document).unbind(".dragCheck");
|
||
|
});
|
||
|
}
|
||
|
else {//立即触发拖拽事件
|
||
|
_isDragging = true;
|
||
|
mouseDownHandler.call(source, eventArgs);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/// 鼠标按下事件处理函数
|
||
|
var mouseDownHandler = function (e) {
|
||
|
//获得运行时参数
|
||
|
var dragInfo = $.data(this, "qm_drag");
|
||
|
var source = dragInfo.source;
|
||
|
var opts = dragInfo.options;
|
||
|
|
||
|
//保存当前鼠标位置
|
||
|
dragInfo.mousePos = getMousePos(e);
|
||
|
|
||
|
//获得被拖拽对象的当前布局
|
||
|
source.layout = source.getLayout();
|
||
|
//获得容器的布局
|
||
|
if (opts.container != null) {
|
||
|
var container = $(opts.container);
|
||
|
dragInfo.containerLayout = container.getLayout();
|
||
|
}
|
||
|
|
||
|
//获得实际被拖拽的代理对象
|
||
|
if (opts.proxy == 'clone') {
|
||
|
dragInfo.proxy = source.clone().insertAfter(this);
|
||
|
} else {
|
||
|
dragInfo.proxy = source;
|
||
|
}
|
||
|
|
||
|
var proxy = dragInfo.proxy;
|
||
|
//获得拖拽对象的定位和zIndex
|
||
|
source._position = source.css("position");
|
||
|
source._zIndex = source.css("z-index");
|
||
|
//设置被拖拽对象的起始位置
|
||
|
proxy.css({ position: "absolute", left: source.layout.left + 5 + "px", top: source.layout.top + 5 + "px" });
|
||
|
//设置新的zIndex
|
||
|
proxy.css("z-index", 1002);
|
||
|
//获得被拖拽对象的当前位置(移移5像素,以便增加视觉效果)
|
||
|
proxy.currentPos = { left: source.layout.left + 5, top: source.layout.top + 5 };
|
||
|
|
||
|
//设置鼠标抓取能力
|
||
|
document.documentElement.setCapture();
|
||
|
//绑定鼠标移动和抬起事件
|
||
|
$(document).bind('mousemove.dragging', { srcElement: this }, mouseMoveHandler);
|
||
|
$(document).bind('mouseup.dragging', { srcElement: this }, mouseUpHandler);
|
||
|
|
||
|
//触发调用者的拖拽开始事件
|
||
|
//opts.onStartDrag.call(this, e);
|
||
|
opts.onStartDrag.call(proxy[0], e);
|
||
|
};
|
||
|
|
||
|
/// 鼠标移动事件处理
|
||
|
var mouseMoveHandler = function (e) {
|
||
|
//获得运行时参数
|
||
|
var dragInfo = $.data(e.data.srcElement, "qm_drag");
|
||
|
var source = dragInfo.source;
|
||
|
var proxy = dragInfo.proxy;
|
||
|
var opts = dragInfo.options;
|
||
|
|
||
|
//获得当前鼠标位置
|
||
|
var mousePos = getMousePos(e);
|
||
|
//计算鼠标移动距离
|
||
|
var distance = { x: mousePos.x - dragInfo.mousePos.x, y: mousePos.y - dragInfo.mousePos.y };
|
||
|
//保存当前鼠标位置
|
||
|
dragInfo.mousePos = mousePos;
|
||
|
|
||
|
//获得被拖拽对象移到的位置
|
||
|
proxy.currentPos.left += distance.x;
|
||
|
proxy.currentPos.top += distance.y;
|
||
|
//移动被拖拽对象
|
||
|
if (opts.container != null) {
|
||
|
//获得被拖拽对象的新的布局
|
||
|
var rect = { left: proxy.currentPos.left, top: proxy.currentPos.top,
|
||
|
right: proxy.currentPos.left + source.layout.width,
|
||
|
bottom: proxy.currentPos.top + source.layout.height
|
||
|
};
|
||
|
var containerLayout = dragInfo.containerLayout;
|
||
|
if (rectInRect(rect, containerLayout)) { //如果被拖拽对象在容器内部
|
||
|
//设置被拖拽对象的水平和垂直坐标
|
||
|
proxy.css({ left: proxy.currentPos.left + "px", top: proxy.currentPos.top + "px" });
|
||
|
} else if (rect.left > containerLayout.left && rect.right < containerLayout.right) { //如果被拖拽象的水平坐标在容器内部
|
||
|
//设置被拖拽对象的水平坐标
|
||
|
proxy.css({ left: proxy.currentPos.left + "px" });
|
||
|
} else if (rect.top > containerLayout.top && rect.bottom < containerLayout.bottom) { //如果被拖拽象的垂直坐标在容器内部
|
||
|
//设置被拖拽对象的垂直坐标
|
||
|
proxy.css({ top: proxy.currentPos.top + "px" });
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
proxy.css({ left: proxy.currentPos.left + "px", top: proxy.currentPos.top + "px" });
|
||
|
}
|
||
|
|
||
|
//触发调用者的拖拽事件
|
||
|
opts.onDrag.call(source[0], e);
|
||
|
|
||
|
//触发拖放对象的onDropOver事件
|
||
|
var eventArgs = $.extend(true, {}, e);
|
||
|
for (var i = 0; i < _dropObjects.length; i++) {
|
||
|
var objDrop = $(_dropObjects[i]);
|
||
|
var layout = objDrop.getLayout();
|
||
|
if (ptInRect(mousePos, layout)) {
|
||
|
var options = $.data(_dropObjects[i], "qm_drop").options;
|
||
|
options.onDropOver.call(_dropObjects[i], eventArgs);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/// 鼠标抬起事件处理
|
||
|
var mouseUpHandler = function (e) {
|
||
|
//获得运行时参数
|
||
|
var dragInfo = $.data(e.data.srcElement, "qm_drag");
|
||
|
var source = dragInfo.source;
|
||
|
var proxy = dragInfo.proxy;
|
||
|
var opts = dragInfo.options;
|
||
|
|
||
|
//获得当前鼠标位置
|
||
|
var mousePos = getMousePos(e);
|
||
|
|
||
|
//取消鼠标抓取
|
||
|
document.documentElement.releaseCapture();
|
||
|
//取消事件绑定
|
||
|
$(document).unbind('.dragging');
|
||
|
|
||
|
//复制事件参数
|
||
|
var eventArgs = $.extend(true, {}, e);
|
||
|
|
||
|
//设置拖拽标志结束
|
||
|
_isDragging = false;
|
||
|
|
||
|
//触发调用者的拖拽结束事件
|
||
|
opts.onStopDrag.call(source[0], e);
|
||
|
|
||
|
//结束拖拽
|
||
|
var stopDrag = function () {
|
||
|
//处理实际被拖拽的对象
|
||
|
if (opts.proxy == 'clone') {
|
||
|
proxy.remove(); //删除代理
|
||
|
} else {
|
||
|
//恢复原来的定位方式和zIndex
|
||
|
source.css("position", source._position);
|
||
|
source.css("z-index", source._zIndex);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//触发拖放对象的onDrop事件
|
||
|
for (var i = 0; i < _dropObjects.length; i++) {
|
||
|
var theElement = _dropObjects[i];
|
||
|
if (theElement == e.data.srcElement) continue;
|
||
|
var objDrop = $(theElement);
|
||
|
var layout = objDrop.getLayout();
|
||
|
if (ptInRect(mousePos, layout)) {
|
||
|
var options = $.data(theElement, "qm_drop").options;
|
||
|
if (options.onDrop.call(e.data.srcElement, eventArgs, e.data.srcElement, theElement) == false) {
|
||
|
stopDrag();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (opts.revert) { //如果恢复到拖拽前的位置
|
||
|
var layout = source.getLayout();
|
||
|
proxy.animate({ left: layout.left + "px", top: layout.top + "px" }, stopDrag);
|
||
|
} else {
|
||
|
stopDrag();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
/// 拖拽方法
|
||
|
this.drag = function (dragObjects, options) {
|
||
|
//处理容器布局,以防拖拽超出了容器的范围
|
||
|
if (options instanceof Object && options.container) {
|
||
|
var container = $(options.container);
|
||
|
$(window).bind("resize", { container: container }, function (e) { e.data.container[0].layout = e.data.container.getLayout(); });
|
||
|
}
|
||
|
//遍历每个对象注册鼠标事件
|
||
|
$(dragObjects).each(function () {
|
||
|
var opts;
|
||
|
|
||
|
//获得运行时配置(以便fn.qm.drag可以多次调用)
|
||
|
var dragInfo = $.data(this, "qm_drag");
|
||
|
if (!(dragInfo instanceof Object)) {
|
||
|
opts = $.extend({}, _defaultDragOptions, options || {});
|
||
|
} else {
|
||
|
opts = $.extend(dragInfo.options, options);
|
||
|
}
|
||
|
//保存运行时配置
|
||
|
var objDrag = $(this);
|
||
|
dragInfo = {
|
||
|
options: opts,
|
||
|
source: objDrag, //要拖拽的对象
|
||
|
handle: opts.handle ? $(opts.handle) : objDrag, //拖拽把手
|
||
|
onclick: this.onclick,
|
||
|
ondblclick: this.ondblclick
|
||
|
};
|
||
|
this.onclick = onclickHook;
|
||
|
this.ondblclick = ondblclickHook;
|
||
|
$.data(this, "qm_drag", dragInfo);
|
||
|
|
||
|
//设置被拖拽对象的鼠标形状
|
||
|
objDrag.css("cursor", opts.cursor);
|
||
|
|
||
|
//检查鼠标按下事件
|
||
|
$(dragInfo.handle).bind("mousedown", { srcElement: this }, mouseDownCheck);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
/// 拖放方法
|
||
|
this.drop = function (dropObjects, options) {
|
||
|
dropObjects = $(dropObjects);
|
||
|
|
||
|
//遍历每个对象注册拖放事件
|
||
|
$(dropObjects).each(function () {
|
||
|
var opts;
|
||
|
|
||
|
//保存拖放对象到全局数组中
|
||
|
_dropObjects.push(this);
|
||
|
|
||
|
//获得运行时配置
|
||
|
var dropInfo = $.data(this, "qm_drop");
|
||
|
if (!(dropInfo instanceof Object)) {
|
||
|
opts = $.extend({}, _defaultDropOptions, options || {});
|
||
|
} else {
|
||
|
opts = $.extend(dropInfo.options, options);
|
||
|
}
|
||
|
//保存运行时配置
|
||
|
var dropObj = $(this);
|
||
|
dropInfo = {
|
||
|
options: opts,
|
||
|
source: dropObj //要拖放的对象
|
||
|
};
|
||
|
$.data(this, "qm_drop", dropInfo);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
}).call($.qm);
|
||
|
})(jQuery);
|