JavaScript Text Selection

Built for BREAD, a JavaScript Bible reader. See app at github.com/prrstn/bread

by Preston Badeer

HTML

<div class="chapter ui-selectable" translation="KJV" book="Matthew" book-id="40" chapter="1">
<span class="verse ui-selectee" verse="1"><span class="n">1</span>The book of the generation of Jesus Christ, the son of David, the son of Abraham.</span> <span class="verse ui-selectee" verse="2"><span class="n">2</span>Abraham begat Isaac; and Isaac begat Jacob; and Jacob begat Judas and his brethren;</span><span class="verse ui-selectee" verse="3"><span class="n">3</span>And Judas begat Phares and Zara of Thamar; and Phares begat Esrom; and Esrom begat Aram;</span><span class="verse ui-selectee" verse="4"><span class="n">4</span>And Aram begat Aminadab; and Aminadab begat Naasson; and Naasson begat Salmon;</span><span class="verse ui-selectee" verse="5"><span class="n">5</span>And Salmon begat Booz of Rachab; and Booz begat Obed of Ruth; and Obed begat Jesse;</span><span class="verse ui-selectee" verse="6"><span class="n">6</span>And Jesse begat David the king; and David the king begat Solomon of her that had been the wife of Urias;</span> <span class="verse ui-selectee" verse="7"><span class="n">7</span>And Solomon begat Roboam; and Roboam begat Abia; and Abia begat Asa;</span><span class="verse ui-selectee" verse="8"><span class="n">8</span>And Asa begat Josaphat; and Josaphat begat Joram; and Joram begat Ozias;</span> <span class="verse ui-selectee" verse="9"><span class="n">9</span>And Ozias begat Joatham; and Joatham begat Achaz; and Achaz begat Ezekias;</span><span class="verse ui-selectee" verse="10"><span class="n">10</span>And Ezekias begat Manasses; and Manasses begat Amon; and Amon begat Josias;</span> <span class="verse ui-selectee" verse="11"><span class="n">11</span>And Josias begat Jechonias and his brethren, about the time they were carried away to Babylon:</span><span class="verse ui-selectee" verse="12"><span class="n">12</span>And after they were brought to Babylon, Jechonias begat Salathiel; and Salathiel begat Zorobabel;</span><span class="verse...

JavaScript

/*
Documents:
http://www.quirksmode.org/dom/range%5Fintro.html
http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html
http://stackoverflow.com/questions/2955244/html-selection-range-getting-the-range-starting-node-ending-node-dista
http://stackoverflow.com/questions/2477192/use-javascript-to-extend-a-dom-range-to-cover-partially-selected-nodes
http://stackoverflow.com/questions/2494177/retrieve-parent-node-from-selection-range-in-gecko-and-webkit
*/

/* For getting selected text
var userSelection;
if (window.getSelection) {
    userSelection = window.getSelection();
} else if (document.selection) {
    userSelection = document.selection.createRange();
}*/

function getSelectedNode(pos) {
    var node, selection;
    if (window.getSelection) {
        selection = getSelection();
        if (pos == 's') node = selection.anchorNode;
        else if (pos == 'e') node = selection.focusNode;
    }
    if (!node && document.selection) {
        selection = document.selection
        var range = selection.getRangeAt ? selection.getRangeAt(0) : selection.createRange();
        node = range.commonAncestorContainer ? range.commonAncestorContainer : range.parentElement ? range.parentElement() : range.item(0);
    }
    if (node) {
        return (node.nodeName == "#text" ? node.parentNode : node);
    }
}

function getSelectionRange() {
    var sel;
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.rangeCount) {
            return sel.getRangeAt(0);
        }
    } else if (document.selection) {
        return document.selection.createRange();
    }
    return null;
}

var range;

$('.chapter > span').mouseup(function () {
    // Get Start Node
    sn = getSelectedNode('s');
    // Get End Node
    en = getSelectedNode('e');
    r = getSelectionRange();

    var sb = $(sn).parent().attr("book-id"),
        sc = $(sn).parent().attr("chapter"),
        sv = $(sn).attr("verse"),
        si = r.startOffset;

    var eb =...