Reputation: 1212
I have a web application that, after clicking any node in the HTML, needs to retrieve the index of that node in its parent's childNodes array. However, I am having trouble getting the currently selected node through an onclick event. The returned target of the event is the containing element
rather than the specific node
inside the element. This difference is important when text nodes exist, such as:
<div>This is Node 1<span>node 2</span>, node 3, and <span>node 4</span></div>
If you click on the spans for Node 2 or Node 4, it's straightforward to know where you are. However, if you click on the text for Node 1 and Node 3, I can't seem to find where the event would help you figure out which part of the actual content was clicked on.
This happens to be important because a later operation needs to check for certain properties either forward or backward through the document until the first match. So, if both Node 2 and Node 4 are a match for the search, I need to know if I am in Node 1 or Node 3 in order to know which one to return. For example, if searching rightwards, starting in Node 1 means that Node 2 should be returned, and starting in Node 3 means that Node 4 should be returned. Obviously, this is a simplification, but it demonstrates the issue. Does anyone know the canonical solution for this? If I can get the node object or the index, that should be sufficient. jquery is fine, but not necessary.
Upvotes: 3
Views: 1761
Reputation: 1440
Maybe somthing like this demo could help you out a bit:
document.getElementsByTagName('div')[0].addEventListener('click', function () {
var fullStr = this.innerHTML.replace(/<[^>]*>/g, ''),
sel = window.getSelection(),
str = sel.anchorNode.data,
clickPos = sel.focusOffset,
wordPosLeft = str.slice(0, clickPos + 1).search(/\S+$/),
wordPosRight = str.slice(clickPos).search(/\s/),
wordClicked,
nextWordRegex,
nextWordPosLeft,
nextWord;
if(wordPosRight < 0) {
wordClicked = str.slice(wordPosLeft);
} else {
wordClicked = str.slice(wordPosLeft, wordPosRight + clickPos);
}
nextWordRegex = new RegExp(wordClicked);
nextWordPosLeft = fullStr.search(nextWordRegex) + wordClicked.length;
nextWord = fullStr.slice(nextWordPosLeft).match(/^\s*(\S*)\s*.*$/)[1];
console.log('wordClicked: ' + wordClicked);
console.log('nextWord: ' + nextWord);
});
See this fiddle.
Upvotes: 1
Reputation: 1086
It is not possible to do this as far as I know. You cannot:
This answer gives an idea with some good insight, but does not do what you want (return the index of the node).
I believe you are out of luck, unless you can find a way to use the solution above to determine index.
Upvotes: 0
Reputation: 1636
check out even bubbling / propagation
Also: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener useCapture section
Upvotes: 0
Reputation: 3469
If you're just trying to work out the text of the element you clicked, minus child nodes text, I have a solution:
$('body').on('click', function(e) {
alert('Node Text: '+$(e.target).clone().children().remove().end().text());
});
http://jsfiddle.net/xoegujqu/1/
Essentially, delegate the click event to the highest-level element you want this to run for (in this example it just used body, but you'll probably want to be more specific). use $(e.target)
to get the element that was actually clicked, .clone()
to clone it so you can modify it without affecting the actual page content, .children().remove()
to remove all it's descendant elements, .end()
to go back to the previous jQuery selector object, then finally .text()
to get the remaining text content.
Upvotes: 0
Reputation: 6732
You need to get Your nodes in some containers. If You would click on "Node 1" text, function will return You a <div>
element. But, if You would change Your code on this:
<div>
<span>This is Node 1</span>
<span>node 2</span>
<span>, node 3, and </span>
<span>node 4</span>
</div>
it would work and return <span>
container. Not possible in other way, I think.
You can eventually make some JavaScript split() or regex operations.
Upvotes: 0