JavaScript实现鼠标框选与批量选择功能

作者:白露时间:2026-10-27 23:19:40浏览:255

本文介绍如何使用原生JavaScript实现鼠标拖动框选功能。通过监听鼠标事件计算可视区域,判断目标元素是否位于框内并应用选中样式。代码包含自定义选择器、事件绑定及坐标计算逻辑,适用于文件列表等需要批量操作的场景。

JavaScript实现鼠标框选与批量选择功能

具体实现代码如下:

<style><!--
body{padding-top:50px;padding-left:100px;padding-right:150px;}
.fileDiv{float:left;width:100px;height:100px;text-align:center;line-height:100px;font-size:12px;border:1px solid #cccccc;margin-right:10px;margin-bottom:10px;}
.seled{border:1px solid #ff0000;background-color:#D6DFF7;}
--></style>
<script type="text/javascript">// <![CDATA[
Array.prototype.remove = function( item ){
for( var i = 0 ; i < this.length ; i++ ){
if( item == this[i] )
break;
  }
if( i == this.length )
return;
for( var j = i ; j < this.length - 1 ; j++ ){
this[ j ] = this[ j + 1 ];
  }
this.length--;
  } 
String.prototype.replaceAll = function (AFindText,ARepText){ raRegExp = new RegExp(AFindText,"g"); return this.replace(raRegExp,ARepText;)}
function getAllChildren(e) {
return e.all ? e.all : e.getElementsByTagName('*');
}
document.getElementsBySelector = function(selector) {\n if (!document.getElementsByTagName) {\n return new Array();\n }\n var tokens = selector.split(' ');\n var currentContext = new Array(document);\n for (var i = 0; i < tokens.length; i++) {\n token = tokens[i].replace(/^\\s+/,'').replace(/\\s+$/,'');;\n if (token.indexOf('#') > -1) {\n var bits = token.split('#');\n var tagName = bits[0];\n var id = bits[1];\n var element = document.getElementById(id);\n if (tagName && element.nodeName.toLowerCase() != tagName) {\n return new Array();\n }\n currentContext = new Array(element);\n continue; \n }\n if (token.indexOf('.') > -1) {
var bits = token.split('.');\n var tagName = bits[0];\n var className = bits[1];\n if (!tagName) {\n tagName = '*';\n }
var found = new Array;\n var foundCount = 0;\n for (var h = 0; h < currentContext.length; h++) {\n var elements;\n if (tagName == '*') {\n elements = getAllChildren(currentContext[h]);\n } else {\n elements = currentContext[h].getElementsByTagName(tagName);\n }\n for (var j = 0; j < elements.length; j++) {\n found[foundCount++] = elements[j];\n }\n }\n currentContext = new Array;\n var currentContextIndex = 0;\n for (var k = 0; k < found.length; k++) {\n if (found[k].className && found[k].className.match(new RegExp('\\b'+className+'\\b'))) {\n currentContext[currentContextIndex++] = found[k];\n }\n }\n continue;\n }\n if (token.match(/^(\\w*)\\[(\\w+)([=~\\|\\^\\$\\*]?)=?"?([^\\]"]*)"?\\]$/)) {\n var tagName = RegExp.$1;\n var attrName = RegExp.$2;\n var attrOperator = RegExp.$3;\n var attrValue = RegExp.$4;\n if (!tagName) {\n tagName = '*';\n }\n var found = new Array;\n var foundCount = 0;\n for (var h = 0; h < currentContext.length; h++) {\n var elements;\n if (tagName == '*') {\n elements = getAllChildren(currentContext[h]);\n } else {\n elements = currentContext[h].getElementsByTagName(tagName);\n }\n for (var j = 0; j < elements.length; j++) {\n found[foundCount++] = elements[j];\n }\n }\n currentContext = new Array;\n var currentContextIndex = 0;\n var checkFunction; \n switch (attrOperator) {\n case '=':\n checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue); };\n break;\n case '~': \n checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('\\b'+attrValue+'\\b'))); };\n break;\n case '|':\n checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))); };\n break;\n case '^':\n checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0); };\n break;\n case '$': \n checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length); };\n break;\n case '*': \n checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1); };\n break;\n default :\n checkFunction = function(e) { return e.getAttribute(attrName); };\n }\n currentContext = new Array;\n var currentContextIndex = 0;\n for (var k = 0; k < found.length; k++) {\n if (checkFunction(found[k])) {\n currentContext[currentContextIndex++] = found[k];\n }\n }\n continue;\n }\n tagName = token;\n var found = new Array;\n var foundCount = 0;\n for (var h = 0; h < currentContext.length; h++) {\n var elements = currentContext[h].getElementsByTagName(tagName);\n for (var j = 0; j < elements.length; j++) {\n found[foundCount++] = elements[j];\n }\n }\n currentContext = found;\n }\n return currentContext;\n}\n\n function addEvent(eventType,eventFunc,eventObj){\n eventObj = eventObj || document;\n if(window.attachEvent) eventObj.attachEvent("on"+eventType,eventFunc);\n if(window.addEventListener) eventObj.addEventListener(eventType,eventFunc,false);\n }\nfunction clearEventBubble(evt){\n evt = evt || window.event;\n if (evt.stopPropagation) evt.stopPropagation(); else evt.cancelBubble = true; \n if (evt.preventDefault) evt.preventDefault(); else evt.returnValue = false;\n}\n\nfunction posXY(event){\n event = event || window.event;\n var posX = event.pageX || (event.clientX +\n (document.documentElement.scrollLeft || document.body.scrollLeft));\n var posY = event.pageY || (event.clientY +\n (document.documentElement.scrollTop || document.body.scrollTop));\n return {x:posX, y:posY};\n}
var _selectedRegions = [];\n function RegionSelect(selRegionProp){\n this.regions =[];\n var _regions = document.getElementsBySelector(selRegionProp["region"]);\n if(_regions && _regions.length > 0){\n var _self = this;\n for(var i=0; i< _regions.length;i++){\n _regions[i].onmousedown = function(){\n var evt = window.event || arguments[0];\n if(!evt.shiftKey && !evt.ctrlKey){\n // 清空所有select样式\n _self.clearSelections(_regions);\n this.className += " "+_self.selectedClass;\n // 清空selected数组,并加入当前select中的元素\n _selectedRegions = [];\n _selectedRegions.push(this);\n }else{\n if(this.className.indexOf(_self.selectedClass) == -1){\n this.className += " "+_self.selectedClass;\n _selectedRegions.push(this);\n }else{\n this.className = this.className.replaceAll(_self.selectedClass,"");\n _selectedRegions.remove(this);\n }\n }\n clearEventBubble(evt);\n }\n this.regions.push(_regions[i]);\n }\n }\n this.selectedClass = selRegionProp["selectedClass"];\n this.selectedRegion = [];\n this.selectDiv = null;\n this.startX = null;\n this.startY = null;\n }\n\n RegionSelect.prototype.select = function(){\n var _self = this;\n addEvent("mousedown",function(){\n var evt = window.event || arguments[0];\n _self.onBeforeSelect(evt);\n clearEventBubble(evt);\n },document);\n\n addEvent("mousemove",function(){\n var evt = window.event || arguments[0];\n _self.onSelect(evt);\n clearEventBubble(evt);\n },document);\n\n addEvent("mouseup",function(){\n _self.onEnd();\n },document);\n }\n\n RegionSelect.prototype.onBeforeSelect = function(evt){\n if(!document.getElementById("selContainer")){\n this.selectDiv = document.createElement("div");\n this.selectDiv.style.cssText = "position:absolute;width:0px;height:0px;font-size:0px;margin:0px;padding:0px;border:1px dashed #0099FF;background-color:#C3D5ED;z-index:1000;filter:alpha(opacity:60);opacity:0.6;display:none;";\n this.selectDiv.id = "selContainer";\n document.body.appendChild(this.selectDiv);\n }else{\n this.selectDiv = document.getElementById("selContainer");\n }\n\n this.startX = posXY(evt).x;\n this.startY = posXY(evt).y;\n this.isSelect = true;\n\n }\n\n RegionSelect.prototype.onSelect = function(evt){\n var _self = this;\n if(_self.isSelect){\n if(_self.selectDiv.style.display == "none") _self.selectDiv.style.display = "";\n\n var posX = posXY(evt).x;\n var poxY = posXY(evt).y;\n\n _self.selectDiv.style.left = Math.min(posX, this.startX);\n _self.selectDiv.style.top = Math.min(poxY, this.startY);\n _self.selectDiv.style.width = Math.abs(posX - this.startX);\n _self.selectDiv.style.height = Math.abs(poxY - this.startY); \n\n var regionList = _self.regions;\n for(var i=0; i< regionList.length; i++){\n var r = regionList[i], sr = _self.innerRegion(_self.selectDiv,r);\n if(sr && r.className.indexOf(_self.selectedClass) == -1){\n r.className = r.className + " "+_self.selectedClass; \n _selectedRegions.push(r);\n }else if(!sr && r.className.indexOf(_self.selectedClass) != -1){\n r.className = r.className.replaceAll(_self.selectedClass,"");\n _selectedRegions.remove(r);\n }\n\n }\n }\n }\n\n RegionSelect.prototype.onEnd = function(){\n if(this.selectDiv){\n this.selectDiv.style.display = "none"; \n }\n this.isSelect = false;\n //_selectedRegions = this.selectedRegion;\n }\n\n // 判断一个区域是否在选择区内\n RegionSelect.prototype.innerRegion = function(selDiv, region){\n var s_top = parseInt(selDiv.style.top);\n var s_left = parseInt(selDiv.style.left);\n var s_right = s_left + parseInt(selDiv.offsetWidth);\n var s_bottom = s_top + parseInt(selDiv.offsetHeight);\n\n var r_top = parseInt(region.offsetTop);\n var r_left = parseInt(region.offsetLeft);\n var r_right = r_left + parseInt(region.offsetWidth);\n var r_bottom = r_top + parseInt(region.offsetHeight);\n\n var t = Math.max(s_top, r_top);\n var r = Math.min(s_right, r_right);\n var b = Math.min(s_bottom, s_bottom);\n var l = Math.max(s_left, r_left);\n\n if (b > t+5 && r > l+5) {\n return region;\n } else {\n return null;\n }\n\n }\n\n RegionSelect.prototype.clearSelections = function(regions){\n for(var i=0; i<regions.length;i++){\n regions[i].className = regions[i].className.replaceAll(this.selectedClass,"");\n }\n }\n\n function getSelectedRegions(){\n return _selectedRegions;\n}
function showSelDiv(){\n var selInfo = "";\n var arr = getSelectedRegions();\n for(var i=0; i<arr.length;i++){\n selInfo += arr[i].innerHTML+"\n";\n }
alert("共选择 "+arr.length+" 个文件,分别是:\n"+selInfo);\n\n }\n// ]]></script>\n<p><button onclick="showSelDiv();">getRegions</button></p>\n<div class="fileDiv">file1</div>\n<div class="fileDiv">file2</div>\n<div class="fileDiv">file3</div>\n<div class="fileDiv">file4</div>\n<div class="fileDiv">file5</div>\n<div class="fileDiv">file6</div>\n<div class="fileDiv">file7</div>\n<div class="fileDiv">file8</div>\n<div style="float: left; width: 100%;"><button onclick="showSelDiv();">getRegions</button></div>\n<script type="text/javascript">// <![CDATA[\nnew RegionSelect({\n region:'div.fileDiv',\n selectedClass: 'seled'\n }).select();\n// ]]></script>
作者最新文章