js综合练习(原生js的拖拽)

来源:互联网 发布:免费收款收据打印软件 编辑:程序博客网 时间:2024/06/08 06:08

原生表格的拖拽

参考书目:《JavaScript高级程序设计》


一、效果图




二、代码

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <title>dropTab.html</title>    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">    <meta http-equiv="description" content="this is my page">    <meta http-equiv="content-type" content="text/html; charset=UTF-8">        <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->    <style type="text/css">    table{    border:1px solid black;    cellpadding:0px;    cellmargin:0px;    cellspacing:10px;    align:center;    width:50%;    padding:0px;    border-collapse:collapse;    }    th{     background:gray;    text-align:center;    font-size:20px;    font-weight:800px;    font-family:"微软雅黑";    }    .td,td{    background:gray;    text-align:center;    font-size:15px;    font-weight:400px;    font-family:"微软雅黑";    padding:0px;    margin:0px;    border:1px solid #000;    }        tr{    padding:0px;    margin:0px    }        </style>  </head>    <body>    <table>    <tr><th colspan="4">拖动表 N.1</th></tr>    <tr>    <td>赵</td>    <td>钱</td>    <td>孙</td>    <td>李</td>    </tr>    <tr>    <td>周</td>    <td>吴</td>    <td>郑</td>    <td>王</td>    </tr>    </table>        <table style="margin:10 0;">    <tr><th colspan="4">拖动表 No.2</th></tr>    <tr>    <td>疯</td>    <td>成</td>    <td>五</td>    <td>味</td>    </tr>    <tr>    <td>奖</td>    <td>省</td>    <td>喊</td>    <td>羊</td>    </tr>    </table>    <script type="text/javascript">    //初始化变量    var start_drag = false;    var dragDiv_id = "dragDiv";    var dragDiv_color = "pink";    var over_color = "#0F0";    var normal_color = "gray";    var begin_color = "#F00";    var begin_comp;    var dragDiv = document.createElement("div");    dragDiv.id = dragDiv_id;    dragDiv.className = "td";    dragDiv.style.border = "1px solid black";    dragDiv.style.position = "absolute"    dragDiv.style.display = "none";    document.body.appendChild(dragDiv);//    if(document.all){//ie独有属性//    return window.event;//    }/*** 获取Event:* document.all获取所有元素 IE专属,所以一般用来判断是否IE*fn.caller:获取本方法的调用方法。即有个方法调用了当前方法,找到当前方法的上层方法*obj.constructor:有点类似于通过实例,获取构造该实例的对象***/function getEvent(){if(document.all){return window.event;}func = getEvent.caller;while(func != null){arg0 = func.arguments[0];if(arg0){if (arg0.constructor == Event || arg0.constructor == MouseEvent) {return arg0;}}func = func.caller;}return null;}/*** 展示过度元素*****/function showDiv(){var event = getEvent();var obj = event.srcElement ? event.srcElement: event.target;begin_comp = obj;//obj.style.background = "#F00";if(obj.tagName.toLowerCase() != "td"){return;}//obj.style.background = begin_color;var dragDiv = document.getElementById(dragDiv_id);var pos = getPosition(obj);//设置宽高 dragDiv.style.width = obj.offsetWidth;dragDiv.style.height = obj.offsetHeight;dragTop = pos[0];dragLeft = pos[1];dragX = event.clientX;dragY = event.clientY;dragDiv.style.top = pos[0];dragDiv.style.left = pos[1];dragDiv.style.display = "";dragDiv.style.cursor = "hand";dragDiv.style.background = "lavender";dragDiv.innerHTML = obj.innerHTML;start_drag = true;}/*** 隐藏过度元素****/function hidDiv(){start_drag = false;var dragDiv = document.getElementById(dragDiv_id);dragDiv.style.cursor = "";dragDiv.style.display = "none";var text = dragDiv.innerHTML;dragDiv.innerHTML = "";var mouseX = event.x || event.pageX;var mouseY = event.y || event.pageY;var tabs = document.getElementsByTagName("table");for(var t = 0;t < tabs.length; t++){//tabs有多少列var rowsLength = tabs[t].rows.length;for(var i = 0 ; i < rowsLength ; i++ ) {var cellLength = tabs[t].rows[i].cells.length;for(var j = 0 ; j < cellLength ; j++) {var cell = tabs[t].rows[i].cells[j];if( cell.tagName.toLowerCase() == "td" ){var pos = getPosition(cell);//判断在当前鼠标在哪一个cell中  如果在,换成绿色   否则还原回去if((mouseX > pos[1] && mouseX < ( pos[1] + cell.offsetWidth )) && (mouseY > pos[0] && mouseY < ( pos[0] + cell.offsetHeight ))) {cell.style.background = normal_color;begin_comp.innerHTML = cell.innerHTML;cell.innerHTML = text;} }}}}}/*** 拖动结束****/function dragOver(){hidDiv();}//按下鼠标document.getElementsByTagName("table")[0].onmousedown = function() {showDiv();}
<span style="white-space:pre"></span><pre name="code" class="html"><span style="white-space:pre"></span>//移动鼠标onmousemovedocument.onmousemove = function(){dragCell();}
//释放鼠标document.getElementById(dragDiv_id).onmouseup = function() {if(!start_drag){return ;}dragOver();//被拖动的内容//var event = getEvent();//var obj = event.srcElement ? event.srcElement : event.target ;//ie某些版本识别不了argument[0]//var text = begin_comp.innerHTML;//alert(obj.innerHTML);//alert(text);//begin_comp.innerHTML = "111";//obj.innerHTML = text;}/*** 获取事件对象的绝对位置****/function getPosition(obj){var pos = new Array();pos[0] = obj.offsetTop;pos[1] = obj.offsetLeft;while(obj = obj.offsetParent) {pos[0] += obj.offsetTop;pos[1] += obj.offsetLeft;}return pos;}/***  移动***/function dragCell(){var event = getEvent();var obj = event.srcElement ? event.srcElement : event.target;//事件的启动对象if(!start_drag){return ;}//过渡元素的位置var dragDivX = event.clientY - dragY + dragTop;var dragDivY = event.clientX - dragX + dragLeft;//获取过渡元素var dragDiv = document.getElementById(dragDiv_id);dragDiv.style.top = dragDivX;dragDiv.style.left = dragDivY;var mouseX = event.x || event.pageX;var mouseY = event.y || event.pageY;//鼠标位置,换颜色var tabs = document.getElementsByTagName("table");for(var t = 0;t < tabs.length; t++){//tabs有多少列var rowsLength = tabs[t].rows.length;for(var i = 0 ; i < rowsLength ; i++ ) {var cellLength = tabs[t].rows[i].cells.length;for(var j = 0 ; j < cellLength ; j++) {var cell = tabs[t].rows[i].cells[j];if( cell.tagName.toLowerCase() == "td" ){var pos = getPosition(cell);//判断在当前鼠标在哪一个cell中  如果在,换成绿色   否则还原回去if((mouseX > pos[1] && mouseX < ( pos[1] + cell.offsetWidth )) && (mouseY > pos[0] && mouseY < ( pos[0] + cell.offsetHeight ))) {cell.style.background = over_color;}else {cell.style.background = normal_color;} }}}}}    </script>      </body></html>

三、css

table标签一定要有border-collapse:collapse;否则cell之间有白色边线去不掉,之前总以为是padding或者border。

四、JS

功能逻辑

1、创建过渡层dragDiv并拼接到dom中。注意:定位请设置为absolute;
2、第一个表格鼠标按下事件document.getElementsByTagName("table")[0].onmousedown。鼠标按下时,我希望能显示出过渡层,所以引用showDiv()。showDiv有显示过渡层dragDiv、与所点击的单元格相重合的效果。
3、鼠标移动document.onmousemove。我希望在页面中任意移动,并且移动到对应的cell换成绿色。所以事件的目标应该是document,调用dragCell()。dragCell()应该拥有变换过渡层(dragDiv)与变换cell底色的效果。
4、鼠标释放document.getElementById(dragDiv_id).onmouseup 由于过渡层随着鼠标移动,所以目标元素应该是过渡层。这个事件调用dragOver(),我希望能隐藏过渡层,且交换cell的数据。

细节逻辑

1、getEvent():获取事件对象有跨浏览器问题。比如在IE中,事件对象获取方式为window.event;而在FF用Argument对象获取。
Argument对象:js中的Argument对象与java中method(String... arg)相类似,无论你调用方法传了多少参数,都将保存至Argument对象。在事件处理方法中第一个参数是event,方法中没有传递,event也会自动传递到第一个参数位置。所以可以用argument[0]获取event
argument.callee 返回调用该语句的方法(感觉可用于递归与调用匿名方法)。
argument.caller 返回调用本方法的方法(方法嵌套中,上溯外层方法)
argument.constructor 返回当前对象的构造类型
2、跨浏览器获取目标事件:event.srcElement ? event.srcElement: event.target;  在IE中获取方式是event,srcElement ,event.target功能与之一样。
3、obj.tagName.toLowerCase()
4、设置过渡层的尺寸:我希望其尺寸与目标元素的尺寸一致,dragDiv.style.width = obj.offsetWidth;dragDiv.style.height = obj.offsetHeight;
5、设置过渡层的位置getPosition():obj.offsetTop获取的是相对父级元素的位置。obj.offsetParent获取父级元素。一次次迭代下去,位置累加可得绝对位置。
6、保存鼠标按下的位置dragX,dragY用以计算鼠标移动时过渡层的位置。因为过渡层显示后,鼠标一切动作都将在过渡层上发生,所以调用2的语句获取不了初始目标元素。
7、跨浏览器鼠标位置var mouseX = event.x || event.pageX;var mouseY = event.y || event.pageY;
8、拖动时判断鼠标指向哪个cell:我希望是只有cell才有相应效果,所以获取页面table标签document.getElementsByTagName("table");循环table中,循环row,每个row再循环cell;判断鼠标知否在cell上,在的话cell背景色为绿色,不在的话还原回去。
9、hidDiv()隐藏过度层:交换拖动的cell与放置的cell内容,即交换两者之间的innerHTML

补充

1.鼠标的三种位置(鼠标事件对象)
screeX :相对于电脑屏幕的位置
clientX:相对于浏览器的位置(可计算滚动距离)
pageX :相对于浏览器的位置(非滚动)
offsetX:相对于触发事件构建的鼠标位置
通常是event调用
 
2.相对位移的属性(非鼠标事件对象)
offsetWight;当前构建的宽度
offsetTop:当前构建在父容器的相对位置
offsetParent:当前构建的父构建
3.事件冒泡
ie的事件流叫做事件冒泡,即事件发生最小的单位,,然后再逐层递进上去
比如你敲到桌面,最小可算做桌面事件,上升上去可作为房屋的一个事件。
4.dom事件
dom几个版本
dom0:非W3C规定的
dom1:专注于xml和html(开始由w3c规定)
dom2:对dom1增加了样式表模型
dom3:对dom2增加了内容模型和文档验证(DTD、Schemas)
dom事件
dom0事件处理程序:将值赋给事件处理程序  document.onmousemove = function(){}
dom2指定事件处理程序或者删除事件处理程序(据说,在不用事件处理程序的时候要把事件处理程序删除,,优化程序)addEventListener()和removeEventListenner();三个参数: arg0:事件,arg1:处理程序,arg3:true为捕获截断触发事件处理函数   false为在事件冒泡的时候处理
attachEvent(Etype,fn),detachEvent()-------只支持IE
5.event对象有如下常用属性
bubbler 冒泡(false)        
cancelabler 是否可取消事件默认行为
currentTagetElement 事件处理程序正在处理事件的对象(监听者元素,因为你可能点击那个元素没有监听鼠标点击事件,但它父类监听了,所以指向父类。)
defaultPreventedtrue表示已调用了preventDefault
detail r 与事件相关的细节信息(这个属性比较忧伤,似乎创建自定义事件时用到)
eventPhaser 调用事件处理程序的阶段1.捕获,2.目标,3.冒泡
preventDefault()禁事件默认行为 ,defaultPrevented为false时生效
stopImmediatePropagation() 取消事件进一步捕获或冒泡,同时组织任何事件处理程序被调用(dom3)
stopPropagation()与上同,但是只在bubble为true时可执行
targetr 事件对象
type
viewr 事件相关的抽象视图。
6.跨浏览器对象EventUtil
addHandler : function (element,type,handler){
if(element.addEventListener){
element.addEventListener(type,handler,false);
}else if (element.attachEvent){
element.attachEvent("on"+type , handler);
}else {
element["on" + type] =handler;//这个代码有点意思,据说遍历内部元素可以用“.”--person.name;也可以用“[]”如person[name] ..有效解决了拼凑属性无法访问的弊端
}
},
removeHandler:...
getEvent : function(event){
return event ? event : window.event;
},
getTarget: function(event){
return event.target || event.srcElement;
},
preventDefault: function(event){
if(event.preventDefault){
event.preventDefault();
}else {
event.returnValue = false;
}
},
stoppagation: function(event){
if(event.stopPropagation){
event.stopPropagation();}
}else {
event.cancelBubble = true;
}



0 0