Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding what goes on with textarea selection with JavaScript

I am working on an in-browser editor within a textarea. I have started looking for some information on dealing with textarea selection and found this jQuery plugin, fieldSelection that does some simple manipulation.

However, it doesn't explain what's going on.

I want to understand more on textarea selection in JavaScript, preferably with a description of both pre-DOM3 and post-DOM30 scenarios.

like image 571
brad Avatar asked Dec 30 '08 21:12

brad


People also ask

What is setSelectionRange in javascript?

setSelectionRange() method sets the start and end positions of the current text selection in an <input> or <textarea> element. Optionally, in newer browser versions, you can specify the direction in which selection should be considered to have occurred.

What is Selectionstart in Javascript?

Browser support: 9. Specifies or returns the start position of the selected text within the current element. To retrieve the end position, use the selectionEnd property.

How do you value a text area?

We can get the value of textarea in jQuery with the help of val() method . The val() method is used to get the values from the elements such as textarea, input and select. This method simply returns or sets the value attribute of the selected elements and is mostly used with the form elements.

How do I hide HTML tags in textarea?

The hidden attribute hides the <textarea> element. You can specify either 'hidden' (without value) or 'hidden="hidden"'. Both are valid. A hidden <textarea> element is not visible, but it maintains its position on the page.


2 Answers

function get_selection(the_id)
{
    var e = document.getElementById(the_id);

    //Mozilla and DOM 3.0
    if('selectionStart' in e)
    {
        var l = e.selectionEnd - e.selectionStart;
        return { start: e.selectionStart, end: e.selectionEnd, length: l, text: e.value.substr(e.selectionStart, l) };
    }
    //IE
    else if(document.selection)
    {
        e.focus();
        var r = document.selection.createRange();
        var tr = e.createTextRange();
        var tr2 = tr.duplicate();
        tr2.moveToBookmark(r.getBookmark());
        tr.setEndPoint('EndToStart',tr2);
        if (r == null || tr == null) return { start: e.value.length, end: e.value.length, length: 0, text: '' };
        var text_part = r.text.replace(/[\r\n]/g,'.'); //for some reason IE doesn't always count the \n and \r in the length
        var text_whole = e.value.replace(/[\r\n]/g,'.');
        var the_start = text_whole.indexOf(text_part,tr.text.length);
        return { start: the_start, end: the_start + text_part.length, length: text_part.length, text: r.text };
    }
    //Browser not supported
    else return { start: e.value.length, end: e.value.length, length: 0, text: '' };
}

function replace_selection(the_id,replace_str)
{
    var e = document.getElementById(the_id);
    selection = get_selection(the_id);
    var start_pos = selection.start;
    var end_pos = start_pos + replace_str.length;
    e.value = e.value.substr(0, start_pos) + replace_str + e.value.substr(selection.end, e.value.length);
    set_selection(the_id,start_pos,end_pos);
    return {start: start_pos, end: end_pos, length: replace_str.length, text: replace_str};
}

function set_selection(the_id,start_pos,end_pos)
{
    var e = document.getElementById(the_id);

    //Mozilla and DOM 3.0
    if('selectionStart' in e)
    {
        e.focus();
        e.selectionStart = start_pos;
        e.selectionEnd = end_pos;
    }
    //IE
    else if(document.selection)
    {
        e.focus();
        var tr = e.createTextRange();

        //Fix IE from counting the newline characters as two seperate characters
        var stop_it = start_pos;
        for (i=0; i < stop_it; i++) if( e.value[i].search(/[\r\n]/) != -1 ) start_pos = start_pos - .5;
        stop_it = end_pos;
        for (i=0; i < stop_it; i++) if( e.value[i].search(/[\r\n]/) != -1 ) end_pos = end_pos - .5;

        tr.moveEnd('textedit',-1);
        tr.moveStart('character',start_pos);
        tr.moveEnd('character',end_pos - start_pos);
        tr.select();
    }
    return get_selection(the_id);
}

function wrap_selection(the_id, left_str, right_str, sel_offset, sel_length)
{
    var the_sel_text = get_selection(the_id).text;
    var selection =  replace_selection(the_id, left_str + the_sel_text + right_str );
    if(sel_offset !== undefined && sel_length !== undefined) selection = set_selection(the_id, selection.start +  sel_offset, selection.start +  sel_offset + sel_length);
    else if(the_sel_text == '') selection = set_selection(the_id, selection.start + left_str.length, selection.start + left_str.length);
    return selection;
}
like image 63
user357565 Avatar answered Sep 28 '22 12:09

user357565


Start with PPK's introduction to ranges. Mozilla developer connection has info on W3C selections. Microsoft have their system documented on MSDN. Some more tricks can be found in the answers here.

In addition to incompatible interfaces you'll be happy to know that there is extra bizarreness going on with textarea nodes. If I remember correctly they behave as any other nodes when you select them in IE, but in other browsers they have an independent selection range which is exposed via the .selectionEnd and .selectionStart properties on the node.

Additionally, you should really take a look at .contentEditable as a means to edit things live. From the release of Firefox3, this is now supported by all browsers.

like image 28
Borgar Avatar answered Sep 28 '22 14:09

Borgar