// Cross Browser selectionStart/selectionEnd
// Version 0.2
// Copyright (c) 2005-2007 KOSEKI Kengo
// 
// This script is distributed under the MIT licence.
// http://www.opensource.org/licenses/mit-license.php

function SelectVersion(){
    return "1.0";
}

// this is the range class that is returned from new Selection(txt).create()
var resultObj = Class.create({
    initialize: function(el, txt, rng, start, end){
        this.element = el;
        this.text = txt;
        this.range = rng;
        this.start = start;
        this.end = end;
    },
    setText: function(_newText){
        this.range.setText(_newText);
    }
});

// this is the class that creates and returns the range class defined above
var Selection = Class.create({
    initialize: function(textareaElement) {
        this.element = textareaElement;
    },
    
    // this is the only "public" function of this class
    create: function() {
        if (document.selection != null && this.element.selectionStart == null) {
            return this._ieGetSelection();
        } else {
            return this._mozillaGetSelection();
        }
    },
    
    setRange: function(start,end){
        if(document.selection != null && this.element.selectionStart == null){
            return this._ieSetRange(start,end);
        } else {
            return this._mozillaSetRange(start,end);
        }
    },

    _mozillaGetSelection: function() {
        return new resultObj( 
            this.element,
            $F(this.element).substring(this.element.selectionStart, this.element.selectionEnd),
            {
                element: this.element,
                setText: function(_newText){
                    var txt = $F(this.element).substring(this.element.selectionStart, this.element.selectionEnd);
                    if(txt.length == 0)
                    {
                        var val = $(this.element).value;
                        
                        $(this.element).value = val.substring(0, this.element.selectionStart) + _newText + val.substring(this.element.selectionStart, this.element.value.length);
                    }
                    else
                        {$(this.element).value = $F(this.element).replace(txt, _newText);}}
            },
            this.element.selectionStart, 
            this.element.selectionEnd
        );
    },

    _ieGetSelection: function() {
        this.element.focus();

        var range = document.selection.createRange();
        var bookmark = range.getBookmark();

        var contents = this.element.value;
        var originalContents = contents;
        var marker = this._createSelectionMarker();
        while(contents.indexOf(marker) != -1) {
            marker = this._createSelectionMarker();
        }

        var parent = range.parentElement();
        if (parent == null || 
            (parent.type != "textarea" && parent.type != "text")) {
            return new resultObj(this.element, range.text, range, 0,0);
        }
        range.text = marker + range.text + marker;
        contents = this.element.value;

        var result = {};
        result.start = contents.indexOf(marker);
        contents = contents.replace(marker, "");
        result.end = contents.indexOf(marker);

        this.element.value = originalContents;
        range.moveToBookmark(bookmark);
        range.select();

        //return result;
        
        range.setText = function(txt){this.text = txt;}
        
        return new resultObj(this.element, range.text, range, result.start, result.end);
        
        // extend result to have
        //  element: this.element,
        //  setText: function(_newText){
    },

    _createSelectionMarker: function() {
        return "##SELECTION_MARKER_" + Math.random() + "##";
    },
    
    _mozillaSetRange: function(start,end){
        this.element.selectionStart = start; 
        this.element.selectionEnd = end;
    },
    
    _ieSetRange: function(start, end){
        var range = this.element.createTextRange();
        range.collapse(true);
        range.moveEnd('character',end);
        range.moveStart('character', start);
        range.select();
    }
}); // end Class.create()

