[ Team LiB ] Previous Section Next Section

15.2 Converting a User Selection into an Arbitrary Element

NN n/a, IE 4(Win)

15.2.1 Problem

You want to wrap a user's body text selection in an element to assign a style that highlights the selection.

15.2.2 Solution

We begin with a paragraph container that processes a selection by way of an onmouseup event handler:

<p onmouseup="selection2Element( )">Lorem ipsum dolor sit amet, consectetaur 
adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p>

The selection2Element( ) event handler function creates an IE TextRange object whose boundaries coincide with the current selection, as reported by the browser the instant the mouse button is released on the container:

function selection2Element( ) {
    var rng = document.selection.createRange( );
    var newHTML = "<span class='newSpan'>" + rng.text + "</span>";
    rng.pasteHTML(newHTML);
}

It is assumed in this example that a style sheet rule for the newSpan class name is already defined in the document. The range's pasteHTML( ) method replaces the selection with new HTML, at which time the text immediately gains the associated style properties. The user sees nothing more than a style change of the selected text.

15.2.3 Discussion

Deploy this solution guardedly, as you can get yourself into substantial trouble without realizing it. If a user drags a selection across existing HTML container boundaries, the new HTML that the selection2Element( ) function uses to replace the selection will, at best, be ill-formed HTML that has containers overlapping each other. At worst, the action will destroy the document structure in the vicinity of the replacement.

One way to prevent such problems is to use the IE-only onselectstart event handler in addition to onmouseup. Script the onselectstart event handler to invoke a function that saves (in a global variable) a reference to the most recent element in which the selection begins (derived from the event.srcElement property). Then the selection2Element( ) function compares its event.srcElement property against the preserved value. If they are the same, it means that the selection started and ended in the same element:

// global
var selectionStart;
   
// invoked by onselectstart
function saveStart( ) {
    selectionStart = event.srcElement;
}
// invoked by onmouseup
function selection2Element( ) {
    if (event.srcElement =  = selectionStart) {
        var rng = document.selection.createRange( );
        var newHTML = "<span class='newSpan'>" + rng.text + "</span>";
        rng.pasteHTML(newHTML);
    } else {
        alert("Please restrict selections to within a single paragraph.");
    }
}

One further simplification is to move the event handler assignments to the body or document level, and assign the same class name to the paragraphs containing selectable text. Then limit execution of the inner statements of selection2Element( ) to those event.srcElement objects whose className property matches the class assignment.

The W3C DOM Range object, as implemented in the Netscape browsers through Version 7, doesn't have enough of the needed features to deploy this application.

15.2.4 See Also

Recipe 15.3 for a more advanced application of the IE TextRange object.

    [ Team LiB ] Previous Section Next Section