textRange MoveToPoint()IE

时间:2016-07-26 12:08:31

标签: javascript internet-explorer

textRange IE11的moveToPoint()方法有问题;

如果指向节点不在第一个屏幕中,它似乎不起作用;

document.addEventListener( "click", function(e) {
	var x = e.clientX; 
	var y = e.clientY; 
	var range = document.body.createTextRange();
	range.moveToPoint(x, y);
	range.expand('word');
	console.log(range);
	console.log(range.text);
});

此代码从点击点获取单词,但只有在我们点击第一次滚动的节点时才会正常。

如果我们向下滚动到第一次滚动中没有的节点,我们将捕获该异常。

有人知道如何正确处理这种情况吗?

4 个答案:

答案 0 :(得分:1)

您认为您的同事不使用stackoverflow,不是吗?在你处于试用期之前,发表检查问题并不是一个好的业力。我建议将这些信息提供给您的团队,并且您将产生一些不愉快的后果。

答案 1 :(得分:0)

您可以使用offsetX,offsetY属性。 或者,您可以使用父元素的scrollLeft和scrollTop属性将滚动位置添加到x和y变量。

答案 2 :(得分:0)

我可以确认IE11中存在这样的错误。您可以在评论中找到详细信息:http://generatedcontent.org/post/69213745095/ie11review-part1

可能的解决方案(创建范围后):

range.moveToElementText(e.target);
range.collapse(true)
range.expand("word")

现在您已选择第一个单词。您现在必须使用TextRange属性boundingHeight,boundingWidth,boundingLeft和boundingTop检查所选单词是否适合您的鼠标单击位置。如果没有,则将循环移动到下一个单词:

range.collapse(false);
range.expand("word");

答案 3 :(得分:0)

嗯,受到@dinalt和@JAYBEkster的启发,我提出了这个解决方案。也许有人会需要这个。

下面的代码(对于IE,没有检查所有版本,但它可以正常工作11+)在复杂的嵌套html中抓取单词。

逐步说明它是如何运作的:

  1. Firstable我们从e.target
  2. 创建范围
  3. 我们把它折叠到了开头。
  4. 如果我们可以扩展(“单词”)并迭代每个单词,那将是很棒的,但不幸的是我们不能。所以我们循环遍历字符将它们分成单词并将它们的边界与e.clientX和Y进行比较,另一方面通过迭代字母,我们得到更多的控制权。
  5. 我们得到正确的一个并将target.innerText与它分开,以得到节点文本的左右部分。
  6. 之后我们再次拆分每个部分,但这是我们的分隔符(带有所有白色空格的regexp和我能想象的单词分隔符),我们得到两个arr。
  7. 我们为什么要做第4步和第5步?因为我们发现一些文本在该节点中结束,但它可能不是结尾或开头的,因为一些造型的原因,我的bein它自己的节点和target.node我只是中间部分的一部分。这个单词。因此,我们必须跳过节点并找到单词的结尾。

    如果你确定你的HTML没有抱怨你可以跳过所有其他步骤。

    1. 然后如果arr为空,我们运行递归函数,该函数运行节点和抓取文本,直到找到分隔符。
    2. 是的,因为对于这样的事情,它看起来真的很像我们认为简单的任务。 但我实际上找不到更好的解决方案,有几种选择,所有这些选择并不像我需要的那样普遍。

      这段代码的好处是它根本不关心html的复杂性。

      我会在这里发布我的github repositiry的链接,你可以找到wordGraber的完整代码,当然这将适用于Chrome,Safari,FF和IE。

      https://github.com/6graNik/wordGrabber

      以下只是IE的一部分。

      function getWordFromEventIE(e) {
        const x = e.clientX;
        const y = e.clientY;
        const innerText = e.target && e.target.innerText;
        const separators = /([\s&^:;,!?(){}])+/;
        const IErange = global.document.body.createTextRange();
      
        try {
          IErange.moveToElementText(e.target);
          IErange.collapse(true);
      
          let wholeSentenceLength = 0;
          const reqIEcharTest = () => {
            do {
              IErange.expand("character");
              wholeSentenceLength += 1;
            }
            while (!separators.test(IErange.text.slice(-1)) && wholeSentenceLength <= innerText.length);
            const {boundingLeft, boundingTop, boundingWidth, boundingHeight, text} = IErange;
      
            if (boundingLeft <= x && x <= (boundingLeft + boundingWidth)
             && boundingTop <= y && y <= (boundingTop + boundingHeight)) {
              if (wholeSentenceLength <= innerText.length && !separators.test(text.slice(-1)) ) {
                return text;
              }
              return text.substr(0, text.length - 1);
            }
            IErange.collapse(false);
            return reqIEcharTest();
          };
          const text = reqIEcharTest().trim();
          const innerTextArr = innerText.split(text);
          const innerTextLeft = innerTextArr[0].split(separators);
          const innerTextRight = innerTextArr[1].split(separators);
      
          let leftPart;
          if (innerTextLeft <= 1) {
            leftPart = recursionWordGet(e.target, 'left') + innerTextLeft.slice(-1)[0];
          } else {
            leftPart = innerTextLeft.slice(-1)[0];
          }
          let rightPart;
          if (innerTextRight <= 1) {
            rightPart = innerTextRight[0] + recursionWordGet(e.target, 'right');
          } else {
            rightPart = innerTextRight[0];
          }
      
          return leftPart + text + rightPart;
        } catch (err) {
          console.log('>>>>>>>>>>>>>>>>>> text', err);
        }
      }
      
      
      function recursionWordGet(target, option) {
        const separators = /([\s&^:;,!?(){}])+/;
        const uniqString = Date.now();
      
        target.setAttribute("data-target", uniqString);
        const {parentNode} = target;
        const copyNode = parentNode.cloneNode(true);
      
        copyNode.querySelector(`[data-target="${uniqString}"]`).innerText = uniqString;
        const tagName = copyNode.tagName;
      
      
        const text = copyNode.innerText;
        const textArr = text.split(uniqString);
        const textLeftPartArr = textArr[0].split(separators);
        const textRightPartArr = textArr[1].split(separators);
      
        if (option === 'right') {
          let returnText;
          if (textRightPartArr.length <= 1 && tagName === 'span') {
            returnText = textRightPartArr[0] + recursionWordGet(parentNode, 'right');
          } else {
            returnText = textRightPartArr[0];
          }
          return returnText;
        }
      
        if (option === 'left') {
          let returnText;
          if (textLeftPartArr <= 1 && tagName === 'span') {
            returnText = recursionWordGet(parentNode, 'left') + textLeftPartArr.slice(-1)[0];
          } else {
            returnText = textLeftPartArr.slice(-1)[0];
          }
          return returnText;
        }
      
        return '';
      }