Javascript has a wide variety of functions and properties that allow you to accomplish many different kinds of tasks within a content editable container. One such task is the ability to find the containing element of the currently selected point or text.
Retrieving the selection
In most modern browsers
except Internet Explorer 9
or below, you can make use of Javascript's window.getSelection() method to retrieve a selection object.
var selection = window.getSelection();
The selection object comes with a few useful properties that contain information about a particular selection such as its offset within the content editable container and the immediate containing element of the selection.
Finding the containing element of the selection or caret
The selection object returned by window.getSelection() does include the
anchorNode
property that contains the immediate element that contains the selection or caret.
var selection = window.getSelection();
var container = selection.anchorNode;
This property returns a node object (just like the element object returned by methods such as document.getElementById).
The problem with using this property to retrieve the containing element of a selection, is that a lot of the time the immediate element that contains the selection is a text node, this means that to accurately retrieve the containing element each time, you will need to check that the element is not a text node. If the element is a text node, you will need to retrieve its parent node instead to ensure you are working with proper elements.
To solve this problem we will make use of a function that will return either the immediate containing element of the selection or its parent depending on whether it is a text node or not. To find out whether or not a node is a text node, you can make use of the nodeType property which will return 3 if the node is indeed a text node.
function getSelectionElement(){
var selection = window.getSelection();
var container = selection.anchorNode;
if( container.nodeType !== 3 ){
return container;
}
else{
// return parent if text node
return container.parentNode
}
}