【问题标题】:Character offset in an Internet Explorer TextRangeInternet Explorer TextRange 中的字符偏移
【发布时间】:2010-09-14 21:59:18
【问题描述】:

据我所知,没有简单的方法可以从 Internet Explorer 中的 TextRange 对象中检索字符偏移量。 W3C Range 对象有一个节点,以及该节点内文本的偏移量。 IE 似乎只有像素偏移。有一些方法可以创建、扩展和比较范围,因此可以编写一个算法来计算字符偏移量,但我觉得我一定遗漏了一些东西。

那么,计算 Internet Explorer TextRange 起始字符偏移的最简单方法是什么?

【问题讨论】:

  • 是否要统计范围开始前屏幕左侧的字符数?

标签: javascript html internet-explorer selection dhtml


【解决方案1】:

我使用一种基于此插入符号位置技巧的方法:

// 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) );
}

这应该返回正确的插入符号文本偏移量。当然,如果你已经知道目标节点,或者能够提供上下文,那么你可以跳过整个循环搜索的混乱。

【讨论】:

    【解决方案2】:

    我建议IERange,或者只是TextRange-to-DOM Range 算法。

    2011 年 8 月 9 日更新

    我现在建议使用我自己的 Rangy 库,该库在理念上与 IERange 相似,但实现和支持更全面。

    【讨论】:

      【解决方案3】:

      我使用了一个稍微简单的解决方案,使用 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;
      }
      

      【讨论】:

        【解决方案4】:

        您可以使用 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;
         }
        

        [Reference for findText()]

        【讨论】:

        • 在这种情况下,你最好使用bodyTxt.indexOf(txt),这确实是我的第一个方法。但是,如果范围内的文本在任何地方重复,它会丢弃这个数字。需要明确的是,它是包含我感兴趣的选择的节点内的偏移量,而不是整个主体内的偏移量。
        • 我更新了我的解决方案以接受父节点并检查重复的文本。
        猜你喜欢
        • 2014-05-08
        • 2016-10-16
        • 2013-06-12
        • 2012-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多