JSFiddle - React, Tailwind, and code Playground
HTML
<div>click something in the searchable area</div>
<div class="searchable">
<div>
<ul>
<li>one</li>
<li><i>Lorem</i> ipsum <em>dolor</em> sit amet, consectetur adipisicing elit. Excepturi cumque earum rem placeat. Voluptas libero minima non reprehenderit <b>dignissimos</b> amet doloribus a modi nemo aut voluptatum expedita dolorem vel accusantium.</li>
<li>
<ol>
<li>three</li>
<li>four<div>inside</div></li>
<li>five</li>
</ol>
</li>
</ul>
</div>
<div>
<ul>
<li>one</li>
<li>two</li>
<li>
<ol>
<li>three</li>
<li>four</li>
<li>five</li>
</ol>
</li>
</ul>
</div>
</div>
<input type="text" class="xpathresult" size="100" />
<input type="button" class="highlight" value="highlight" />
CSS
.xpathresult {
border: 1px dashed black;
margin: 1em;
}
.searchable * {
display: block;
border: 1px solid black;
background-color: white;
}
JavaScript
document.querySelector('.searchable').addEventListener('click', xpathstring);
document.querySelector('.highlight').addEventListener('click', highlight);
function nodeindex(element, array) {
var i,
found = -1,
element_name = element.nodeName.toLowerCase(),
matched
;
for (i = 0; i != array.length; ++i) {
matched = array[i];
if (matched.nodeName.toLowerCase() === element_name) {
++found;
if (matched === element) {
return found;
}
}
}
return -1;
}
function xpath(element, suffix) {
var parent, child_index, node_name;
parent = element.parentElement;
if (parent) {
node_name = element.nodeName.toLowerCase();
child_index = nodeindex(element, parent.children) + 1;
return xpath(parent, '/' + node_name + '[' + child_index + ']' + suffix);
} else {
return '//html[1]' + suffix;
}
}
function xpathstring(event) {
var
e = event.srcElement || event.originalTarget,
path = xpath(e, '');;
document.querySelector('.xpathresult').value = path;
highlight();
}
function xquery(path) {
return document.evaluate(
path,
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null).singleNodeValue;
}
function highlight() {
var node, path;
path = document.querySelector('.xpathresult').value;
node = xquery(path);
if (!node) {
alert('invalid node');
} else {
node.style.border = '1px solid red';
node.style.backgroundColor = 'rgba(255, 0, 0, .5)'
}
}