js获取光标位置

news/2024/7/19 16:32:34 标签: js, 获取光标, 设置光标, Selection, Range

js获取光标位置">js获取光标位置

1.概念和原理

DOM中并没有直接获取光标位置的方法,那么我们只能间接来获取光标位置。DOM支持获取光标选中的范围,我们可以以此为切入点,来获取或定位光标的位置。当选取范围起始点和结束点一样时,就是光标插入的位置。

1.1 术语

anchor(瞄点):选区起点。

focus(焦点):选区终点。

range(范围):选区范围,包含整个节点或节点的一部分。

1.2 Selection

Selection:Selection对象表示用户选择的文本范围或插入符号的位置。

经过实验发现Selection选取的节点范围都是块级节点。input和texteare并不能作为Selection的节点

Selection对象存在于window对象上,可以通过window.getSelection()获取示例。

属性:

anchorNode:选区起点的节点。

anchorOffset:选区的起点位置。

focusNode:选区终点的节点。

focusOffset:选区的终点位置。

isCollapsed:起点和终点是否重叠。

rangeCount:选区包含的range数目。

方法

getRangeAt(index):获取指定的选取范围。

addRange(range):将一个范围添加到Selection对象中。

removeRange():移出指定的范围。

removeAllRanges():移出所有range对象。

collapse(parentNode,offset):将光标移动到parentNode节点的offset位置。

collapseToStart():取消当前选区,并把光标定位在原选区的最开始处,如果此时光标所处的位置是可编辑的,且它获得了焦点,则光标会在原地闪烁。

collapseToEnd():取消当前选区,并将光标定位到原选取的最末位。如果此时光标所处的位置是可编辑的,且它获得了焦点,则光标会在原地闪烁。

extend(node,offset):将终点位置移动到node节点的offset位置。

modify(alter,direction,granularity):通过alter方式(move/extend)来改变光标位置,移动方向为direction(left/right),移动单位为granularity

containsNode(aNode,aPartlyContained):判断aNode是否包含在Selection中。aPartlyContained为false表示全包含,为true表示只要部分包含即可。

toString():放回当前Selection对象的字符串。

1.3 Range

Range对象表示一个Selection的选择范围,一个Selection可以包含多个Range

获取对象

document.createRange():创建一个Range

selection.getRangeAt(index):获取指定的Range

属性

collapsed:判断起始位置是否重合。

endContaniner:range终点节点。

endOffset:range的终点位置。

startContaniner:ranstartge起点节点。

startOffset:range的起点位置。

commonAncestorContainer:包含起始点的节点。

方法

setStart(startNode,startOffset):设置范围在startNode的起始位置为startOffset。

setEnd(endNode,endOffset):设置范围在endNode的起始位置为endOffset。

selectNode(referenceNode):设置range的节点为referenceNode。

selectNodeContents(referenceNode):设置range的内容为referenceNode。

collapse(toStart):向边界点折叠range,即是设置光标位置,toStart默认为false,表示光标定位在节点末尾。true表示光标定位在节点起点。

cloneContents():克隆一个range的内容片段。

deleteContents():删除range的内容片段。

extractContents():将range的内容从文档树移动到文档片段中。

insertNode(newNode):在range的其实位置插入新的节点。

surroundContents(newNode):将range对象的内容移动到新的节点中。

cloneRange():克隆一个range对象。

detach():释放当前range。

1.4 input/textarea

在html5中,可输入性表单元素(input/textarea)都存在以下属性。不支持IE6/7。

  • selectionDirection:forward | backward | none,选区方向
  • selectionEnd:选区终点位置
  • selectionStart:选区起点位置

setSelectionRange(selectionStart, selectionEnd, [selectionDirection]):设置获取焦点的输入性元素的选区范围。

获取光标位置">2.获取光标位置

获取光标位置">2.1 可编辑div获取光标位置

js hljs ">js-comment">//获取当前光标位置
js-keyword">const getCursortPosition = js-function">js-keyword">function js-params">(element) {
  js-keyword">var caretOffset = js-number">0;
  js-keyword">var doc = element.ownerDocument || element.document;
  js-keyword">var win = doc.defaultView || doc.parentWindow;
  js-keyword">var sel;
  js-keyword">if (js-keyword">typeof win.getSelection != js-string">"undefined") {js-comment">//谷歌、火狐
    sel = win.getSelection();
    js-keyword">if (sel.rangeCount > js-number">0) {js-comment">//选中的区域
      js-keyword">var range = win.getSelection().getRangeAt(js-number">0);
      js-keyword">var preCaretRange = range.cloneRange();js-comment">//克隆一个选中区域
      preCaretRange.selectNodeContents(element);js-comment">//设置选中区域的节点内容为当前节点
      preCaretRange.setEnd(range.endContainer, range.endOffset);  js-comment">//重置选中区域的结束位置
      caretOffset = preCaretRange.toString().length;
    }
  } js-keyword">else js-keyword">if ((sel = doc.selection) && sel.type != js-string">"Control") {js-comment">//IE
    js-keyword">var textRange = sel.createRange();
    js-keyword">var preCaretTextRange = doc.body.createTextRange();
    preCaretTextRange.moveToElementText(element);
    preCaretTextRange.setEndPoint(js-string">"EndToEnd", textRange);
    caretOffset = preCaretTextRange.text.length;
  }
  js-keyword">return caretOffset;
}

获取光标的位置是先通过获取鼠标的选取范围,然后克隆该选取范围,修改克隆范围的结束位置,这样克隆的范围就只剩下起点到结束点的内容,光标之后的内容被截取扔掉了。所以可以通过剩余内容的长度来确定光标位置。之所以要克隆一个选取范围出来,是为了避免修改光标结束位置时影响到原先内容。

获取光标位置">2.2 input/textarea获取光标位置

js hljs ">js-comment">//输入框获取光标
js-keyword">const getPosition = js-function">js-keyword">function js-params">(element) {
    js-keyword">let cursorPos = js-number">0;
    js-keyword">if (document.selection) {js-comment">//IE
        js-keyword">var selectRange = document.selection.createRange();
        selectRange.moveStart(js-string">'character', -element.value.length);
        cursorPos = selectRange.text.length;
    } js-keyword">else js-keyword">if (element.selectionStart || element.selectionStart == js-string">'0') {
        cursorPos = element.selectionStart;
    }
    js-keyword">return cursorPos;
}

设置光标位置">3.设置光标位置

设置光标位置">3.1 可编辑div设置光标位置

js hljs ">js-comment">//设置光标位置
js-keyword">const setCaretPosition = js-function">js-keyword">function js-params">(element, pos) {
  js-keyword">var range, selection;
  js-keyword">if (document.createRange)js-comment">//Firefox, Chrome, Opera, Safari, IE 9+
  {
    range = document.createRange();js-comment">//创建一个选中区域
    range.selectNodeContents(element);js-comment">//选中节点的内容
    js-keyword">if(element.innerHTML.length > js-number">0) {
      range.setStart(element.childNodes[js-number">0], pos); js-comment">//设置光标起始为指定位置
    }
    range.collapse(js-literal">true);       js-comment">//设置选中区域为一个点
    selection = window.getSelection();js-comment">//获取当前选中区域
    selection.removeAllRanges();js-comment">//移出所有的选中范围
    selection.addRange(range);js-comment">//添加新建的范围
  }
  js-keyword">else js-keyword">if (document.selection)js-comment">//IE 8 and lower
  {
    range = document.body.createTextRange();js-comment">//Create a range (a range is a like the selection but invisible)
    range.moveToElementText(element);js-comment">//Select the entire contents of the element with the range
    range.collapse(js-literal">false);js-comment">//collapse the range to the end point. false means collapse to end rather than the start
    range.select();js-comment">//Select the range (make it the visible selection
  }
}

获取光标位置">3.2 input/textarea获取光标位置

js hljs ">js-comment">// 设置光标位置
js-function">js-keyword">function js-title">setCaretPositionjs-params">(textDom, pos){
    js-keyword">if(textDom.setSelectionRange) {
        js-comment">// IE Support
        textDom.focus();
        textDom.setSelectionRange(pos, pos);
    }js-keyword">else js-keyword">if (textDom.createTextRange) {
        js-comment">// Firefox support
        js-keyword">var range = textDom.createTextRange();
        range.collapse(js-literal">true);
        range.moveEnd(js-string">'character', pos);
        range.moveStart(js-string">'character', pos);
        range.select();
    }
}

4.示例

js ">js-tag"><js-title">html>

js-tag"><js-title">head>
  js-tag"><js-title">title>光标测试js-tag"></js-title">title>
  js-tag"><js-title">style>
    js-tag">p js-rules">{
      js-rule">js-attribute">display:js-value"> flex;
      js-rule">js-attribute">flex-direction:js-value"> row;
    js-rule">}

    js-class">.btn js-rules">{
      js-rule">js-attribute">height:js-value"> js-number">24px;
      js-rule">js-attribute">margin:js-value"> js-number">0 js-number">10px;
    js-rule">}

    js-class">.edit-div js-rules">{
      js-rule">js-attribute">display:js-value"> inline-block;
      js-rule">js-attribute">width:js-value"> js-number">225px;
      js-rule">js-attribute">border:js-value"> js-number">1px solid js-hexcolor">#decdcd;
    js-rule">}
  js-tag"></js-title">style>
  js-tag"><js-title">script>

    js-function">js-keyword">function js-title">getCursortPositionjs-params">(e) {
      js-keyword">var eleP = e.target.parentNode; js-comment">//获取父级元素
      js-keyword">var pos = js-number">0;
      js-keyword">if (e.target.nodeName == js-string">"DIV") {
        pos = getDivPosition(e.target);
      } js-keyword">else {
        pos = getPosition(e.target);
      }

      js-keyword">var spanEle = (eleP.childNodes)[js-number">7];
      spanEle.innerText = pos;
    }

    js-comment">//可编辑div获取坐标
    js-keyword">const getDivPosition = js-function">js-keyword">function js-params">(element) {
      js-keyword">var caretOffset = js-number">0;
      js-keyword">var doc = element.ownerDocument || element.document;
      js-keyword">var win = doc.defaultView || doc.parentWindow;
      js-keyword">var sel;
      js-keyword">if (js-keyword">typeof win.getSelection != js-string">"undefined") {js-comment">//谷歌、火狐
        sel = win.getSelection();
        js-keyword">if (sel.rangeCount > js-number">0) {js-comment">//选中的区域
          js-keyword">var range = win.getSelection().getRangeAt(js-number">0);
          js-keyword">var preCaretRange = range.cloneRange();js-comment">//克隆一个选中区域
          preCaretRange.selectNodeContents(element);js-comment">//设置选中区域的节点内容为当前节点
          preCaretRange.setEnd(range.endContainer, range.endOffset);  js-comment">//重置选中区域的结束位置
          caretOffset = preCaretRange.toString().length;
        }
      } js-keyword">else js-keyword">if ((sel = doc.selection) && sel.type != js-string">"Control") {js-comment">//IE
        js-keyword">var textRange = sel.createRange();
        js-keyword">var preCaretTextRange = doc.body.createTextRange();
        preCaretTextRange.moveToElementText(element);
        preCaretTextRange.setEndPoint(js-string">"EndToEnd", textRange);
        caretOffset = preCaretTextRange.text.length;
      }
      js-keyword">return caretOffset;
    }

    js-comment">//输入框获取光标
    js-keyword">const getPosition = js-function">js-keyword">function js-params">(element) {
      js-keyword">let cursorPos = js-number">0;
      js-keyword">if (document.selection) {js-comment">//IE
        js-keyword">var selectRange = document.selection.createRange();
        selectRange.moveStart(js-string">'character', -element.value.length);
        cursorPos = selectRange.text.length;
      } js-keyword">else js-keyword">if (element.selectionStart || element.selectionStart == js-string">'0') {
        cursorPos = element.selectionStart;
      }
      js-keyword">return cursorPos;
    }
  js-tag"></js-title">script>
js-tag"></js-title">head>

js-tag"><js-title">body>
  js-tag"><js-title">p>
    js-tag"><js-title">label>输入框测试:js-tag"></js-title">label>
    js-tag"><js-title">input js-attribute">type=js-value">"text" js-attribute">style=js-value">"width:220px" js-attribute">onclick=js-value">"getCursortPosition(event);" />
    js-tag"><js-title">span>光标位置:js-tag"></js-title">span>
    js-tag"><js-title">span>js-tag"></js-title">span>
  js-tag"></js-title">p>
  js-tag"><js-title">p>
    js-tag"><js-title">label>文本框测试:js-tag"></js-title">label>
    js-tag"><js-title">textarea js-attribute">rows=js-value">"5" js-attribute">style=js-value">"width:220px" js-attribute">onclick=js-value">"getCursortPosition(event);">js-tag"></js-title">textarea>
    js-tag"><js-title">span>光标位置:js-tag"></js-title">span>
    js-tag"><js-title">span>js-tag"></js-title">span>
  js-tag"></js-title">p>
  js-tag"><js-title">div>
    js-tag"><js-title">label>可编辑div:js-tag"></js-title">label>
    js-tag"><js-title">div js-attribute">contenteditable=js-value">"true" js-attribute">class=js-value">"edit-div" js-attribute">onclick=js-value">"getCursortPosition(event);">js-tag"></js-title">div>
    js-tag"><js-title">span>光标位置:js-tag"></js-title">span>
    js-tag"><js-title">span>js-tag"></js-title">span>
  js-tag"></js-title">div>
js-tag"></js-title">body>

js-tag"></js-title">html>

效果图:

这里写图片描述


http://www.niftyadmin.cn/n/725340.html

相关文章

csuoj 1022: 菜鸟和大牛

http://acm.csu.edu.cn/OnlineJudge/problem.php?id1022 1022: 菜鸟和大牛 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 293 Solved: 145[Submit][Status][Web Board]Description blue和AutoGerk是好朋友。他们的相同点是都喜欢研究算法&#xff0c;不同点是AutoGerk已是…

可编辑div在光标位置插入指定内容

可编辑div在光标位置插入指定内容 //在光标位置插入内容 insertContent(content) {if (!content) {//如果插入的内容为空则返回return;}let sel null;if (document.selection) {//IE9以下sel document.selection;sel.createRange().pasteHTML(content);} else {sel window.…

《javascript高级程序设计》 第20章 JSON

20.1 语法   20.1.1 简单值   20.1.2 对象   20.1.3 数组 20.2 解析与序列化   20.2.1 JSON 对象   20.2.2 序列化选项   20.2.3 解析选项 JSON 对象有两个方法&#xff1a;stringify()和parse()。在最简单的情况下&#xff0c;这两个方法分别用于把JavaScript 对象…

ThinkJs入门

TinkJs入门 本文是以thinkjs3.0版本为参照讲解的&#xff0c;如有不理解的部分&#xff0c;请参照&#xff1a;https://thinkjs.org/zh-cn/doc/3.0/create_project.html。 1.项目创建 全局安装thinkjs $ npm install -g think-cli 创建并执行项目 $ thinkjs new demo; $ …

从汇编看c++中的默认拷贝函数

《c编程思想》上说一个类如果没有拷贝函数&#xff0c;那么编译器就会自动创建一个默认的拷贝函数。下面就让我们看一下真实的情况。 首先看一个简单的类X&#xff0c;这个类没有显示定义拷贝构造函数。c源码如下: class X { private:int i;int j; };int main() {X x1;//先定义…

QQ数据线传输到手机上的文件放到了哪里

sd根目录下Tencent/QQfile_recv下的。转载于:https://www.cnblogs.com/passer1991/p/3298047.html

npm中--save-dev和--save的区别

npm中–save-dev和–save的区别 1.常用几个参数 -g:将模块安装到全局环境。 --save:将模块安装到项目node_modules目录下&#xff0c;并在package.json的dependencies节点写入依赖。 --save-dev:将模块安装到项目node_modules目录下&#xff0c;并在package.json的devDepen…

从汇编看c++的默认operator=操作

从汇编看c的默认operator操作 在c中&#xff0c;如果没有定义operator操作&#xff0c;编译器会提供一个默认的operator操作。由于operator操作和拷贝构造函数的功能类似&#xff0c;都执行拷贝操作。因此&#xff0c;编译器也分提供无用的默认operator操作和非无用的默认oper…