在范围上创建,设置样式

问题描述

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

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个字符?

解决方法

嘘,这是一种痛苦,但我知道了。我希望将我的解决方案添加到此处,希望至少有一些人不必做一些应该是更多“内置”的事情

//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之间的矛盾之处以及“其中”有多少个字符。

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