dom-seek
Version:
Text traversal for HTML documents.
128 lines (90 loc) • 4.17 kB
Markdown
DOM Seek
========
[](http://opensource.org/licenses/MIT)
[](https://www.npmjs.com/package/dom-seek)
[](https://travis-ci.org/tilgovi/dom-seek)
[](https://codecov.io/gh/tilgovi/dom-seek)
POSIX has `lseek(2)`. Now the browser has `dom-seek`.
This library can answer two questions:
- What is the offset of a given `TextNode` within a text?
- Which `TextNode` within a text contains the given offset?
Installation
============
Using npm:
npm install dom-seek
Usage
=====
## `seek(iter, where)`
Adjust the position of a [`NodeIterator`] by an offset measured in text code
units or to the position immediately before a target node.
If the `whatToShow` attribute of `iter` is any value other than
`NodeFilter.SHOW_TEXT`, throw an `InvalidStateError` `DOMException`.
If `where` is a positive integer, seek the iterator forward until the sum of
the text code unit lengths of all nodes that the iterator traverses is as close
as possible to `where` without exceeding it.
If `where` is a negative integer, seek the iterator backward until the sum of
the text code unit lengths of all nodes that the iterator traverses is as close
as possible to the positive value of `where` without exceeding it.
If `where` is a node, seek the iterator forward or backward until its pointer is
positioned immediately before the target node.
If `where` is any other value, throw a `TypeError` exception.
Return the number of text code units between the initial and final iterator
positions. This number will be negative when the traversal causes the iterator
to traverse backward in document order.
If the `where` argument specifies a target beyond the bounds of the `root`
attribute of the iterator, throw a `RangError` exception.
After this function returns, the `pointerBeforeReferencNode` property of the
iterator should be `true`. The function may return a value less than `where` if
returning `where` exactly would result in the iterator pointing after the last
text node that its root node contains.
[`NodeIterator`]: https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator
Browser Support
===============
Use the `dom-node-iterator` module for a portable `NodeIterator` polyfill if
targeting browsers that lack a full implementation that includes the
`referenceNode` and `pointerBeforeReferenceNode` properties.
Example
=======
Often, when searching for text strings in HTML documents, authors will traverse
a document and look at the text of the leaf Elements. However, when the search
pattern is split across element boundaries, the problem is harder.
Below is an example of using `seek` to highlight a string in a document, even
if that string is split across element boundaries.
```javascript
var text = 'ipsum';
// Find the text.
var offset = document.body.textContent.indexOf(text);
var length = text.length;
// Create a NodeIterator.
var iter = document.createNodeIterator(document.body, NodeFilter.SHOW_TEXT);
// Seek the iterator forward by some amount, splitting the text node that
// contains the destination if it does not fall exactly at a text node boundary.
function split(where) {
var count = seek(iter, where);
var remainder = where - count;
if (remainder) {
// Split the text at the offset
iter.referenceNode.splitText(remainder);
// Seek to the exact offset
seek(iter, remainder);
}
return iter.referenceNode;
}
// Find split points
var start = split(offset);
var end = split(length);
// Walk backwards, collecting all the nodes
var nodes = [end];
while (iter.referenceNode !== start) {
nodes.unshift(iter.previousNode());
}
// Highlight all the nodes.
for (var i = 0 ; i < nodes.length ; i++) {
var node = nodes[i];
// Create a highlight
var highlight = document.createElement('mark');
// Wrap it around the text node
node.parentNode.replaceChild(highlight, node);
highlight.appendChild(node);
}
```