再谈js拖拽(一)

  关于js拖拽早已是老生常谈,网上一搜一大坨,但是有很多并不是很完善,或者兼容性不够,或者功能不全,并且这样的东西还是自己写的好用。我打算在(一)中主要对js拖拽功能的注意点进行罗列,力求简单;在(二)中利用(一)的拖拽去实现类似google个性化首页的拖拽模块功能。

  首先贴上完整code(IE/FF/Chrome)

 

ContractedBlock.gifExpandedBlockStart.gif代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title></title>
<script type="text/javascript">
var Common = {
getEvent:
function() {//ie/ff
if (document.all) {
return window.event;
}
func
= getEvent.caller;
while (func != null) {
var arg0 = func.arguments[0];
if (arg0) {
if ((arg0.constructor == Event || arg0.constructor == MouseEvent) || (typeof (arg0) == "object" && arg0.preventDefault && arg0.stopPropagation)) {
return arg0;
}
}
func
= func.caller;
}
return null;
},
getMousePos:
function(ev) {
if (!ev) {
ev
= this.getEvent();
}
if (ev.pageX || ev.pageY) {
return {
x: ev.pageX,
y: ev.pageY
};
}

if (document.documentElement && document.documentElement.scrollTop) {
return {
x: ev.clientX
+ document.documentElement.scrollLeft - document.documentElement.clientLeft,
y: ev.clientY
+ document.documentElement.scrollTop - document.documentElement.clientTop
};
}
else if (document.body) {
return {
x: ev.clientX
+ document.body.scrollLeft - document.body.clientLeft,
y: ev.clientY
+ document.body.scrollTop - document.body.clientTop
};
}
},
getItself:
function(id) {
return "string" == typeof id ? document.getElementById(id) : id;
},
getViewportSize: { w: (window.innerWidth)
? window.innerWidth : (document.documentElement && document.documentElement.clientWidth) ? document.documentElement.clientWidth : document.body.offsetWidth, h: (window.innerHeight) ? window.innerHeight : (document.documentElement && document.documentElement.clientHeight) ? document.documentElement.clientHeight : document.body.offsetHeight },
isIE: document.all
? true : false,
setOuterHtml:
function(obj, html) {
var Objrange = document.createRange();
obj.innerHTML
= html;
Objrange.selectNodeContents(obj);
var frag = Objrange.extractContents();
obj.parentNode.insertBefore(frag, obj);
obj.parentNode.removeChild(obj);
}
}

///------------------------------------------------------------------------------------------------------
var Class = {
create:
function() {
return function() { this.init.apply(this, arguments); }
}
}
var Drag = Class.create();
Drag.prototype
= {
init:
function(titleBar, dragDiv, Options) {
//设置点击是否透明,默认不透明
titleBar = Common.getItself(titleBar);
dragDiv
= Common.getItself(dragDiv);
this.dragArea = { maxLeft: 0, maxRight: Common.getViewportSize.w - dragDiv.offsetWidth - 2, maxTop: 0, maxBottom: Common.getViewportSize.h - dragDiv.offsetHeight - 2 };
if (Options) {
this.opacity = Options.opacity ? (isNaN(parseInt(Options.opacity)) ? 100 : parseInt(Options.opacity)) : 100;
this.keepOrigin = Options.keepOrigin ? ((Options.keepOrigin == true || Options.keepOrigin == false) ? Options.keepOrigin : false) : false;
if (this.keepOrigin) { this.opacity = 50; }
if (Options.area) {
if (Options.area.left && !isNaN(parseInt(Options.area.left))) { this.dragArea.maxLeft = Options.area.left };
if (Options.area.right && !isNaN(parseInt(Options.area.right))) { this.dragArea.maxRight = Options.area.right };
if (Options.area.top && !isNaN(parseInt(Options.area.top))) { this.dragArea.maxTop = Options.area.top };
if (Options.area.bottom && !isNaN(parseInt(Options.area.bottom))) { this.dragArea.maxBottom = Options.area.bottom };
}
}
else {
this.opacity = 100, this.keepOrigin = false;
}
this.originDragDiv = null;
this.tmpX = 0;
this.tmpY = 0;
this.moveable = false;

var dragObj = this;

titleBar.onmousedown
= function(e) {
var ev = e || window.event || Common.getEvent();
//只允许通过鼠标左键进行拖拽,IE鼠标左键为1 FireFox为0
if (Common.isIE && ev.button == 1 || !Common.isIE && ev.button == 0) {
}
else {
return false;
}

if (dragObj.keepOrigin) {
dragObj.originDragDiv
= document.createElement("div");
dragObj.originDragDiv.style.cssText
= dragDiv.style.cssText;
dragObj.originDragDiv.style.width
= dragDiv.offsetWidth;
dragObj.originDragDiv.style.height
= dragDiv.offsetHeight;
dragObj.originDragDiv.innerHTML
= dragDiv.innerHTML;
dragDiv.parentNode.appendChild(dragObj.originDragDiv);
}

dragObj.moveable
= true;
dragDiv.style.zIndex
= dragObj.GetZindex() + 1;
var downPos = Common.getMousePos(ev);
dragObj.tmpX
= downPos.x - dragDiv.offsetLeft;
dragObj.tmpY
= downPos.y - dragDiv.offsetTop;

titleBar.style.cursor
= "move";
if (Common.isIE) {
dragDiv.setCapture();
}
else {
window.captureEvents(Event.MOUSEMOVE);
}

dragObj.SetOpacity(dragDiv, dragObj.opacity);

//FireFox 去除容器内拖拽图片问题
if (ev.preventDefault) {
ev.preventDefault();
ev.stopPropagation();
}

document.onmousemove
= function(e) {
if (dragObj.moveable) {
var ev = e || window.event || Common.getEvent();
//IE 去除容器内拖拽图片问题
if (document.all) //IE
{
ev.returnValue
= false;
}

var movePos = Common.getMousePos(ev);
dragDiv.style.left
= Math.max(Math.min(movePos.x - dragObj.tmpX, dragObj.dragArea.maxRight), dragObj.dragArea.maxLeft) + "px";
dragDiv.style.top
= Math.max(Math.min(movePos.y - dragObj.tmpY, dragObj.dragArea.maxBottom), dragObj.dragArea.maxTop) + "px";

}
};

document.onmouseup
= function() {
if (dragObj.keepOrigin) {
if (Common.isIE) {
dragObj.originDragDiv.outerHTML
= "";
}
else {
Common.setOuterHtml(dragObj.originDragDiv,
"");
}
}
if (dragObj.moveable) {
if (Common.isIE) {
dragDiv.releaseCapture();
}
else {
window.releaseEvents(Event.MOUSEMOVE);
}
dragObj.SetOpacity(dragDiv,
100);
titleBar.style.cursor
= "default";
dragObj.moveable
= false;
dragObj.tmpX
= 0;
dragObj.tmpY
= 0;
}
};
}
},
SetOpacity:
function(dragDiv, n) {
if (Common.isIE) {
dragDiv.filters.alpha.opacity
= n;
}
else {
dragDiv.style.opacity
= n / 100;
}

},
GetZindex:
function() {
var maxZindex = 0;
var divs = document.getElementsByTagName("div");
for (z = 0; z < divs.length; z++) {
maxZindex
= Math.max(maxZindex, divs[z].style.zIndex);
}
return maxZindex;
}
}

window.onload
= function() {
new Drag("dragDiv", "dragDiv", { opacity: 100, keepOrigin: true }); //, area: { left: 50, right: 500, top: 100, bottom: 400}
}
  

</script>

</head>
<body>
<div id="dragDiv" style="position:absolute; background-color:#FFFFFF;border:solid 1px #849BCA;width:200px;left:10px;top:10px;filter:alpha(opacity=100);opacity:1;">
<table cellpadding="0" cellspacing="0" border="0" style="width:100%;border-collapse:collapse; ">
<tr id="titleBar" style="height:22px; text-align:left; background-color:#547BC9;color:White; padding:3px;">
<th align="left" unselectable="on" >Title</th>
</tr>
<tr style="height:130px;padding:3px;" align="left" valign="top" unselectable="on">
<td><img src="http://images.cnblogs.com/logo_small.gif" alt="pic for drag" /> Content...</td> <!---->
</tr>
</table>
</div>
<div style="position:absolute; font-family:Tahoma;border:solid 1px #849BCA; background-color:#AAAAAA;width:200px;height:100px;left:210px;top:210px;filter:alpha(opacity=100);opacity:1; z-index:999">Are you able to cover me?</div>
</body>
</html>

 

对Drag的使用:在window.onload中,必填参数是titleBar和dragDiv,后者是要拖拽的容器,前者是拖拽容器的可拖拽部位,譬如经常遇到的通过标题栏拖动整个DIV,则titleBar即为改标题栏。而{ opacity: 100, keepOrigin: true , area: { left: 50, right: 500, top: 100, bottom: 400}} 是可选参数,用于扩展功能,opacity设置透明度,keepOrigin设置拖拽过程中是否保留原来拖拽容器,area设置拖拽范围。

  1. 拖拽的基本原理:当mousedown时记下鼠标点击位置离拖拽容器左边沿的距离和上边沿的距离,即tmpX,tmpY;mousemove时通过定位拖拽容器的style.left/style.top,使拖拽容器进行移动,定位到哪里则由刚刚的tmpX/tmpY和当前鼠标所在位置计算得出;mouseup时,结束移动。
  2. “var dragObj = this;” 这句是为了在mousedown/mouseup/mousemove事件里对Drag对象的相关变量进行引用。因为在mousedown/mouseup/mousemove里的this是window.
  3. 当拖拽速度太快导致鼠标移出拖拽容器,而拖拽容器位置未变,用document.mousemove代替titleBar.mousemove即可。
  4. 设置拖拽容器可拖拽的范围,若未设置,则默认为当前窗口可视范围。Note:在设置范围的时候使用Math.max/min来处理,而不是用If语句判断,用后者的话会导致快速拖拽时未达到容许范围边沿即停止的状况。
  5. 当拖拽过程中,可设置是否保留原来拖拽容器,当拖拽结束,隐藏原来容器,默认不保留。
  6. 当拖拽时,可设置拖拽的容器是否透明及透明度多少,默认不透明。但若拖拽过程中设置保留原来拖拽容器,即keepOrigin: true,则设置透明度为50%。
  7. 使右键、鼠标中键等不能拖动,仅左键单击可以拖动。Note:IE鼠标左键为event.Button=1 FireFox为event.Button=0.
  8. 解决如果点击在图片上无法拖拽的问题:非常杯具的是IE通过ev.cancelBubble=true;ev.returnValue = false;来防止图片的事件,注意是放在document.onmousemove中,而FireFox通过ev.preventDefault();ev.stopPropagation(); 但是是放在titleBar的mousedown事件中。
  9. 有一种情况,当浏览器窗口不是最大化的时候,你希望当鼠标在浏览器外移动时,浏览器里的拖拽容器仍然移动,这时就要使用鼠标事件捕获,IE中相应的是dragDiv.setCapture();与dragDiv.releaseCapture(); FF中是window.captureEvents(Event.MOUSEMOVE);与window.releaseEvents(Event.MOUSEMOVE) 。
  10. 确保每次拖拽时拖拽容器的zindex都不会被其他块元素覆盖。

 

 

点击下载

转载于:https://www.cnblogs.com/ljchow/archive/2010/04/27/1721695.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/549248.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

操作系统进程调度算法图解(FCFS、轮转、SPN、SRT、HRRN、反馈)

版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。 本文链接&#xff1a;https://blog.csdn.net/woshiwanghao_hi/article/details/13004507 FCFS: 先来先服务&#xff0c;也可以称为先进先出 轮转…

安装Ubuntu之后一定要安装Docky

2019独角兽企业重金招聘Python工程师标准>>> 安装Ubuntu之后一定要安装Docky&#xff0c;然后把面板隐藏&#xff0c;真是太漂亮了&#xff01; 图片太大&#xff0c;传不上来&#xff0c;传到百度上&#xff0c;又不让引用&#xff0c;还是百度看吧&#xff1a; 我…

操作系统中调度算法(FCFS、RR、SPN、SRT、HRRN)

版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。 本文链接&#xff1a;https://blog.csdn.net/xieminyao123/article/details/79116985 决策模式 决策模式说明选择函数在执行的瞬间的处理方式&a…

操作系统学习总结(超赞!!!)

我是技术搬运工,好东西当然要和大家分享啦.原文地址 操作系统基本特征 1. 并发 并发性是指宏观上在一段时间内能同时运行多个程序&#xff0c;而并行性则指同一时刻能运行多个指令。 并行需要硬件支持&#xff0c;如多流水线或者多处理器。 操作系统通过引入进程和线程&#xf…

操作系统的SPOOLING技术

SPOOLING技术&#xff08;Simultaneous Peripheral Operating On Line) 同时联机外围操作技术&#xff0c;它是关于慢速字符设备如何与计算机主机进行数据交换的一种技术&#xff0c;通常又称假脱机技术。 在多道程序环境下&#xff0c;利用多道程序中的一道或者两道程序来模拟…

独立磁盘冗余阵列:RAID

版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。 本文链接&#xff1a;https://blog.csdn.net/fsx2550553488/article/details/79819164 RAID RAID&#xff1a;独立磁盘冗余阵列&#xff08;Redun…

task2 EDA数据分析

目标 了解&#xff0c;验证数据集 了解变量关系&#xff0c;与预测值之间关系 数据处理、特征工程 数据探索性分析 EDA探索性数据分析 通过EDA可实现: 1. 得到数据的直观表现 2. 发现潜在的结构 3. 提取重要的变量 4. 处理异常值 5. 检验统计假设 6. 建立初步…

task2 EDA探索性数据分析

1、赛题数据赛题以预测二手车的交易价格为任务&#xff0c;数据集报名后可见并可下载&#xff0c;该数据来自某交易平台的二手车交易记录&#xff0c;总数据量超过40w&#xff0c;包含31列变量信息&#xff0c;其中15列为匿名变量。为了保证比赛的公平性&#xff0c;将会从中抽…

2021-06-10

局部搜索算法是一种简单的贪心搜索算法&#xff0c;是解决最优化问题的一种启发式算法&#xff0c;该算法每次从当前解的临近解空间中根据启发函数选择一个最优解&#xff08;也不一定是最优解&#xff09;作为当前解&#xff0c;直到达到一个局部最优解。本文以求解八皇后问题…

.NET(C#) Internals: 以一个数组填充的例子初步了解.NET 4.0中的并行(二)

引言 随着CPU多核的普及&#xff0c;编程时充分利用这个特性越显重要。上篇首先用传统的嵌套循环进行数组填充&#xff0c;然后用.NET 4.0中的System.Threading.Tasks提供的Parallel Class来并行地进行填充&#xff0c;最后对比他们的性能。本文将深入分析Parallel Class并借机…

.net框架读书笔记---CLR内存管理\垃圾收集(二)

前几天学习了CLR垃圾收集原理和基本算法&#xff0c;但是那些是仅仅相对于托管堆而言的&#xff0c;任何非托管资源的类型&#xff0c;例如文件、网络资源等&#xff0c;都必须支持一种称为终止化&#xff08;finalization&#xff09;的操作。 终止化 终止化操作允许一种资源在…

重构手法——提炼函数、搬移函数、以多态取代条件表达式

目录我的心路历程我的学习概括Extract Method&#xff08;提炼函数&#xff09;动机*--做法动机--做法*Move Method&#xff08;搬移函数&#xff09;动机*--做法动机--做法*Replace Conditional with Polymorphism&#xff08;以多态取代条件表达式&#xff09;动机*--做法动机…

FTP服务器架设详细图解

FTP是File Transfer Protocol&#xff08;文件传输协议&#xff09;的缩写&#xff0c;用来在两台计算机之间互相传送文件。FTP服务作为Internet最古老的服务之一&#xff0c;无论在过去还是现在都有着不可替代的作用。在企业中&#xff0c;对于一些大文件的共享&#xff0c;通…

IP-tools

IP-tools 网管员的第三只眼^ Ip-tools是一款功能齐全的网管软件&#xff0c;可以随时随地的向网管员报告网络的运行情况ip-tools自身集成多种tcp/ip使用工具&#xff0c;如本地信息、链接信息、端口扫描、ping、WHOIS、finger、nslookup、telnet、NetBIOS等功能。界面是全英的&…

用git提交代码到远程仓库遇到的问题

目录我的学习过程git环境配置&#xff08;Mac版&#xff09;git原理图git的push操作思路遇到的问题我的学习过程 昨天重写了一遍聊天程序&#xff0c;准备提交到git上进行代码管理。结果遇到了不少问题。我照着网上的教程进行操作&#xff0c;一步一步踩了很多坑。 git环境配…

git pull和push整理和归纳

目录各个模块概念工作区版本库暂存区远程仓库pull和push流程相关的命令暂存区相关版本库相关远程仓库相关利用远程仓库协作开发各个模块概念 我的理解&#xff1a; Git是版本管理工具&#xff0c;它主要对指定目录下的一些特定的文件的修改进行版本管理。 相关的模块有&#x…

Linux中点号,星号,加号,问号实战

目录Linux中的星号&#xff0c;点号和加号概念我的学习过程&#xff1a;我的思考过程&#xff1a;点号&#xff08;.&#xff09;星号&#xff08;*&#xff09;加号&#xff08;&#xff09;问号&#xff08;?&#xff09;linux星号&#xff0c;点号&#xff0c;加号&#xf…

广播地址的计算方法(与运算、或运算)

目录我的学习过程Python中逻辑运算符notandor位运算符取反&#xff08;~&#xff09;与&#xff08;&&#xff09;或&#xff08;|&#xff09;广播地址计算方法IP地址子网掩码网络地址广播地址广播地址计算举例我的学习过程 今天学习UDP的单播、多播、广播中&#xff0c;…

Wt::WTreeNode

2019独角兽企业重金招聘Python工程师标准>>> A single node in a tree. 〔 这个 widget 渲染的是一棵树的一个节点。〕 A tree list is constructed by combining several tree node objects in a tree hierarchy, by passing the parent tree node as the last arg…