Get all DOM block elements for selected texts

When selecting texts in HTML documents, you can start from one DOM element to another element, possibly passing through several other elements along the way. Using the DOM API, you can get a range of selections, selected texts, and even the parent of all selected DOM elements (using commonAncestorContainer or parentElement () based on the browser you use). However, I do not know that I can specify all elements containing elements of selected texts, except for getting a single parent element that contains all of them. Using the parent element and moving the child nodes will not do this, as there may be other siblings that are not selected inside this parent.

So, is there any way that I can get all of these elements containing the selected texts. I am mainly interested in getting the elements of the block (p, h1, h2, h3, ... etc.), but I believe that if there is a way to get all the elements, then I can go through them and filter them so that get what i want. I welcome any ideas and suggestions.

Thanks.

+10
javascript dom html range selection
source share
4 answers

Key window.getSelection().getRangeAt(0) https://developer.mozilla.org/en/DOM/range

Here is an example code that you can play with to do what you want. Mentioning what you really want to be in question will help people provide better answers.

 var selection = window.getSelection(); var range = selection.getRangeAt(0); var allWithinRangeParent = range.commonAncestorContainer.getElementsByTagName("*"); var allSelected = []; for (var i=0, el; el = allWithinRangeParent[i]; i++) { // The second parameter says to include the element // even if it not fully selected if (selection.containsNode(el, true) ) { allSelected.push(el); } } console.log('All selected =', allSelected); 

This is not the most efficient way, you can traverse the DOM yourself using Range startContainer / endContainer, as well as nextSibling / previousSibling and childNodes.

+19
source share

You can use my Rangy library for this. It provides implementation of DOM Range and Selection objects for all browsers, including IE, and has additional Range methods. One of them getNodes() :

 function isBlockElement(el) { // You may want to add a more complete list of block level element // names on the next line return /h[1-6]|div|p/i.test(el.tagName); } var sel = rangy.getSelection(); if (sel.rangeCount) { var range = sel.getRangeAt(0); var blockElements = range.getNodes([1], isBlockElement); console.log(blockElements); } 
+10
source share

It looks like you could use the Transition from the jQuery API .

Maybe .contents ()

Hope this helps!

+1
source share

Here is the es6 approach based on @Juan Mendes answer:

 const selection = window.getSelection(); const range = selection.getRangeAt(0); const elementsFromAncestorSelections = range.commonAncestorContainer.getElementsByTagName("*"); const allSelectedElements = Array.from(elementsFromAncestorSelections).reduce( (elements, element) => selection.containsNode(element, true) ? [...elements, element] : elements, [], ); 
0
source share

All Articles