﻿///<reference name="MicrosoftAjax.js">

FocusPersister = function ()
{
    try
    {
        FocusPersister.initializeBase(this, null);

        this._prm = null;
        this._activeElement = null;
        this._excludeButtons = false;
        this._excludeLinks = false;
        this._focusDelegate = null;
        this._pageLoadedDelegate = null;
        this._selectionOnFocus = FocusPersister.prototype.SelectionOnFocus.None;
    }
    catch(err){alert(err.description);}
};

FocusPersister.prototype =
{
    initialize: function ()
    {
        this._prm = Sys.WebForms.PageRequestManager.getInstance();

        this._pageLoadedDelegate = Function.createDelegate(this, this._pageLoaded);
        this._prm.add_pageLoaded(this._pageLoadedDelegate);

        this._focusDelegate = Function.createDelegate(this, this._focus);
        if (document.body.addEventListener)
        {
            document.body.addEventListener("focus", this._focusDelegate, true);
        }
        if (document.body.attachEvent)
        {
            document.body.attachEvent("onfocusin", this._focusDelegate);
        }
    },

    get_selectionOnFocus: function ()
    {
        return this._selectionOnFocus;
    },

    set_selectionOnFocus: function (value)
    {
        this._selectionOnFocus = value;
    },

    get_excludeButtons: function ()
    {
        return this._excludeButtons;
    },

    set_excludeButtons: function (value)
    {
        this._excludeButtons = value;
    },

    get_excludeLinks: function ()
    {
        return this._excludeLinks;
    },

    set_excludeLinks: function (value)
    {
        this._excludeLinks = value;
    },

    _focus: function (e)
    {
        var element = document.activeElement || e.target || e.srcElement;

        if (this.canFocus(element) && !(this.get_excludeButtons() && this.isButton(element)) && !(this.get_excludeLinks() && this.isLink(element)))
        {
            this._activeElement = element;
        }
    },

    canFocus: function (element)
    {
        return this.isFocusableElement(element) && !element.disabled;
    },

    isFocusableElement: function (element)
    {
        return "input textarea select button a".indexOf(element.tagName.toLowerCase()) > -1 &&
            !(element.type && element.type.toLowerCase() === "hidden");
    },

    isButton: function (element)
    {
        var tagName = element.tagName.toLowerCase();
        var type = element.type ? element.type.toLowerCase() : "";

        return tagName === "button" || (tagName === "input" && (type === "submit" || type === "button" || type === "image"));
    },

    isLink: function (element)
    {
        return element.tagName.toLowerCase() === "a";
    },

    _pageLoaded: function (sender, args)
    {
        this.focusLastActiveElement();
    },

    focusLastActiveElement: function ()
    {
        try{
        if (this._activeElement && this._activeElement.id)
        {
            var _this = this;

            setTimeout(function ()
            {
                var target = $get(_this._activeElement.id);

                if (!target) return;

                try
                {
                    if (Sys.Browser.agent === Sys.Browser.InternetExplorer)
                    {
                        var oldContentEditableSetting;
                        if (typeof (target.contentEditable) !== "undefined")
                        {
                            oldContentEditableSetting = target.contentEditable;
                            target.contentEditable = false;
                        }
                        
                        target.focus();
                    }
                    else
                    {
                        target.focus();
                    }

                    if (target.scrollIntoView)
                    {
                        //target.scrollIntoView(false);
                    }
                }
                catch (e)
                {

                }
                finally
                {
                    if (typeof (oldContentEditableSetting) !== "undefined")
                    {
                        target.contentEditable = oldContentEditableSetting;
                    }
                }

                _this.updateSelectionOnFocus();
            }, 0);
        }
        }catch (err2) {}
    },

    updateSelectionOnFocus: function ()
    {
        if (!this._activeElement || !this._activeElement.value)
        {
            return;
        }

        switch (this.get_selectionOnFocus())
        {
            case FocusPersister.SelectionOnFocus.CaretToBeginning:
                this.set_caretPosition(0);
                break;

            case FocusPersister.SelectionOnFocus.CaretToEnd:
                this.set_caretPosition(this._activeElement.value.replace(/\r/g, "").length);
                break;

            case FocusPersister.SelectionOnFocus.SelectAll:
                this.applySelection(0, this._activeElement.value.length);
                break;
        }
    },

    set_caretPosition: function (position)
    {
        if (!this._activeElement)
        {
            return;
        }

        //the method fails for empty textarea elements
        if (this._activeElement.tagName.toLowerCase() == "textarea" && this._activeElement.value.length < position)
            return;

        this.applySelection(position, position);
    },

    applySelection: function (selectionStart, selectionEnd)
    {
        if (!this._activeElement)
        {
            return;
        }

        if ((Sys.Browser.agent == Sys.Browser.Opera) || !document.selection)
        {
            this._activeElement.selectionStart = selectionStart;
            this._activeElement.selectionEnd = selectionEnd;
            return;
        }

        this._activeElement.select();

        sel = document.selection.createRange();
        sel.collapse();
        sel.moveStart('character', selectionStart);
        sel.collapse();
        sel.moveEnd('character', selectionEnd - selectionStart);
        sel.select();
    },

    dispose: function ()
    {
        this._prm.remove_pageLoaded(this._pageLoadedDelegate);
        this._pageLoadedDelegate = null;

        if (document.body.removeEventListener)
        {
            document.body.removeEventListener("focus", this._focusDelegate, true);
        }
        if (document.body.detachEvent)
        {
            document.body.detachEvent("onfocusin", this._focusDelegate);
        }
        this._focusDelegate = null;
    }
};

FocusPersister.prototype.SelectionOnFocus = {
    None: 0,
    CaretToBeginning: 1,
    CaretToEnd: 2,
    SelectAll: 3
}

FocusPersister.registerClass("FocusPersister", Sys.Component);

if (typeof (Sys) !== "undefined")
{
    Sys.Application.add_init(function ()
    {
        window.FocusPersister = $create(FocusPersister, null, null, null, null);
    });
}
