JavaScript獲取文本框光標的像素位置


【簡介】本文主要實現獲取textarea和input光標的像素位置,即光標的offsetLeft與offsetTop。可實現如下效果:

首先說明一下,在網上搜到的很多代碼是如何獲取輸入光標位置的如下代碼是如何獲取光標的的字符位置,如對於串“He|llo World!”返回的是光標|前的字符數2,並不是光標在頁面上的像素位置。當然,這段代碼對於獲取光標的像素位置能起到一定的輔助作用。

複製代碼
// 獲取光標在文本框的位置
function _getFocus(elem) {
var index = 0;
if (document.selection) {// IE Support
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);
}
複製代碼

對於IE瀏覽器,通過下面的代碼1實現起來比較方便。
複製代碼
//代碼1
if (document.selection) {
elem.focus();
var Sel = document.selection.createRange();
return {
left: Sel.boundingLeft,
top: Sel.boundingTop,
bottom: Sel.boundingTop
+ Sel.boundingHeight
};
}
複製代碼

而對於firefox之類的瀏覽器則通過模擬來實現,如下圖所示。首先通過拷貝輸入區域的樣式到一個div層(clone層),然後在此clone層之中的text子層添加光標之前的字符,並在text子層之後添加focus層,focus層中包含字符“|”來模擬光標,進而通過獲取focus層的偏移量即可獲得文本光標的像素座標位置。

具體實現代碼如下:

複製代碼
var kingwolfofsky = {
/**
* 獲取輸入光標在頁面中的座標
* @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 {
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'), focus = elem[cloneFocus] || document.createElement('span');
var text = elem[cloneLeft] || document.createElement('span');
var offset = that._offset(elem), index = this._getFocus(elem), 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
};
}
},

// 克隆元素樣式並返回類
_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)) {
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;
},

// 向頁頭插入樣式
_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: {},

// 獲取最終樣式
_getStyle: 'getComputedStyle' in window ? function (elem, name) {
return getComputedStyle(elem, null)[name];
} :
function (elem, name) {
return elem.currentStyle[name];
},

// 獲取光標在文本框的位置
_getFocus: function (elem) {
var index = 0;
if (document.selection) {// IE Support
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);
},

// 獲取元素在頁面中位置
_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
};
}
};

function getPosition(ctrl) {
var p = kingwolfofsky.getInputPositon(ctrl);
document.getElementById(
'show').style.left = p.left + "px";
document.getElementById(
'show').style.top = p.bottom + "px";
}
複製代碼
測試頁面如下:
複製代碼
<!DOCTYPE html>
<html>
<head>
<title>InputPostion</title>
<script type="text/javascript" src="kingwolfofsky.js""></script>
<script type="text/javascript">
function show(elem) {
var p = kingwolfofsky.getInputPositon(elem);
var s = document.getElementById('show');
s.style.top
= p.bottom+'px';
s.style.left
= p.left + 'px';
s.style.display
= 'inherit';
}
</script>
</head>
<body>
<textarea id="text" onkeyup="show(this)" style="width: 340px; height: 210px;"></textarea>
<br />
<input type="text" onkeyup="show(this)" style="width: 340px;" />
<div id="show" style="width: 34px; height: 13px; background: #eee; position: absolute;border:1px solid grey;font-size:13px; display:none;">Tips</div>
</body>
</html>
複製代碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章