Highliting text in html page having only xPath, an

2019-05-26 06:31发布

I'm trying to hightlight some part of a text in a html page having only the xPath (or css path) of the selected area, an anchorOffset and a focusOffset.

I know how to manage this using the selection() method from user input, but i'm having serious difficulties trying to reproduce the same mechanism in an automathic way without the selection but only with these infos

Example: (imagine I have many others like this)

Xpath : heyThere[1]
anchorOffset  : 3
focusOffset : 45

My goal is something like this

(see pic) http://oi57.tinypic.com/68aebo.jpg

can anybody give me an hint for this task?

Thanks a lot!

1条回答
2楼-- · 2019-05-26 07:12

I don't see how a relative path like heyThere[1] would select anything in an HTML document as the root element name is html and not heyThere. As for styling a certain part, assuming you have a path leading to a text node and the offsets are inside that text node, you can create a range using the W3C DOM Level 2 Rang API, create a span with a certain CSS class as a wrapper and that way the text can be highlighted. Note that support for that DOM API is not available in older IE versions, I think only Edge on Windows 10 supports document.evaluate with XPath and I am not sure about the range support.

function highlight(textNode, start, end) {
  var range = document.createRange();
  range.setStart(textNode, start);
  range.setEnd(textNode, end);
  var span = textNode.ownerDocument.createElement('span');
  span.className = 'highlight';
  range.surroundContents(span);
}

window.onload = function() {
  var testData = [
    {
      path: 'html/body/section/h1/text()',
      start: 3,
      end: 5
    },
    {
      path: 'html/body/section/div/ul/li[2]/text()',
      start: 12,
      end: 19
    },
    {
      path: '//p',
      start: 1,
      end: 1
    }
  ];
  for (var i = 0; i < testData.length; i++) {
    var node = document.evaluate(testData[i].path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    if (node !== null) {
      highlight(node, testData[i].start, testData[i].end);
    }
    else {
      console.log('No node found for path ' + testData[i].path);
    }
  }
};
.highlight {
  color: brown;
  font-weight: bold;
}
<section>
  <h1>Example</h1>
  <div>
    <ul>
      <li>This is list item 1.</li>
      <li>This is list item 2.</li>
    </ul>
  </div>
</section>
  

I looked up the IE support, the range API is supported since IE 9 so only the XPath based access does not work, an example for IE using CSS based node selection is

function highlight(textNode, start, end) {
  var range = document.createRange();
  range.setStart(textNode, start);
  range.setEnd(textNode, end);
  var span = textNode.ownerDocument.createElement('span');
  span.className = 'highlight';
  range.surroundContents(span);
}

window.onload = function() {
  var testData = [
    {
      css: 'section > h1',
      start: 3,
      end: 5
    },
    {
      css: 'section > div > ul li:nth-child(2)',
      start: 12,
      end: 19
    },
  ];
  for (var i = 0; i < testData.length; i++) {
    var node = document.body.querySelector(testData[i].css);
    if (node !== null) {
      highlight(node.firstChild, testData[i].start, testData[i].end);
    }
    else {
      console.log('No node found for CSS selector ' + testData[i].css);
    }
  }
};
.highlight {
  color: brown;
  font-weight: bold;
}
<section>
  <h1>Example</h1>
  <div>
    <ul>
      <li>This is list item 1.</li>
      <li>This is list item 2.</li>
    </ul>
  </div>
</section>

查看更多
登录 后发表回答