Reputation: 3020
I'm attempting to get the node I'm standing at after selecting the text meaning if I have the following DOM structure:
<p>
This is an example
<span style="text-transform: uppercase">text in caps</span>
some more text in here
</p>
When I select text in caps, i would like to get the node where this selection is. In this case, would be the <span>
in case I select everything of course.
I know there's a library called rangy but I think it's kinda overkill for me to use it just to get these nodes, any other way to retrieve it?
This is how I implement it so far:
var select = window.getSelection();
if (select.rangeCount) {
var $elem = $('<span>', {'style': 'text-transform: ' + type});
var range = select.getRangeAt(0).cloneRange();
var selectedNode = range.cloneContents().childNodes[0];
var nodeHasStyle = !!(selectedNode.style && selectedNode.style.textTransform.length !== 0);
if (nodeHasStyle) {
// If it's the same as previous, just toggle it by resetting the node
var currentStyle = selectedNode.style.textTransform;
selectedNode.style.textTransform = currentStyle === type ? '' : type;
}
range.surroundContents(!nodeHasStyle ? $elem.get(0) : selectedNode);
select.removeAllRanges();
select.addRange(range);
But noticed selectedNode
is not always correct. So whenever I do surroundContents, it adds a new span around the one that I should have gotten in the first place.
I'm working with summernote to toggle uppercase, lowercase text-transform over a range of selected text.
Any help would be appreciated.
Thanks.
Upvotes: 1
Views: 1289
Reputation: 449
you do not need to rely on other libraries first you need to get the selected text then find node which contained this text through xpath i.e
let text = window.getSelection().toString()
if (text) {
let xpath = "//text()[contains(., '"+ text +"')]";
let selectionNode = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}
or you can use window selection i.e window.getSelection().anchorNode.parentNode
Upvotes: 2