1

I would like to create a function that select a given text inside a HTML element.

For example calling selectText('world') would select world in a markup like <span>Hello </span><strong>world</strong>!

Lots of answers on similar questions suggests to use range and selection but none of them work in my case (some would select all the text, some won't work with such markup, ...).

For now this is what I have (it doesn't work):

function selectText ( element, textToSelect ) { var text = element.textContent, start = text.indexOf( textToSelect ), end = start + textToSelect.length - 1, selection, range; element.focus(); if( window.getSelection && document.createRange ) { range = document.createRange(); range.setStart( element.firstChild, start ); range.setEnd( element.lastChild, end ); selection = window.getSelection(); selection.removeAllRanges(); selection.addRange( range ); } else if (document.body.createTextRange) { range = document.body.createTextRange(); range.moveToElementText( element ); range.moveStart( 'character', start ); range.collapse( true ); range.moveEnd( 'character', end ); range.select(); } } 

Here is a jsfiddle so you see what is actually happening: http://jsfiddle.net/H2H2p/

Outputed error :

Uncaught IndexSizeError: Failed to execute 'setStart' on 'Range': The offset 11 is larger than or equal to the node's length (5). 

P.S.: no jQuery please :)

3
  • Here's how you select the text, jsfiddle.net/H2H2p/1, it's setStart(node, offset), and you're getting the offset from the text only, so it's 11, but the textnode you're targeting doesn't have 11 characters, so you end up with an error. Commented Jun 1, 2014 at 13:55
  • jsfiddle.net/H2H2p/2 Commented Jun 1, 2014 at 14:06
  • @adeneo Thank you, I feel much closer to my goal :) Do you see a way to make it work if I want to select Hello wo in <span>Hello </span><strong>world</strong>! ? Commented Jun 1, 2014 at 14:28

1 Answer 1

2

You could use a combination of your approach of finding the text within the element's textContent and this function.

Demo: http://jsfiddle.net/H2H2p/3/

Code:

function selectText(element, textToSelect) { var elementText; if (typeof element.textContent == "string" && document.createRange && window.getSelection) { elementText = element.textContent; } else if (document.selection && document.body.createTextRange) { var textRange = document.body.createTextRange(); textRange.moveToElement(element); elementText = textRange.text; } var startIndex = elementText.indexOf(textToSelect); setSelectionRange(element, startIndex, startIndex + textToSelect.length); } function getTextNodesIn(node) { var textNodes = []; if (node.nodeType == 3) { textNodes.push(node); } else { var children = node.childNodes; for (var i = 0, len = children.length; i < len; ++i) { textNodes.push.apply(textNodes, getTextNodesIn(children[i])); } } return textNodes; } function setSelectionRange(el, start, end) { if (document.createRange && window.getSelection) { var range = document.createRange(); range.selectNodeContents(el); var textNodes = getTextNodesIn(el); var foundStart = false; var charCount = 0, endCharCount; for (var i = 0, textNode; textNode = textNodes[i++]; ) { endCharCount = charCount + textNode.length; if (!foundStart && start >= charCount && (start < endCharCount || (start == endCharCount && i < textNodes.length))) { range.setStart(textNode, start - charCount); foundStart = true; } if (foundStart && end <= endCharCount) { range.setEnd(textNode, end - charCount); break; } charCount = endCharCount; } var sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); } else if (document.selection && document.body.createTextRange) { var textRange = document.body.createTextRange(); textRange.moveToElementText(el); textRange.collapse(true); textRange.moveEnd("character", end); textRange.moveStart("character", start); textRange.select(); } } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.