js獲取光標(biāo)位置的最新方法
1.概念和原理
DOM中并沒有直接獲取光標(biāo)位置的方法,那么我們只能間接來獲取光標(biāo)位置。DOM支持獲取光標(biāo)選中的范圍,我們可以以此為切入點(diǎn),來獲取或定位光標(biāo)的位置。當(dāng)選取范圍起始點(diǎn)和結(jié)束點(diǎn)一樣時(shí),就是光標(biāo)插入的位置。
1.1 術(shù)語
- anchor(瞄點(diǎn)):選區(qū)起點(diǎn)。
- focus(焦點(diǎn)):選區(qū)終點(diǎn)。
- range(范圍):選區(qū)范圍,包含整個(gè)節(jié)點(diǎn)或節(jié)點(diǎn)的一部分。
1.2 Selection
Selection: Selection對象表示用戶選擇的文本范圍或插入符號的位置。
經(jīng)過實(shí)驗(yàn)發(fā)現(xiàn)Selection選取的節(jié)點(diǎn)范圍都是塊級節(jié)點(diǎn)。input 和 texteare 并不能作為Selection的節(jié)點(diǎn)
Selection對象存在于window對象上,可以通過window.getSelection()獲取示例。
屬性:
- anchorNode: 選區(qū)起點(diǎn)的節(jié)點(diǎn)。
- anchorOffset:選區(qū)的起點(diǎn)位置。
- focusNode:選區(qū)終點(diǎn)的節(jié)點(diǎn)。
- focusOffset:選區(qū)的終點(diǎn)位置。
- isCollapsed:起點(diǎn)和終點(diǎn)是否重疊。
- rangeCount:選區(qū)包含的range數(shù)目。
方法
- getRangeAt(index):獲取指定的選取范圍。
- addRange(range):將一個(gè)范圍添加到Selection對象中。
- removeRange():移出指定的范圍。
- removeAllRanges():移出所有range對象。
- collapse(parentNode,offset):將光標(biāo)移動(dòng)到parentNode節(jié)點(diǎn)的offset位置。
- collapseToStart():取消當(dāng)前選區(qū),并把光標(biāo)定位在原選區(qū)的最開始處,如果此時(shí)光標(biāo)所處的位置是可編輯的,且它獲得了焦點(diǎn),則光標(biāo)會(huì)在原地閃爍。
- collapseToEnd():取消當(dāng)前選區(qū),并將光標(biāo)定位到原選取的最末位。如果此時(shí)光標(biāo)所處的位置是可編輯的,且它獲得了焦點(diǎn),則光標(biāo)會(huì)在原地閃爍。
- extend(node,offset):將終點(diǎn)位置移動(dòng)到node節(jié)點(diǎn)的offset位置。
- modify(alter,direction,granularity):通過alter方式(move/extend)來改變光標(biāo)位置,移動(dòng)方向?yàn)閐irection(left/right),移動(dòng)單位為granularity。
- containsNode(aNode,aPartlyContained):判斷aNode是否包含在Selection中。aPartlyContained為false表示全包含,為true表示只要部分包含即可。
- toString():放回當(dāng)前Selection對象的字符串。
1.3 Range
Range對象表示一個(gè)Selection的選擇范圍,一個(gè)Selection可以包含多個(gè)Range。
獲取對象
document.createRange():創(chuàng)建一個(gè)Range。
selection.getRangeAt(index):獲取指定的Range。
屬性
- collapsed:判斷起始位置是否重合。
- endContaniner:range終點(diǎn)節(jié)點(diǎn)。
- endOffset:range的終點(diǎn)位置。
- startContaniner:ranstartge起點(diǎn)節(jié)點(diǎn)。
- startOffset:range的起點(diǎn)位置。
- commonAncestorContainer:包含起始點(diǎn)的節(jié)點(diǎn)。
方法
- setStart(startNode,startOffset):設(shè)置范圍在startNode的起始位置為startOffset。
- setEnd(endNode,endOffset):設(shè)置范圍在endNode的起始位置為endOffset。
- selectNode(referenceNode):設(shè)置range的節(jié)點(diǎn)為referenceNode。
- selectNodeContents(referenceNode):設(shè)置range的內(nèi)容為referenceNode。
- collapse(toStart):向邊界點(diǎn)折疊range,即是設(shè)置光標(biāo)位置,toStart默認(rèn)為false,表示光標(biāo)定位在節(jié)點(diǎn)末尾。true表示光標(biāo)定位在節(jié)點(diǎn)起點(diǎn)。
- cloneContents():克隆一個(gè)range的內(nèi)容片段。
- deleteContents():刪除range的內(nèi)容片段。
- extractContents():將range的內(nèi)容從文檔樹移動(dòng)到文檔片段中。
- insertNode(newNode):在range的其實(shí)位置插入新的節(jié)點(diǎn)。
- surroundContents(newNode):將range對象的內(nèi)容移動(dòng)到新的節(jié)點(diǎn)中。
- cloneRange():克隆一個(gè)range對象。
- detach():釋放當(dāng)前range。
1.4 input/textarea
在html5中,可輸入性表單元素(input/textarea)都存在以下屬性。不支持IE6/7。
selectionDirection:forward | backward | none,選區(qū)方向
selectionEnd:選區(qū)終點(diǎn)位置
selectionStart:選區(qū)起點(diǎn)位置
setSelectionRange(selectionStart, selectionEnd, [selectionDirection]):設(shè)置獲取焦點(diǎn)的輸入性元素的選區(qū)范圍。
2.獲取光標(biāo)位置
2.1 可編輯div獲取光標(biāo)位置
//獲取當(dāng)前光標(biāo)位置 const getCursortPosition = function (element) { var caretOffset = 0; var doc = element.ownerDocument || element.document; var win = doc.defaultView || doc.parentWindow; var sel; if (typeof win.getSelection != "undefined") {//谷歌、火狐 sel = win.getSelection(); if (sel.rangeCount > 0) {//選中的區(qū)域 var range = win.getSelection().getRangeAt(0); var preCaretRange = range.cloneRange();//克隆一個(gè)選中區(qū)域 preCaretRange.selectNodeContents(element);//設(shè)置選中區(qū)域的節(jié)點(diǎn)內(nèi)容為當(dāng)前節(jié)點(diǎn) preCaretRange.setEnd(range.endContainer, range.endOffset); //重置選中區(qū)域的結(jié)束位置 caretOffset = preCaretRange.toString().length; } } else if ((sel = doc.selection) && sel.type != "Control") {//IE var textRange = sel.createRange(); var preCaretTextRange = doc.body.createTextRange(); preCaretTextRange.moveToElementText(element); preCaretTextRange.setEndPoint("EndToEnd", textRange); caretOffset = preCaretTextRange.text.length; } return caretOffset; }
獲取光標(biāo)的位置是先通過獲取鼠標(biāo)的選取范圍,然后克隆該選取范圍,修改克隆范圍的結(jié)束位置,這樣克隆的范圍就只剩下起點(diǎn)到結(jié)束點(diǎn)的內(nèi)容,光標(biāo)之后的內(nèi)容被截取扔掉了。所以可以通過剩余內(nèi)容的長度來確定光標(biāo)位置。之所以要克隆一個(gè)選取范圍出來,是為了避免修改光標(biāo)結(jié)束位置時(shí)影響到原先內(nèi)容。
2.2 input/textarea獲取光標(biāo)位置
//輸入框獲取光標(biāo) const getPosition = function (element) { let cursorPos = 0; if (document.selection) {//IE var selectRange = document.selection.createRange(); selectRange.moveStart('character', -element.value.length); cursorPos = selectRange.text.length; } else if (element.selectionStart || element.selectionStart == '0') { cursorPos = element.selectionStart; } return cursorPos; }
3.設(shè)置光標(biāo)位置
3.1 可編輯div設(shè)置光標(biāo)位置
//設(shè)置光標(biāo)位置 const setCaretPosition = function (element, pos) { var range, selection; if (document.createRange)//Firefox, Chrome, Opera, Safari, IE 9+ { range = document.createRange();//創(chuàng)建一個(gè)選中區(qū)域 range.selectNodeContents(element);//選中節(jié)點(diǎn)的內(nèi)容 if(element.innerHTML.length > 0) { range.setStart(element.childNodes[0], pos); //設(shè)置光標(biāo)起始為指定位置 } range.collapse(true); //設(shè)置選中區(qū)域?yàn)橐粋€(gè)點(diǎn) selection = window.getSelection();//獲取當(dāng)前選中區(qū)域 selection.removeAllRanges();//移出所有的選中范圍 selection.addRange(range);//添加新建的范圍 } else if (document.selection)//IE 8 and lower { range = document.body.createTextRange();//Create a range (a range is a like the selection but invisible) range.moveToElementText(element);//Select the entire contents of the element with the range range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start range.select();//Select the range (make it the visible selection } }
3.2 input/textarea獲取光標(biāo)位置
// 設(shè)置光標(biāo)位置 function setCaretPosition(textDom, pos){ if(textDom.setSelectionRange) { // IE Support textDom.focus(); textDom.setSelectionRange(pos, pos); }else if (textDom.createTextRange) { // Firefox support var range = textDom.createTextRange(); range.collapse(true); range.moveEnd('character', pos); range.moveStart('character', pos); range.select(); } }
4.示例
<html> <head> <title>光標(biāo)測試</title> <style> p { display: flex; flex-direction: row; } .btn { height: 24px; margin: 0 10px; } .edit-div { display: inline-block; width: 225px; border: 1px solid #decdcd; } </style> <script> function getCursortPosition(e) { var eleP = e.target.parentNode; //獲取父級元素 var pos = 0; if (e.target.nodeName == "DIV") { pos = getDivPosition(e.target); } else { pos = getPosition(e.target); } var spanEle = (eleP.childNodes)[7]; spanEle.innerText = pos; } //可編輯div獲取坐標(biāo) const getDivPosition = function (element) { var caretOffset = 0; var doc = element.ownerDocument || element.document; var win = doc.defaultView || doc.parentWindow; var sel; if (typeof win.getSelection != "undefined") {//谷歌、火狐 sel = win.getSelection(); if (sel.rangeCount > 0) {//選中的區(qū)域 var range = win.getSelection().getRangeAt(0); var preCaretRange = range.cloneRange();//克隆一個(gè)選中區(qū)域 preCaretRange.selectNodeContents(element);//設(shè)置選中區(qū)域的節(jié)點(diǎn)內(nèi)容為當(dāng)前節(jié)點(diǎn) preCaretRange.setEnd(range.endContainer, range.endOffset); //重置選中區(qū)域的結(jié)束位置 caretOffset = preCaretRange.toString().length; } } else if ((sel = doc.selection) && sel.type != "Control") {//IE var textRange = sel.createRange(); var preCaretTextRange = doc.body.createTextRange(); preCaretTextRange.moveToElementText(element); preCaretTextRange.setEndPoint("EndToEnd", textRange); caretOffset = preCaretTextRange.text.length; } return caretOffset; } //輸入框獲取光標(biāo) const getPosition = function (element) { let cursorPos = 0; if (document.selection) {//IE var selectRange = document.selection.createRange(); selectRange.moveStart('character', -element.value.length); cursorPos = selectRange.text.length; } else if (element.selectionStart || element.selectionStart == '0') { cursorPos = element.selectionStart; } return cursorPos; } </script> </head> <body> <p> <label>輸入框測試:</label> <input type="text" style="width:220px" onclick="getCursortPosition(event);" /> <span>光標(biāo)位置:</span> <span></span> </p> <p> <label>文本框測試:</label> <textarea rows="5" style="width:220px" onclick="getCursortPosition(event);"></textarea> <span>光標(biāo)位置:</span> <span></span> </p> <div> <label>可編輯div:</label> <div contenteditable="true" class="edit-div" onclick="getCursortPosition(event);"></div> <span>光標(biāo)位置:</span> <span></span> </div> </body> </html>
總結(jié)
到此這篇關(guān)于js獲取光標(biāo)位置的文章就介紹到這了,更多相關(guān)js獲取光標(biāo)位置內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javascript中apply、call、bind的巧妙使用
Javascript中apply、call、bind都是為了改變函數(shù)體內(nèi)部 this 的指向。下面通過本文重點(diǎn)給大家介紹js中apply,call,bind的巧妙使用方法,感興趣的朋友一起學(xué)習(xí)吧2016-08-08javascript和jQuery實(shí)現(xiàn)網(wǎng)頁實(shí)時(shí)聊天的ajax長輪詢
在做網(wǎng)頁實(shí)時(shí)聊天的時(shí)候常常需要長輪詢,本文由于采用原生的JS及AJAX,所以簡單易懂,通過這篇文章就可以建立一個(gè)簡單的聊天室程序。2016-07-07js實(shí)現(xiàn)動(dòng)畫特效的文字鏈接鼠標(biāo)懸停提示的方法
這篇文章主要介紹了js實(shí)現(xiàn)動(dòng)畫特效的文字鏈接鼠標(biāo)懸停提示的方法,實(shí)例分析了javascript操作css的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03javaScript實(shí)現(xiàn)鼠標(biāo)在文字上懸浮時(shí)彈出懸浮層效果
這篇文章主要為大家詳細(xì)介紹了javaScript實(shí)現(xiàn)鼠標(biāo)在文字上懸浮時(shí)彈出懸浮層效果的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03基于javascript html5實(shí)現(xiàn)3D翻書特效
這篇文章主要介紹了基于javascript html5實(shí)現(xiàn)翻書特效的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-03-03