Internet Explorer TextRange中的字符偏移量
时间:2020-03-06 15:02:43 来源:igfitidea点击:
据我所知,在Internet Explorer中没有简单的方法可以从TextRange对象中获取字符偏移量。 W3C Range对象具有一个节点,以及该节点内文本的偏移量。 IE似乎只有像素偏移。有创建,扩展和比较范围的方法,因此有可能编写一种算法来计算字符偏移量,但是我觉得我一定会丢失一些东西。
那么,计算Internet Explorer TextRange开头字符偏移的最简单方法是什么?
解决方案
我们可以使用String.substring()遍历body元素的TextRange.text属性,以与想要字符偏移的TextRange进行比较。
function charOffset(textRange, parentTextRange) { var parentTxt = parentTextRange.text; var txt = textRange.text; var parentLen = parentTxt.length; for(int i=0; i < parentLen ; ++i) { if (parentTxt.substring(i, txt.length+i) == txt) { var originalPosition = textRange.getBookmark(); //moves back one and searches backwards for same text textRange.moveStart("character",-1); var foundOther = textRange.findText(textRange.text,-parentLen,1); //if no others were found return offset if (!foundOther) return i; //returns to original position to try next offset else textRange.moveToBookmark(originalPosition); } } return -1; }
[findText()的参考]
我使用基于此插入符号位置技巧的方法:
// Assume r is a range: var offsetFromBody = Math.abs( r.moveEnd('character', -1000000) );
由于moveEnd返回实际移动的字符数,因此offset现在应该是距文档开头的偏移量。这对于测试原始插入符号的移动效果很好,但是对于扩展的选择以及获取持有范围锚点的确切节点,我们将需要更复杂的东西:
// where paramter r is a range: function getRangeOffsetIE( r ) { var end = Math.abs( r.duplicate().moveEnd('character', -1000000) ); // find the anchor element's offset var range = r.duplicate(); r.collapse( false ); var parentElm = range.parentElement(); var children = parentElm.getElementsByTagName('*'); for (var i = children.length - 1; i >= 0; i--) { range.moveToElementText( children[i] ); if ( range.inRange(r) ) { parentElm = children[i]; break; } } range.moveToElementText( parentElm ); return end - Math.abs( range.moveStart('character', -1000000) ); }
这应该返回正确的插入符号文本偏移量。当然,如果我们已经知道目标节点,或者能够提供上下文,则可以跳过整个循环的搜索过程。
我建议使用IERange,或者仅使用它的" TextRange"到" DOM Range"算法。
更新,2011年8月9日
我现在建议使用我自己的Rangy库,该库的概念与IERange相似,但要得到更全面的实现和支持。
我使用了一个稍微简单的解决方案,使用了textRange的偏移量值:
function getIECharOffset() { var offset = 0; // get the users selection - this handles empty selections var userSelection = document.selection.createRange(); // get a selection from the contents of the parent element var parentSelection = userSelection.parentElement().createTextRange(); // loop - moving the parent selection on a character at a time until the offsets match while (!offsetEqual(parentSelection, userSelection)) { parentSelection.move('character'); offset++; } // return the number of char you have moved through return offset; } function offsetEqual(arg1, arg2) { if (arg1.offsetLeft == arg2.offsetLeft && arg1.offsetTop == arg2.offsetTop) { return true; } return false; }