javascript实现模拟鼠标拖动元素(下)
在javascript实现模拟鼠标拖动元素(上)一文中,我凑巧让dispatch函数在html文件中生效了,本想将该函数用在chrome插件中,但因为个人js基本知识务必匮乏导致未使用成功。经过多天的查阅资料与学习,终于成功在chrome插件中使用dispatch函数,在此记录下来。
chrome插件中使用dispatchEvent验证方案
这里采用chrome插件控制本地html文件(new.html)中的元素来验证这个问题,html文件中包含一个绿色的正方形,且包含mouseup, mousedown, mousemove等处理函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
<!DOCTYPE html> <html> <head> <title>draggable div</title> <style type="text/css"> body{ margin: 0; padding: 0; background-color: #fff; } #drag_div{ width: 150px; height: 150px; padding: 10px; margin: 10px; background-color: #66dd33; cursor: move; } </style> </head> </html> <body> <div id="drag_div"></div> </body> <script type="text/javascript"> function Drag () { this.initialize.apply(this, arguments); } Drag.prototype = { // 初始化 initialize : function (element, options) { this.element = this.$(element); // 被拖动的对象 this._x = this._y = 0; // 鼠标在元素中的位置 this._moveDrag = this.bind(this, this.moveDrag); this._stopDrag = this.bind(this, this.stopDrag); // 设置参数 this.setOptions(options); // 设置鼠标去“拖”的“柄”对象(注意与被拖动的对象区别) this.handle = this.$(this.options.handle); // 设置回调函数 this.onStart = this.$(this.options.onStart); this.onMove = this.$(this.options.onMove); this.onStop = this.$(this.options.onStop); this.handle.style.cursor = "move"; this.changeLayout(); // 注册开始拖动事件 this.addHandler(this.handle, "mousedown", this.bind(this, this.startDrag)); }, // 改变被拖动对象的布局属性 changeLayout: function () { this.element.style.top = this.element.offsetTop + "px"; this.element.style.left = this.element.offsetLeft + "px"; this.element.style.position = "absolute"; this.element.style.margin = "0"; }, startDrag : function (event) { var event = event || window.event; this._x = event.clientX - this.element.offsetLeft; this._y = event.clientY - this.element.offsetTop; this.addHandler(document, "mousemove", this._moveDrag); this.addHandler(document, "mouseup", this._stopDrag); this.preventDefault(event); this.handle.setCapture && this.handle.setCapture(); this.onStart(); }, moveDrag : function (event) { var event = this.getEvent(event); if(!event.isTrusted) { var iTop = event.clientY - this._y; var iLeft = event.clientX - this._x; this.element.style.top = iTop + "px"; this.element.style.left = iLeft + "px"; this.onMove(); } }, stopDrag : function () { this.removeHandler(document, "mousemove", this._moveDrag); this.removeHandler(document, "mouseup", this._stopDrag); this.handle.releaseCapture && this.handle.releaseCapture(); this.onStop(); }, setOptions : function (options) { this.options = { handle: this.element, //事件对象 onStart : function () {}, // 开始时回调函数 onMove : function(){}, // 拖拽时回调函数 onStop : function(){} // 停止时回调函数 }; for(var p in options){ this.options[p] = options[p]; } }, $ : function (id) { return typeof id === "string" ? document.getElementById(id):id; }, addHandler : function (element, eventType, handler) { if(element.addEventListener){ return element.addEventListener(eventType, handler, false); }else{ return element.attachEvent("on"+eventType, handler); } }, removeHandler : function (element, eventType, handler) { if(element.removeEventListener){ return element.removeEventListener(eventType, handler, false); }else{ return element.detachEvent("on" + eventType, handler); } }, getEvent: function (event) { return event || window.event; }, preventDefault: function (event) { if(event.preventDefault){ event.preventDefault(); }else{ event.returnValue = false; } }, bind : function (obj, handler) { return function () { return handler.apply(obj, arguments); } } }; window.onload = function () { var drag_div = document.getElementById("drag_div"); var drag = new Drag(drag_div, {handle: drag_div}); var evObj = new Event('mousedown'); drag_div.dispatchEvent(evObj); } </script> </html> |
在
chrome插件界面中填写好指定坐标后,按下GO。chrome插件会开启new.html文件,向该html文件中注入js代码,该js代码会先触发
mousedown事件,此事件会让html文件中的mousedown函数执行,然后会触发mousemove事件,该事件会将元素的目标位置传递至
html文件的mousemove函数中,最终实现将正方形移动至指定坐标。
验证此功能的源代码可以在这里下载。现在默认状态下,new.html放在D盘根目录下,插件要操作本地电脑中的文件,需要在manifeston.json中给相应的权限。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
{ "manifest_version": 2, "name": "Tao Bao Seckill", "version": "0.1", "background": { "persistent": false, "scripts": ["jquery.js","background.js"] }, "content_scripts": [{ "matches": ["file:///D:/*","http://*.taobao.com/*" , "https://*.taobao.com/*" , "http://*.tmall.com/*" , "https://*.tmall.com/*"], "js": ["jquery.js"] , "run_at" : "document_start" }], "browser_action": { "default_title": "Tao Bao Seckill" , "default_icon": "icon.png", "default_popup": "popup.html" }, "permissions": [ "tabs" , "cookies" , "notifications", "storage", "http://*/*" , "https://*/*" , "file:///D:/*/*"/////////////////给插件访问D盘的权限 ] }<span style="font-family:Microsoft YaHei;font-size:14px;line-height:2;"></span> |
在《javascript实现模拟鼠标拖动元素(上)》diapatch调用失败的原因
在tb登录界面中,有多个元素。在chrome浏览器中,按下F12,在Console界面中手动分别获取这些元素并触发这些元素的mouseevent事件,会发现一部分元素会报错,而另一部分则不会报错。而我之前在插件中操作的正好是会报错的元素,于是我以为是因为chrome插件injectjs无法使用dispatch函数,实际上并不是不能使用,而是浏览器判断该元素为未定义的元素,因此报错。
那么dispatch是否能移动tb拖动元素呢?不能。
在学习过程中,我发现mouseevent有一个只读属性,IsTrusted,该属性可以区分当前的鼠标事件是由dispatch触发或是非dispatch触发。我在chrome的console控制台中手动输入相关代码尝试移动拖动元素,console未报错但也浏览器未执行移动。在我们常用的百度搜索中,如果我们双击搜索内容,该内容会被选中,我在console中用dispatch对输入框触发鼠标双击动作,内容并未被选中。
作为一个js入门者,需要学习更多的知识和更多的实践来弄懂这些东西。