动态获取输入框光标在页面中的位置! || 动态添加 style标签 || 获取元素样式 || 获取元素在页面中的位置
html
<!DOCTYPE html> <html> <head> <title>InputPostion</title> <script src="./getFocusPosition.js"></script> </head> <body> <textarea id="text" style="width: 340px; height: 210px;"></textarea> <button onclick=" getPosition() ">获取焦点</button> <script> function getPosition(){ let textareaNode = document.getElementById("text"); console.log("textarea焦点位置",getFocusPosition.getInputPositon(textareaNode)); } </script> </body> </html>
getFocusPosition.js
/** * getPositionApiObj 是获取输入框(textarea、input)的光标焦点位置的对象,里面包含各种api,其中getInputPositon方法会返回 光标的位置坐标 */ var getFocusPosition = { /** * 主方法 * 获取输入光标在页面中的坐标 * @param {HTMLElement} 输入框元素 * @return {Object} 返回left和top,bottom */ getInputPositon :function (elem) { if (document.selection) { //IE Support elem.focus(); var Sel = document.selection.createRange(); return { left: Sel.boundingLeft, top: Sel.boundingTop, bottom: Sel.boundingTop + Sel.boundingHeight }; } else {// 非IE Support var that = this; var cloneDiv ='{$clone_div}', cloneLeft ='{$cloneLeft}', cloneFocus ='{$cloneFocus}', cloneRight ='{$cloneRight}'; var none ='<span style="white-space:pre-wrap;"> </span>'; var div = elem[cloneDiv] || document.createElement('div'), //clone的div元素 focus = elem[cloneFocus] || document.createElement('span');//clone的span元素 var text = elem[cloneLeft] || document.createElement('span');//clone的span元素 var offset = that._offset(elem), index = this._getFocus(elem), //获取到textarea或input的光标所在的索引 focusOffset = { left: 0, top: 0 }; if (!elem[cloneDiv]) { elem[cloneDiv] = div; elem[cloneFocus] = focus; elem[cloneLeft] = text; div.appendChild(text); div.appendChild(focus); document.body.appendChild(div); focus.innerHTML ='|'; focus.style.cssText ='display:inline-block;width:0px;overflow:hidden;z-index:-100;word-wrap:break-word;word-break:break-all;'; div.className =this._cloneStyle(elem); div.style.cssText ='visibility:hidden;display:inline-block;position:absolute;z-index:-100;word-wrap:break-word;word-break:break-all;overflow:hidden;'; }; div.style.left = this._offset(elem).left +"px"; div.style.top = this._offset(elem).top +"px"; var strTmp = elem.value.substring(0, index).replace(/</g, '<').replace(/>/g, '>').replace(/\n/g, '<br/>').replace(/\s/g, none); text.innerHTML = strTmp; focus.style.display ='inline-block'; try { focusOffset = this._offset(focus); } catch (e) { }; focus.style.display ='none'; return { left: focusOffset.left, top: focusOffset.top, bottom: focusOffset.bottom }; } }, /** *获取光标在文本域或输入框的光标所在的位置(这里的位置是光标在第几个字符串的索引)对获取光标位置有辅助作用 *@param {HTMLElement} 输入框元素 */ _getFocus:function(elem) { var index =0; if (document.selection) {// IE Support console.log("支持"); elem.focus(); var Sel = document.selection.createRange(); if (elem.nodeName ==='TEXTAREA') {//textarea var Sel2 = Sel.duplicate(); Sel2.moveToElementText(elem); var index =-1; while (Sel2.inRange(Sel)) { Sel2.moveStart('character'); index++; }; }else if (elem.nodeName ==='INPUT') {// input Sel.moveStart('character', -elem.value.length); index = Sel.text.length; } }else if (elem.selectionStart || elem.selectionStart =='0') { // Firefox support index = elem.selectionStart; } return (index); }, /** *获取元素在页面中位置 *@param {HTMLElement} 输入框元素 */ _offset:function (elem) { var box = elem.getBoundingClientRect(), doc = elem.ownerDocument, body = doc.body, docElem = doc.documentElement; var clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0; var top = box.top + (self.pageYOffset || docElem.scrollTop) - clientTop, left = box.left + (self.pageXOffset || docElem.scrollLeft) - clientLeft; return { left: left, top: top, right: left + box.width, bottom: top + box.height }; }, // 克隆元素样式并返回类 _cloneStyle: function (elem, cache) { if (!cache && elem['${cloneName}']) return elem['${cloneName}']; var className, name, rstyle =/^(number|string)$/; var rname =/^(content|outline|outlineWidth)$/; //Opera: content; IE8:outline && outlineWidth var cssText = [], sStyle = elem.style; for (name in sStyle) { if (!rname.test(name)) { var val; val =this._getStyle(elem, name); if (val !==''&& rstyle.test(typeof val)) { // Firefox 4 name = name.replace(/([A-Z])/g, "-$1").toLowerCase(); cssText.push(name); cssText.push(':'); cssText.push(val); cssText.push(';'); }; }; }; cssText = cssText.join(''); elem['${cloneName}'] = className ='clone'+ (new Date).getTime(); this._addHeadStyle('.'+ className +'{'+ cssText +'}'); return className; }, // 获取元素某个属性样式值 _getStyle: 'getComputedStyle'in window ? function (elem, name) { return getComputedStyle(elem, null)[name]; } : function (elem, name) { return elem.currentStyle[name]; }, // 动态插入style标签(样式) _addHeadStyle: function (content) { var style =this._style[document]; if (!style) { style =this._style[document] = document.createElement('style'); document.getElementsByTagName('head')[0].appendChild(style); }; style.styleSheet && (style.styleSheet.cssText += content) || style.appendChild(document.createTextNode(content)); }, _style: {}, }
效果:
原理是,动态创建一个div,克隆输入框的所有样式,往div内动态添加两个span元素,span(text)里面装输入框里的文字,span(模仿光标),这两个元素都设置为行内块元素,然后只需要获取到span(模拟光标)在页面中的位置,就是光标所在的位置。
。