文章原创作者:codingWeb 链接:https://blog.csdn.net/fesfsefgs/article/details/109540259
这周碰到一个东西,contentEditable
,它是用来指定一个元素是否是可编辑的,这也是富文本编辑器实现的底层支持,网上关于这部分东西的资料比较少或者不全,所以我来整理下关于这个属性,和可编辑区域的一些操作吧,比如获取光标位置,设置光标,往可编辑区域光标处插入内容等等
HTML中的contentEditable的属性可以打开某些元素的可编辑状态.也许你没用过contentEditable属性.甚至从未听说过.contentEditable的作用相当神奇.可以让div或整个网页,以及span等等元素设置为可写。我们最常用的输入文本内容便是input与textarea,使用contentEditable属性后,可以在div,table,p,span,body,等等很多元素中输入内容.
设置一个容器为可编辑区域: 设置contentEditable属性
<body>
<p contentEditable style="border: 1px solid red;">grsd</p>
<div contentEditable style="border: 1px solid red;">rsdgsdg </div>
</body>
设置placeholder: 这个不像表单一样,给属性加上placeholder属性指定值就可以了,还需要配合特殊的样式:empty
做设置
< style type = " text/css" >
.content:empty::before {
content : attr ( placeholder) ;
font-size : 14px;
color : #CCC;
line-height : 21px;
padding-top : 20px;
}
.content {
border : 1px solid black;
}
</ style>
< body>
< div contentEditable class = " content" placeholder = " 请输入不少于150字" > </ div>
</ body>
回车时,在标记生成上的不同点
因为各个浏览器在标记生成上的不同,因此跨浏览器使用 contenteditable 一直以来都是痛点,例如一些看起来十分简单的事情,如: 当你按下Enter/Return键在可编辑区域中创建一个新的文本行时,不同主流浏览器对此有不同处理(Firefox 插入<br>
、IE/Opera将使用<p>
、 Chrome/Safari 将使用 <div>
)幸运的是在现代浏览器中,这些不同都趋于一致了。截止到Firefox 60,火狐开始使用<div>
元素来包裹新生成的文本行,以与Chrome, modern Opera, Edge, and Safari.的行为趋于一致
改变回车时插入的标签: 如果你想使用不同的方式创建新的段落,上面所有浏览器都支持document.execCommand
方法,该方法提供的 defaultParagraphSeparator
命令能够让你以不同的方式创建新的段落例如, 使用 <p>
元素:
document.execCommand("defaultParagraphSeparator", false, "p");
现在在编辑器中按回车就变成p
标签了
document.execCommand的强大:
上面只是document.execCommand
的一个命令演示
当一个HTML文档切换到设计模式时,document暴露 execCommand 方法
,该方法允许运行命令来操纵可编辑内容区域的元素。 大多数命令影响document的 selection(粗体,斜体等),当其他命令插入新元素(添加链接)或影响整行(缩进)。当使用contentEditable时,调用 execCommand() 将影响当前活动的可编辑元素
。
命令很多,这里就不列举出来,具体可以参考官方文档document.execCommand命令大全
基于document.execCommand的这些命令
,我们可以做一个小型的富文本编辑器:
<! doctype html >
< html>
< head>
< title> Rich Text Editor</ title>
< script type = " text/javascript" >
var oDoc, sDefTxt;
function initDoc ( ) {
oDoc = document. getElementById ( "textBox" ) ;
sDefTxt = oDoc. innerHTML;
if ( document. compForm. switchMode. checked) {
setDocMode ( true ) ;
}
}
function formatDoc ( sCmd, sValue ) {
if ( validateMode ( ) ) {
document. execCommand ( sCmd, false , sValue) ;
oDoc. focus ( ) ;
}
}
function validateMode ( ) {
if ( ! document. compForm. switchMode. checked) {
return true ;
}
alert ( "Uncheck \"Show HTML\"." ) ;
oDoc. focus ( ) ;
return false ;
}
function setDocMode ( bToSource ) {
var oContent;
if ( bToSource) {
oContent = document. createTextNode ( oDoc. innerHTML) ;
oDoc. innerHTML = "" ;
var oPre = document. createElement ( "pre" ) ;
oDoc. contentEditable = false ;
oPre. id = "sourceText" ;
oPre. contentEditable = true ;
oPre. appendChild ( oContent) ;
oDoc. appendChild ( oPre) ;
document. execCommand ( "defaultParagraphSeparator" , false , "div" ) ;
} else {
if ( document. all) {
oDoc. innerHTML = oDoc. innerText;
} else {
oContent = document. createRange ( ) ;
oContent. selectNodeContents ( oDoc. firstChild) ;
oDoc. innerHTML = oContent. toString ( ) ;
}
oDoc. contentEditable = true ;
}
oDoc. focus ( ) ;
}
function printDoc ( ) {
if ( ! validateMode ( ) ) {
return ;
}
var oPrntWin = window. open ( "" , "_blank" , "width=450,height=470,left=400,top=100,menubar=yes,toolbar=no,location=no,scrollbars=yes" ) ;
oPrntWin. document. open ( ) ;
oPrntWin. document. write ( "<!doctype html><html><head><title>Print<\/title><\/head><body οnlοad=\"print();\">" + oDoc. innerHTML + "<\/body><\/html>" ) ;
oPrntWin. document. close ( ) ;
}
</ script>
< style type = " text/css" >
.intLink {
cursor : pointer;
}
img.intLink {
border : 0;
}
#toolBar1 select {
font-size : 10px;
}
#textBox {
width : 540px;
height : 200px;
border : 1px #000000 solid;
padding : 12px;
overflow : scroll;
}
#textBox #sourceText {
padding : 0;
margin : 0;
min-width : 498px;
min-height : 200px;
}
#editMode label {
cursor : pointer;
}
</ style>
</ head>
< body onload = " initDoc();" >
< form name = " compForm" method = " post" action = " sample.php" onsubmit = " if(validateMode()){this.myDoc.value=oDoc.innerHTML;return true;}return false;" >
< input type = " hidden" name = " myDoc" >
< div id = " toolBar1" >
< select onchange = " formatDoc(' formatblock' ,this[this.selectedIndex].value);this.selectedIndex=0;" >
< option selected > - formatting -</ option>
< option value = " h1" > Title 1 < h1> </ option>
< option value = " h2" > Title 2 < h2> </ option>
< option value = " h3" > Title 3 < h3> </ option>
< option value = " h4" > Title 4 < h4> </ option>
< option value = " h5" > Title 5 < h5> </ option>
< option value = " h6" > Subtitle < h6> </ option>
< option value = " p" > Paragraph < p> </ option>
< option value = " pre" > Preformatted < pre> </ option>
</ select>
< select onchange = " formatDoc(' fontname' ,this[this.selectedIndex].value);this.selectedIndex=0;" >
< option class = " heading" selected > - font -</ option>
< option> Arial</ option>
< option> Arial Black</ option>
< option> Courier New</ option>
< option> Times New Roman</ option>
</ select>
< select onchange = " formatDoc(' fontsize' ,this[this.selectedIndex].value);this.selectedIndex=0;" >
< option class = " heading" selected > - size -</ option>
< option value = " 1" > Very small</ option>
< option value = " 2" > A bit small</ option>
< option value = " 3" > Normal</ option>
< option value = " 4" > Medium-large</ option>
< option value = " 5" > Big</ option>
< option value = " 6" > Very big</ option>
< option value = " 7" > Maximum</ option>
</ select>
< select onchange = " formatDoc(' forecolor' ,this[this.selectedIndex].value);this.selectedIndex=0;" >
< option class = " heading" selected > - color -</ option>
< option value = " red" > Red</ option>
< option value = " blue" > Blue</ option>
< option value = " green" > Green</ option>
< option value = " black" > Black</ option>
</ select>
< select onchange = " formatDoc(' backcolor' ,this[this.selectedIndex].value);this.selectedIndex=0;" >
< option class = " heading" selected > - background -</ option>
< option value = " red" > Red</ option>
< option value = " green" > Green</ option>
< option value = " black" > Black</ option>
</ select>
</ div>
< div id = " toolBar2" >
< img class = " intLink" title = " Clean" onclick = " if(validateMode()&&confirm(' Are you sure?' )){oDoc.innerHTML=sDefTxt};" src = " data:image/gif;base64,R0lGODlhFgAWAIQbAD04KTRLYzFRjlldZl9vj1dusY14WYODhpWIbbSVFY6O7IOXw5qbms+wUbCztca0ccS4kdDQjdTLtMrL1O3YitHa7OPcsd/f4PfvrvDv8Pv5xv///yH5BAEKAB8ALAAAAAAWABYAAAV84CeOZGmeaKqubMteyzK547QoBcFWTm/jgsHq4rhMLoxFIehQQSAWR+Z4IAyaJ0kEgtFoLIzLwRE4oCQWrxoTOTAIhMCZ0tVgMBQKZHAYyFEWEV14eQ8IflhnEHmFDQkAiSkQCI2PDC4QBg+OAJc0ewadNCOgo6anqKkoIQA7" />
< img class = " intLink" title = " Print" onclick = " printDoc();" src = " data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oEBxcZFmGboiwAAAAIdEVYdENvbW1lbnQA9syWvwAAAuFJREFUOMvtlUtsjFEUx//n3nn0YdpBh1abRpt4LFqtqkc3jRKkNEIsiIRIBBEhJJpKlIVo4m1RRMKKjQiRMJRUqUdKPT71qpIpiRKPaqdF55tv5vvusZjQTjOlseUkd3Xu/3dPzusC/22wtu2wRn+jG5So/OCDh8ycMJDflehMlkJkVK7KUYN+ufzA/RttH76zaVocDptRxzQtNi3mRWuPc+6cKtlXZ/sddP2uu9uXlmYXZ6Qm8v4Tz8lhF1H+zDQXt7S8oLMXtbF4e8QaFHjj3kbP2MzkktHpiTjp9VH6iHiA+whtAsX5brpwueMGdONdf/2A4M7ukDs1JW662+XkqTkeUoqjKtOjm2h53YFL15pSJ04Zc94wdtibr26fXlC2mzRvBccEbz2kiRFD414tKMlEZbVGT33+qCoHgha81SWYsew0r1uzfNylmtpx80pngQQ91LwVk2JGvGnfvZG6YcYRAT16GFtW5kKKfo1EQLtfh5Q2etT0BIWF+aitq4fDbk+ImYo1OxvGF03waFJQvBCkvDffRyEtxQiFFYgAZTHS0zwAGD7fG5TNnYNTp8/FzvGwJOfmgG7GOx0SAKKgQgDMgKBI0NJGMEImpGDk5+WACEwEd0ywblhGUZ4Hw5OdUekRBLT7DTgdEgxACsIznx8zpmWh7k4rkpJcuHDxCul6MDsmmBXDlWCH2+XozSgBnzsNCEE4euYV4pwCpsWYPW0UHDYBKSWu1NYjENDReqtKjwn2+zvtTc1vMSTB/mvev/WEYSlASsLimcOhOBJxw+N3aP/SjefNL5GePZmpu4kG7OPr1+tOfPyUu3BecWYKcwQcDFmwFKAUo90fhKDInBCAmvqnyMgqUEagQwCoHBDc1rjv9pIlD8IbVkz6qYViIBQGTJPx4k0XpIgEZoRN1Da0cij4VfR0ta3WvBXH/rjdCufv6R2zPgPH/e4pxSBCpeatqPrjNiso203/5s/zA171Mv8+w1LOAAAAAElFTkSuQmCC" >
< img class = " intLink" title = " Undo" onclick = " formatDoc(' undo' );" src = " data:image/gif;base64,R0lGODlhFgAWAOMKADljwliE33mOrpGjuYKl8aezxqPD+7/I19DV3NHa7P///yH5BAEKAA8ALAAAAAAWABYAAARR8MlJq7046807TkaYeJJBnES4EeUJvIGapWYAC0CsocQ7SDlWJkAkCA6ToMYWIARGQF3mRQVIEjkkSVLIbSfEwhdRIH4fh/DZMICe3/C4nBQBADs=" />
< img class = " intLink" title = " Redo" onclick = " formatDoc(' redo' );" src = " data:image/gif;base64,R0lGODlhFgAWAMIHAB1ChDljwl9vj1iE34Kl8aPD+7/I1yH5BAEKAAcALAAAAAAWABYAAANKeLrc/jDKSesyphi7SiEgsVXZEATDICqBVJjpqWZt9NaEDNbQK1wCQsxlYnxMAImhyDoFAElJasRRvAZVRqqQXUy7Cgx4TC6bswkAOw==" />
< img class = " intLink" title = " Remove formatting" onclick = " formatDoc(' removeFormat' )" src = " data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB9oECQMCKPI8CIIAAAAIdEVYdENvbW1lbnQA9syWvwAAAuhJREFUOMtjYBgFxAB501ZWBvVaL2nHnlmk6mXCJbF69zU+Hz/9fB5O1lx+bg45qhl8/fYr5it3XrP/YWTUvvvk3VeqGXz70TvbJy8+Wv39+2/Hz19/mGwjZzuTYjALuoBv9jImaXHeyD3H7kU8fPj2ICML8z92dlbtMzdeiG3fco7J08foH1kurkm3E9iw54YvKwuTuom+LPt/BgbWf3//sf37/1/c02cCG1lB8f//f95DZx74MTMzshhoSm6szrQ/a6Ir/Z2RkfEjBxuLYFpDiDi6Af///2ckaHBp7+7wmavP5n76+P2ClrLIYl8H9W36auJCbCxM4szMTJac7KzaR3H1w2cfWAgafPbqs5g7D95++/P1B4+ECK8tAwMDw/1H7159+/7r7ZcvPz4fOHbzEwMDwx8GBgaGnNatfHZx8zqrJ+4VJBh5CQEGOySEua/v3n7hXmqI8WUGBgYGL3vVG7fuPK3i5GD9/fja7ZsMDAzMG/Ze52mZeSj4yu1XEq/ff7W5dvfVAS1lsXc4Db7z8C3r8p7Qjf///2dnZGxlqJuyr3rPqQd/Hhyu7oSpYWScylDQsd3kzvnH738wMDzj5GBN1VIWW4c3KDon7VOvm7S3paB9u5qsU5/x5KUnlY+eexQbkLNsErK61+++VnAJcfkyMTIwffj0QwZbJDKjcETs1Y8evyd48toz8y/ffzv//vPP4veffxpX77z6l5JewHPu8MqTDAwMDLzyrjb/mZm0JcT5Lj+89+Ybm6zz95oMh7s4XbygN3Sluq4Mj5K8iKMgP4f0fv77//8nLy+7MCcXmyYDAwODS9jM9tcvPypd35pne3ljdjvj26+H2dhYpuENikgfvQeXNmSl3tqepxXsqhXPyc666s+fv1fMdKR3TK72zpix8nTc7bdfhfkEeVbC9KhbK/9iYWHiErbu6MWbY/7//8/4//9/pgOnH6jGVazvFDRtq2VgiBIZrUTIBgCk+ivHvuEKwAAAAABJRU5ErkJggg==" >
< img class = " intLink" title = " Bold" onclick = " formatDoc(' bold' );" src = " data:image/gif;base64,R0lGODlhFgAWAID/AMDAwAAAACH5BAEAAAAALAAAAAAWABYAQAInhI+pa+H9mJy0LhdgtrxzDG5WGFVk6aXqyk6Y9kXvKKNuLbb6zgMFADs=" />
< img class = " intLink" title = " Italic" onclick = " formatDoc(' italic' );" src = " data:image/gif;base64,R0lGODlhFgAWAKEDAAAAAF9vj5WIbf///yH5BAEAAAMALAAAAAAWABYAAAIjnI+py+0Po5x0gXvruEKHrF2BB1YiCWgbMFIYpsbyTNd2UwAAOw==" />
< img class = " intLink" title = " Underline" onclick = " formatDoc(' underline' );" src = " data:image/gif;base64,R0lGODlhFgAWAKECAAAAAF9vjyH5BAEAAAIALAAAAAAWABYAAAIrlI+py+0Po5zUgAsEzvEeL4Ea15EiJJ5PSqJmuwKBEKgxVuXWtun+DwxCCgA7" />
< img class = " intLink" title = " Left align" onclick = " formatDoc(' justifyleft' );" src = " data:image/gif;base64,R0lGODlhFgAWAID/AMDAwAAAACH5BAEAAAAALAAAAAAWABYAQAIghI+py+0Po5y02ouz3jL4D4JMGELkGYxo+qzl4nKyXAAAOw==" />
< img class = " intLink" title = " Center align" onclick = " formatDoc(' justifycenter' );" src = " data:image/gif;base64,R0lGODlhFgAWAID/AMDAwAAAACH5BAEAAAAALAAAAAAWABYAQAIfhI+py+0Po5y02ouz3jL4D4JOGI7kaZ5Bqn4sycVbAQA7" />
< img class = " intLink" title = " Right align" onclick = " formatDoc(' justifyright' );" src = " data:image/gif;base64,R0lGODlhFgAWAID/AMDAwAAAACH5BAEAAAAALAAAAAAWABYAQAIghI+py+0Po5y02ouz3jL4D4JQGDLkGYxouqzl43JyVgAAOw==" />
< img class = " intLink" title = " Numbered list" onclick = " formatDoc(' insertorderedlist' );" src = " data:image/gif;base64,R0lGODlhFgAWAMIGAAAAADljwliE35GjuaezxtHa7P///yH5BAEAAAcALAAAAAAWABYAAAM2eLrc/jDKSespwjoRFvggCBUBoTFBeq6QIAysQnRHaEOzyaZ07Lu9lUBnC0UGQU1K52s6n5oEADs=" />
< img class = " intLink" title = " Dotted list" onclick = " formatDoc(' insertunorderedlist' );" src = " data:image/gif;base64,R0lGODlhFgAWAMIGAAAAAB1ChF9vj1iE33mOrqezxv///yH5BAEAAAcALAAAAAAWABYAAAMyeLrc/jDKSesppNhGRlBAKIZRERBbqm6YtnbfMY7lud64UwiuKnigGQliQuWOyKQykgAAOw==" />
< img class = " intLink" title = " Quote" onclick = " formatDoc(' formatblock' ,' blockquote' );" src = " data:image/gif;base64,R0lGODlhFgAWAIQXAC1NqjFRjkBgmT9nqUJnsk9xrFJ7u2R9qmKBt1iGzHmOrm6Sz4OXw3Odz4Cl2ZSnw6KxyqO306K63bG70bTB0rDI3bvI4P///yH5BAEKAB8ALAAAAAAWABYAAAVP4CeOZGmeaKqubEs2CekkErvEI1zZuOgYFlakECEZFi0GgTGKEBATFmJAVXweVOoKEQgABB9IQDCmrLpjETrQQlhHjINrTq/b7/i8fp8PAQA7" />
< img class = " intLink" title = " Delete indentation" onclick = " formatDoc(' outdent' );" src = " data:image/gif;base64,R0lGODlhFgAWAMIHAAAAADljwliE35GjuaezxtDV3NHa7P///yH5BAEAAAcALAAAAAAWABYAAAM2eLrc/jDKCQG9F2i7u8agQgyK1z2EIBil+TWqEMxhMczsYVJ3e4ahk+sFnAgtxSQDqWw6n5cEADs=" />
< img class = " intLink" title = " Add indentation" onclick = " formatDoc(' indent' );" src = " data:image/gif;base64,R0lGODlhFgAWAOMIAAAAADljwl9vj1iE35GjuaezxtDV3NHa7P///yH5BAEAAAgALAAAAAAWABYAAAQ7EMlJq704650B/x8gemMpgugwHJNZXodKsO5oqUOgo5KhBwWESyMQsCRDHu9VOyk5TM9zSpFSr9gsJwIAOw==" />
< img class = " intLink" title = " Hyperlink" onclick = " var sLnk=prompt(' Write the URL here' ,' http:\/\/' );if(sLnk&&sLnk!=' ' &&sLnk!=' http://' ){formatDoc(' createlink' ,sLnk)}" src = " data:image/gif;base64,R0lGODlhFgAWAOMKAB1ChDRLY19vj3mOrpGjuaezxrCztb/I19Ha7Pv8/f///yH5BAEKAA8ALAAAAAAWABYAAARY8MlJq7046827/2BYIQVhHg9pEgVGIklyDEUBy/RlE4FQF4dCj2AQXAiJQDCWQCAEBwIioEMQBgSAFhDAGghGi9XgHAhMNoSZgJkJei33UESv2+/4vD4TAQA7" />
< img class = " intLink" title = " Cut" onclick = " formatDoc(' cut' );" src = " data:image/gif;base64,R0lGODlhFgAWAIQSAB1ChBFNsRJTySJYwjljwkxwl19vj1dusYODhl6MnHmOrpqbmpGjuaezxrCztcDCxL/I18rL1P///yH5BAEAAB8ALAAAAAAWABYAAAVu4CeOZGmeaKqubDs6TNnEbGNApNG0kbGMi5trwcA9GArXh+FAfBAw5UexUDAQESkRsfhJPwaH4YsEGAAJGisRGAQY7UCC9ZAXBB+74LGCRxIEHwAHdWooDgGJcwpxDisQBQRjIgkDCVlfmZqbmiEAOw==" />
< img class = " intLink" title = " Copy" onclick = " formatDoc(' copy' );" src = " data:image/gif;base64,R0lGODlhFgAWAIQcAB1ChBFNsTRLYyJYwjljwl9vj1iE31iGzF6MnHWX9HOdz5GjuYCl2YKl8ZOt4qezxqK63aK/9KPD+7DI3b/I17LM/MrL1MLY9NHa7OPs++bx/Pv8/f///yH5BAEAAB8ALAAAAAAWABYAAAWG4CeOZGmeaKqubOum1SQ/kPVOW749BeVSus2CgrCxHptLBbOQxCSNCCaF1GUqwQbBd0JGJAyGJJiobE+LnCaDcXAaEoxhQACgNw0FQx9kP+wmaRgYFBQNeAoGihCAJQsCkJAKOhgXEw8BLQYciooHf5o7EA+kC40qBKkAAAGrpy+wsbKzIiEAOw==" />
< img class = " intLink" title = " Paste" onclick = " formatDoc(' paste' );" src = " data:image/gif;base64,R0lGODlhFgAWAIQUAD04KTRLY2tXQF9vj414WZWIbXmOrpqbmpGjudClFaezxsa0cb/I1+3YitHa7PrkIPHvbuPs+/fvrvv8/f///yH5BAEAAB8ALAAAAAAWABYAAAWN4CeOZGmeaKqubGsusPvBSyFJjVDs6nJLB0khR4AkBCmfsCGBQAoCwjF5gwquVykSFbwZE+AwIBV0GhFog2EwIDchjwRiQo9E2Fx4XD5R+B0DDAEnBXBhBhN2DgwDAQFjJYVhCQYRfgoIDGiQJAWTCQMRiwwMfgicnVcAAAMOaK+bLAOrtLUyt7i5uiUhADs=" />
</ div>
< div id = " textBox" contenteditable = " true" >
< p> Lorem ipsum</ p>
</ div>
< p id = " editMode" > < input type = " checkbox" name = " switchMode" id = " switchBox" onchange = " setDocMode(this.checked);" /> < label for = " switchBox" > Show HTML</ label> </ p>
< p> < input type = " submit" value = " Send" /> </ p>
</ form>
</ body>
</ html>
是不是很酷?
window.getSelection():文档地址
Selection
对象表示用户选择的文本范围或插入符号的当前位置。它代表页面中的文本选区,可能横跨多个元素。文本选区由用户拖拽鼠标经过文字而产生。要获取用于检查或修改的 Selection
对象,请调用 window.getSelection()
。
Selection 对象所对应的是用户所选择的 ranges (区域),俗称拖蓝。默认情况下,该函数只针对一个区域,我们可以这样使用这个函数:
var selObj = window.getSelection();
var range = selObj.getRangeAt(0);
例子: 我写了如下代码来一起探究下这两个是什么东西吧 每次我拖动完,或者点击完鼠标的时候,都会打印selObj
,查看selObj
对象,看看里面有什么属性
< body>
< div> 我是p标签的内容</ div>
< p> 我是p标签的内容</ p>
< ul>
< li> li1</ li>
< li> li2</ li>
</ ul>
</ body>
< script type = " text/javascript" >
document. onmouseup = function ( ) {
var selObj = window. getSelection ( ) ;
console. log ( selObj)
var range = selObj. getRangeAt ( 0 ) ;
console. log ( range)
}
</ script>
可以看到window.getSelection()打印的对象就是我们选中区域的对象,对象里面的属性值,我来介绍以下吧 而range对象
里面的信息就简洁很多,这个我就不介绍了,和selection对象
是一样的
当然range对象
和selection对象
原型上也有很多的方法提供给我们使用,可以自行查阅文档 selection对象的方法 range对象的方法
我们要说的是基于这些方法,我们如何做到在可编辑的div或容器中往光标处插入内容,返回光标位置
通过js的方式在可编辑区域的光标处插入文本:
方法一: 较完整的,考虑兼容,插入后,光标自动设置到插入后的位置
<! DOCTYPE html >
< html lang = " zh" >
< head>
< meta charset = " UTF-8" />
< meta name = " viewport" content = " width=device-width, initial-scale=1.0" />
< meta http-equiv = " X-UA-Compatible" content = " ie=edge" />
< title> Document</ title>
</ head>
< body>
< div class = " box" contenteditable style = " border : 1px solid red; " >
我是可编辑的div
</ div>
< button onclick = " pasteHtmlAtCaret(' 我是插入的内容' )" > 插入</ button>
</ body>
< script type = " text/javascript" >
function pasteHtmlAtCaret ( html ) {
var sel, range;
if ( window. getSelection) {
sel = window. getSelection ( ) ;
if ( sel. getRangeAt && sel. rangeCount) {
range = sel. getRangeAt ( 0 ) ;
range. deleteContents ( ) ;
var el = document. createElement ( "div" ) ;
el. innerHTML = html;
var frag = document. createDocumentFragment ( ) , node, lastNode;
while ( ( node = el. firstChild) ) {
lastNode = frag. appendChild ( node) ;
}
range. insertNode ( frag) ;
if ( lastNode) {
range = range. cloneRange ( ) ;
range. setStartAfter ( lastNode) ;
range. collapse ( true ) ;
sel. removeAllRanges ( ) ;
sel. addRange ( range) ;
}
}
} else if ( document. selection && document. selection. type != "Control" ) {
document. selection. createRange ( ) . pasteHTML ( html) ;
}
}
</ script>
</ html>
方法二: 可插入一段html字符串,可被解析
< body>
< div id = " box" contentEditable > 我是p标签的内容</ div>
</ body>
< script type = " text/javascript" >
document. getElementById ( "box" ) . onmouseup = function ( ) {
insertHtmlAtCursor ( "<strong>666</strong>" )
}
function insertHtmlAtCursor ( html ) {
var range, node;
range = window. getSelection ( ) . getRangeAt ( 0 ) ;
node = range. createContextualFragment ( html) ;
range. insertNode ( node) ;
}
</ script>
方法三: 插入一段文本
< body>
< div id = " box" contentEditable > 我是p标签的内容</ div>
</ body>
< script type = " text/javascript" >
document. getElementById ( "box" ) . onmouseup = function ( ) {
insertTextAtCursor ( "<strong>666</strong>" )
}
function insertTextAtCursor ( txt ) {
var sel = window. getSelection ( ) ;
var iEnd = sel. anchorOffset;
var htmldata = sel. anchorNode. data;
if ( htmldata) {
var finaldata = htmldata. substring ( 0 , iEnd) + txt + htmldata. substring ( iEnd) ;
sel. anchorNode. textContent = finaldata
} else {
sel. anchorNode. textContent = txt
}
}
</ script>
方法四: 插入一个节点
< body>
< div id = " box" contentEditable > 我是p标签的内容</ div>
</ body>
< script type = " text/javascript" >
document. getElementById ( "box" ) . onmouseup = function ( ) {
insertTextAtCursor ( "<strong>666</strong>" )
}
function insertTextAtCursor ( text ) {
var sel = window. getSelection ( ) ;
if ( sel. getRangeAt && sel. rangeCount) {
var range = sel. getRangeAt ( 0 ) ;
range. deleteContents ( ) ;
range. insertNode ( document. createTextNode ( text) ) ;
}
}
</ script>
总结了以上方式,大概能满足你插入的基本需求了
获取光标位置:
console. log ( window. getSelection ( ) . anchorOffset)
console. log ( window. getSelection ( ) . focusOffset)
获取选中区域的文本:
document. onmouseup = function ( ) {
console. log ( window. getSelection ( ) . toString ( ) )
}
光标移动到最后:
< body>
< div id = " box" contentEditable > 我是p标签的内容</ div>
</ body>
< script type = " text/javascript" >
document. getElementById ( "box" ) . onmouseup = function ( ) {
set_focus ( this )
}
function set_focus ( el ) {
var range = document. createRange ( ) ;
range. selectNodeContents ( el) ;
range. collapse ( false ) ;
var sel = window. getSelection ( ) ;
sel. removeAllRanges ( ) ;
sel. addRange ( range) ;
}
</ script>
记录光标和恢复光标:通过一个例子演示
< body>
< div id = " box" contentEditable > 我是p标签的内容</ div>
< button id = " saveBtn" > 记录光标位置</ button>
< button id = " restoreBtn" > 恢复光标位置</ button>
</ body>
< script type = " text/javascript" >
let range = null
document. getElementById ( "saveBtn" ) . onclick = function ( ) {
range = saveSelection ( )
}
document. getElementById ( "restoreBtn" ) . onclick = function ( ) {
restoreSelection ( range)
}
function saveSelection ( ) {
if ( window. getSelection) {
sel = window. getSelection ( ) ;
if ( sel. getRangeAt && sel. rangeCount) {
return sel. getRangeAt ( 0 ) ;
}
} else if ( document. selection && document. selection. createRange) {
return document. selection. createRange ( ) ;
}
return null ;
}
function restoreSelection ( range ) {
if ( range) {
if ( window. getSelection) {
sel = window. getSelection ( ) ;
sel. removeAllRanges ( ) ;
sel. addRange ( range) ;
} else if ( document. selection && range. select) {
range. select ( ) ;
}
}
}
</ script>
所有评论(0)