Snap selection to word.
Currently extends both sides each time you snap. :(
by inactivist
HTML
<button onClick="javascript:snapSelectionToWord();">Snap</button>
<div contenteditable="true" onmouseup="snapSelectionToWord()">
<p>Hello, <b>her</b>e is some <i>nice text</i>. Please try selecting some text.</p>
<p><b><u>Then, click the [Snap] button a few times just for fun.</u></b></p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas nisi lorem, semper consequat consequat id, interdum vel purus. Phasellus ipsum tortor, adipiscing nec egestas sed, rhoncus sed urna. Suspendisse ultrices neque felis. Maecenas id orci ut lectus luctus lacinia quis et mauris. Ut pretium, ipsum in hendrerit consequat, mauris lorem pulvinar nulla, vel tristique lorem ligula eget nisi. Proin pulvinar nibh vel felis tempor eget ornare lorem egestas. Morbi molestie viverra turpis, pulvinar tristique diam mollis non. Phasellus facilisis justo a ipsum faucibus lacinia. Quisque sit amet ultrices nulla.</p>
<p>Etiam lacinia odio in nisi porttitor dapibus. Maecenas vitae nulla purus, a eleifend est. Vivamus ut quam nibh, euismod imperdiet elit. Praesent nisl sapien, suscipit sit amet cursus vehicula, facilisis eu ligula. Nunc dapibus erat sed odio elementum non fringilla leo semper. Fusce vitae tellus sem. Nam sit amet euismod ipsum. Sed pharetra tempor pharetra. Etiam congue elit quis nisi pretium eget facilisis dolor malesuada. Etiam blandit velit eu purus semper ut malesuada eros rutrum. Morbi ullamcorper pretium metus, at pretium nisl lacinia sit amet. In pellentesque porttitor risus et sodales. In hac habitasse platea dictumst.</p>
</div>
CSS
p {margin-bottom: 1.3em;}
JavaScript
function snapSelectionToWord() {
var sel;
// Check for existence of window.getSelection() and that it has a
// modify() method. IE 9 has both selection APIs but no modify() method.
if (window.getSelection && (sel = window.getSelection()).modify) {
sel = window.getSelection();
if (!sel.isCollapsed) {
// Detect if selection is backwards
var range = document.createRange();
range.setStart(sel.anchorNode, sel.anchorOffset);
range.setEnd(sel.focusNode, sel.focusOffset);
var backwards = range.collapsed;
range.detach();
// modify() works on the focus of the selection
var endNode = sel.focusNode, endOffset = sel.focusOffset;
sel.collapse(sel.anchorNode, sel.anchorOffset);
if (backwards) {
sel.modify("move", "forward", "word");
sel.extend(endNode, endOffset);
sel.modify("extend", "backward", "word");
} else {
sel.modify("move", "backward", "word");
sel.extend(endNode, endOffset);
sel.modify("extend", "forward", "word");
}
}
} else if ( (sel = document.selection) && sel.type != "Control") {
var textRange = sel.createRange();
if (textRange.text) {
textRange.expand("word");
// Move the end back to not include the word's trailing space(s),
// if necessary
while (/\s$/.test(textRange.text)) {
textRange.moveEnd("character", -1);
}
textRange.select();
}
}
}