Making the selection interact with the user. We will detect if there is any selection and if there is any, we will show a nice little modal box aligned to the selection.
ClientRect object
This is a really simple object, it contains the following attributes on the instance level:- top
- left
- right
- bottom
- width
- height
//returns a ClientRect object var clientRect = range.getBoundingClientRect();Using this object we can simply show up a modal dialog box after some short & basic math using jQuery:
//returns a ClientRect object var clientRect = range.getBoundingClientRect(); menu.css({ left: (rect.left + (rect.width / 2) - (menu.outerWidth(true) / 2)), top: (rect.top + rect.height + 5) }) .show();
Modifying a selection through Range
Mofiying a selection is not a big deal, you only need to keep in mind some rules:- Creating a new Range object is done through document.createRange() method.
- The range.setStart() method does NOT accept HTMLElement as a first parameter. You need to pass a TextNode (#text) type node in there.
Also, Webkit cannot select empty elements (without at least one TextNode)
Solution: use the Element.firstChild property instead of the Element - in case you only have text inside the element. Otherwise you can write a function which digs down in the Element's children and their children and returns a TextNode. - range.startContainer and range.endContainer contains the TextNodes where the selection begins and ends. They point to the same TextNode if there is no selection or the selection does not flow out from a TextNode.
- range.startOffset and range.endOffset represent the numbers (positions) where the selection ends. Watch for the positions, they return the "distance" from the beginning of their TextNode, NOT the distance from the parent Element. We used a method to merge these separate TextNodes and another to get the "absolute" position of the caret.
//creating a new range object var newRange = document.createRange(); //setting up the new range object created at the beginning of the scope newRange.setStart(theTextNodeYouPreviouslyFound, start); //removeing all range objects and adding the new one selection.removeAllRanges(); selection.addRange(newRange);So putting it all together, I have created this small dummy interaction, check it out at this jsfiddle. It is simple, right? =) Just enough for a weekend demonstration. =)