【问题标题】:Creating, setting styles on a range在范围内创建、设置样式
【发布时间】:2021-01-02 15:38:55
【问题描述】:

我正在尝试自动检测页面上的地址并在找到的位置添加“地址”类。

var rangyPatternApplier = function(element, pattern, style) {
  var innerText = element.innerText;
  var matches = innerText.match(pattern);
  if (matches) {
    for (var i = 0; i < matches.length; i++) {
      console.log("Match: " + matches[i]);
      var start = innerText.indexOf(matches[i]);
      var end = start + matches[i].length;

      let range = document.createRange();
      var start = innerText.indexOf(matches[i]);
      console.log('inner text: ' + innerText);
      console.log('start: ' + start);
      console.log('starts with: ' + innerText.substring(start));
      var end = start + matches[i].length;
      var startNode = element.childNodes[0];
      var endNode = startNode;
      while (startNode.nodeValue.length < start) {
        start -= startNode.nodeValue.length;
        end -= startNode.nodeValue.length;
        startNode = startNode.nextSibling;
        endNode = startNode;
        if (startNode == null) {
          error.reportError("Just wrong in Sections.rangyPatternApplier");
          return;
        }
      }
      while (endNode.nodeValue.length < end) {
        end -= endNode.nodeValue.length;
        if (endNode.nextSibling) endNode = endNode.nextSibling;
        while (!endNode.nodeValue) {
          endNode = endNode.childNodes[0];
        }
        if (endNode == null) {
          error.reportError("Just wrong in Sections.rangyPatternApplier");
        }
      } 
      range.setStart(startNode, start);
      console.log("starts with: " + startNode.nodeValue.substring(start));
      range.setEnd(endNode, end);

          var applier  = rangy.createClassApplier(style, {
                    elementTagName: "span",
                    elementProperties: {
                    },
          });
      window.getSelection().addRange(range);
      applier.toggleSelection();
    }
  }
}

调用方式:

  $("P").each(function () {
    rangyPatternApplier(this, new RegExp("\\d+\\s[A-z]+\\s[A-z0-9]+\\s(Street|St|Avenue|Av|Ave|Road|Rd)", "mgi"), "Address");
  });

段落中的文字:

If the income renders the household ineligible for CA/CILOCA, the case will be systemically referred to the Administration for Children s Services Transitional Child Care Unit at 109 East 16th Street 3rd floor for evaluation of Transitional Child Care (TCC) benefits. The TCC Worker determines eligibility for up to 12 months of TCC benefits.

正则表达式正在运行,正在应用地址类。我将范围应用于窗口选择,因为仅在范围上应用时似乎存在错误(我收到一条错误消息)。但不知何故,当我创建范围时,跨度出现在地址开始前 5 个字符并提前结束 9 个字符。提前结束的部分可能是由于第 16 街的“th”周围的标签。但是为什么范围比我在 innerText 中找到的要早 5 个字符?

【问题讨论】:

    标签: javascript jquery textselection rangy


    【解决方案1】:

    哎呀,这很痛苦,但我得到了它的工作。在我看来,在这里添加我的解决方案,希望至少有几个人不必做一些应该更“内置”的事情

    //nextTextNode is for getting the next text node from the DOM
    
    function nextTextNode(node) {
      if (node.nodeType == 1) { //element
        while (node.nodeType != 3) {
          node = node.firstChild;
        }
        return node;
      }
      if (node.nodeType == 3) { //text node
        if (node.nextSibling) {
          if (node.nextSibling.nodeType == 3) {
            return node.nextSibling;
          } else {
            return nextTextNode(node.nextSibling);
          }
        } else {
          while (!node.nextSibling) {
            node = node.parentNode;
            if (!node) return null;
          }
          if (node.nextSibling.nodeType == 3) {
            return node.nextSibling;
          } else {
            return nextTextNode(node.nextSibling);
          }
        }
      } else {
        throw new Error("nextTextNode: Node is either null, not connected to the DOM, or is not of node type 1 or 3");
      }
    }
    

    然后创建范围。与 element.innerText 相比,文本节点具有额外的换行符和空格字符。在下面的函数中,我跟踪额外字符数和总字符数,以跟踪 innerText 和 node.nodeValue 之间的不一致以及它有多少个“in”字符。

    function createRangeForString(startElement, text) {
      var extras = 0;
      var innerText = startElement.innerText;
      var start = innerText.indexOf(text);
      if (start === -1) throw new Error ("createRangeForString. text: " + text + " not found in startElement");
      var textNode = nextTextNode(startElement);
      var totalCharsSeen = 0;
      var range = document.createRange();
      for (var i = 0; i < start; i++) { // I don't think I have to add extras in limit for i. Is already included
        if ((i + extras) - totalCharsSeen >= textNode.nodeValue.length) { //check if textNode is long enough
          totalCharsSeen += textNode.nodeValue.length;
          textNode = nextTextNode(textNode);
        }
        while (textNode.nodeValue.charAt(i + extras - totalCharsSeen) == "\n") {
          extras++;
        }
        while (textNode.nodeValue.charAt(i + extras - totalCharsSeen) == " " && innerText.charAt(i) != " ") {
          extras++;
        }
      }
      range.setStart(textNode, i + extras - totalCharsSeen);
    
      var end = start + text.length;
    
      for (var i = start + 1; i < end; i++) { // I don't think I have to add extras in limit for i. Is already included
        if ((i + extras) - totalCharsSeen >= textNode.nodeValue.length) { //check if textNode is long enough
          totalCharsSeen += textNode.nodeValue.length;
          textNode = nextTextNode(textNode);
        }
        while (textNode.nodeValue.charAt(i + extras - totalCharsSeen) == "\n") {
          extras++;
        }
        while (textNode.nodeValue.charAt(i + extras - totalCharsSeen) == " " && innerText.charAt(i) != " ") {
          extras++;
        }
      }
      range.setEnd(textNode, i + extras - totalCharsSeen);
      return range;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-21
      • 1970-01-01
      相关资源
      最近更新 更多