再谈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,一经查实,立即删除!

相关文章

2019 CCPC - 网络选拔赛 A题^^

一个多月前打的&#xff0c;但是由于一点事情一直没写关于A题的反思&#xff0c;今天有空果断补上: Problem Description Bit operation is a common computing method in computer science ,Now we have two positive integers A and B ,Please find a positive integer C th…

用户态和核心态的转换

用户态和内核态的转换 1&#xff09;用户态切换到内核态的3种方式 a. 系统调用 这是用户态进程主动要求切换到内核态的一种方式&#xff0c;用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作&#xff0c;比如前例中fork()实际上就是执行了一个创建新进程的系统调…

华为防火墙Edumon1000E配置

华为防火墙Edumon1000E&#xff0c;配置有四个光电互斥接口&#xff0c;为千兆状态防火墙。默认情况下所有区域之间不允许有流量经过。本文为Edumon1000E的基本配置&#xff0c;该基本配置适用一般企业级单机接入情况。配置一台防火墙主要包含以下几个步骤&#xff1a;1、配置端…

操作系统进程调度算法图解(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…

Eclipse安装

1.下载Eclipse及其语言包 打开http://www.eclipse.org/downloads/&#xff0c;下载相应的文件。如下载Eclipse Classic版 打开http://www.eclipse.org/babel/下载相应语言包 2.安装Eclipse Eclipse直接解压&#xff0c;语言包直接解压后覆盖Eclipse解压出来的文件夹中的同名文件…

操作系统的SPOOLING技术

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

每日学习记录5.5

今天把帝国cms的sitmap问题解决了&#xff0c;通过实际操作&#xff0c;感觉对网页前台布局还是有了一定的了解。今天的学习是继续进行DIVCSS的初步学习。以适合公司网站改版。同时从今天起的学习期间&#xff0c;保证一天一篇至少50字的流水账。近日准备发表博客&#xff1a;“…

独立磁盘冗余阵列:RAID

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

使用south实现Django的数据库升级迁移

Technorati 标签: django,south,数据库迁移Ruby有牛哄哄的Rails Migration实现数据的升级和迁移&#xff0c;django呢&#xff1f; 有south。 已有的应用要支持south&#xff08;开发版&#xff09; 编辑settings.py , 把 ‘south’ 放到INSTALLED_APPS 中 manage.py syncdb 把…

task2 EDA数据分析

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

lua中文教程(第一章 起点)

一 全局变量 全局变量不需要声明&#xff0c;给一个变量赋值后即创建了这个全局变量&#xff0c;访问一个没有初始化的全局变量也不会出错&#xff0c;只不过得到的结果是:nil 如果想删除一个全局变量&#xff0c;只需要将变量赋值为nil 二 词法约定 1 标识符&#xff1a;字母或…

task2 EDA探索性数据分析

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

Liaoning Province--保三成功

现在做什么事情怎么都有遗憾&#xff0c;从小到大&#xff0c;每件事情都有遗憾...... 周六&#xff0c;在东电宾馆报道的&#xff0c;刚进宾馆&#xff0c;接待人员对我说有个人认识你&#xff0c;我诧异&#xff0c;看到后我挨个想&#xff0c;我想出来他是天之痕了&#xff…

2021-06-10

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

用JavaScript嵌入你的SWF

用JavaScript嵌入你的SWFswfobject.embedSWF(swfUrl, id, width, height, version, expressInstallSwfurl, flashvars, params, attributes)有5个必须的参数和4个可选的参数&#xff1a;swfUrl&#xff08;String&#xff0c;必须的&#xff09;指定SWF的URL。 id&#xff08;S…

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

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

Ghost安装之后,键盘出现字符出现乱码

今天我安装了G版本的WinServer2003,安装完成之后键盘打字出现乱字符,后来终于发现原来我的输入法模式为数字模式,按FN&#xff0b;insert可以切换回来,问题就解决了.转载于:https://blog.51cto.com/yaojian/314847