XPath
support.XPath
implementation in MS Edge version 11.00.10240.16397 from 07.22.2015 (according to the file version), it is 20.10240.16384.0 (according to the information in the settings)).XPath
tools I XPath
. Element.closest()
, for which, however, there is a poly file ).XPath
features that I lacked. Functions are not very convenient to use, it would be good for them to implement cheining (the possibility of call chains), but as far as I heard, it is not safe to extend the DOM
, so I did not decide to add them to Element.prototype
./following-sibling::subject[predicate]
<div> ... <p class='foo' id='point-of-view'></p> <p class='bar'></p> ... <p class='target'></p> ... </div>
p
to the unknown which account of the neighboring p
with the required class. You can organize a loop with checks of all neighbors. And you can do everything in the conditional one touch. Create a function: function findNextSibling(startNode, endSelector) { return [].filter.call(document.querySelectorAll(endSelector), function(el) { return startNode.parentNode === el.parentNode && startNode.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING; }).shift(); }
var from = document.querySelector('#point-of-view'); var to = findNextSibling(from, 'p.target')
/preceding-sibling::subject[predicate]
<div> ... <p class='target'></p> <p class='bar'></p> ... <p class='foo' id='point-of-view'></p> ... </div>
function findPrevSibling(startNode, endSelector) { return [].filter.call(document.querySelectorAll(endSelector), function(el) { return startNode.parentNode === el.parentNode && startNode.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_PRECEDING; }).pop(); }
var from = document.querySelector('#point-of-view'); var to = findPrevSibling(from, 'p.target')
/following::subject[predicate]
DOM
traversal, regardless of hierarchy relationships), but the implementation of our method will be simpler, minus one condition. <div> ... <p class='foo' id='point-of-view'></p> <p class='bar'></p> ... </div> <div> ... <div> <p class='target'></p> </div> ... </div>
function findNext(startNode, endSelector) { return [].filter.call(document.querySelectorAll(endSelector), function(el) { return startNode.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING; }).shift(); }
var from = document.querySelector('#point-of-view'); var to = findNext(from, 'p.target')
/preceding::subject[predicate]
<div> ... <div> <p class='target'></p> </div> ... </div> <div> ... <p class='bar'></p> <p class='foo' id='point-of-view'></p> ... </div>
function findPrev(startNode, endSelector) { return [].filter.call(document.querySelectorAll(endSelector), function(el) { return startNode.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_PRECEDING; }).pop(); }
var from = document.querySelector('#point-of-view'); var to = findPrev(from, 'p.target')
/ancestor-or-self::subject[predicate]
getSelection().focusNode
, since this property often corresponds to a text node). I could use the mentioned polyfil for Element.closest()
, but for the sake of consistency, I added a function in the style of the previous ones. <a href='#target'><code><b id='point-of-view'></b></code></a>
<a href='#target' id='point-of-view'></a>
function findClosestAncestorOrSelf(startNode, endSelector) { return [].filter.call(document.querySelectorAll(endSelector), function(el) { return startNode.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_CONTAINS || startNode === el; }).pop(); }
var from = document.querySelector('#point-of-view'); var to = findClosestAncestorOrSelf(from, 'a')
/descendant::subject[node-predicate]
:has()
selector, which is still not supported by any of the browsers, yep .code
element, like this: <div id='point-of-view'> ... <a href='#target'> </a> ... <a href='#target'><code> </code></a> ... <div>
function findByDescendant(contextNode, subjectSelector, predicateSelector) { return [].filter.call(contextNode.querySelectorAll(subjectSelector), function(el) { return el.querySelector(predicateSelector); }).shift(); }
var scope = document.querySelector('#point-of-view'); var target = findByDescendant(scope, 'a', 'code')
.shift()
), you can get arrays of the necessary elements, and if contextNode
set document
as the contextNode
, then the selection will be made from the entire document.Source: https://habr.com/ru/post/262853/
All Articles