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