﻿var 
 _f = function () {
     Page = {};
     Application = parent.Application;


     Page.Initialize = function (props) {
         debugger;
         var p = JSON.parse(props);
         for (var i in p) Page[i] = p[i];

         if (Application) {
             var t = Application.GetTab(window);
             if (t) {
                 t.Window = window;
                 t.Page = Page;
             }
         }
     };
 } ();

function TabStrip_Menu_TabBeforeSelect(sender, e) {
    var item = e.get_tab();
    if (item.get_value()) {
        e.set_cancel(true);
        Application.OpenTab(item.get_id() || Guid.NewGuid(), item.get_value(), item.get_text());
    }
};


function TabStrip_Menu_Load(sender, e) {
    sender.selectTabById(sender.get_tabs().getTab(0).get_id());
};

function Logout() {
    PageMethods.Logout(function () {
        $("input[Login]").each(function () {
            $(this).val($(this).attr("DefaultText"));
        });

        $("#div_profile_loggedin").fadeOut(500, function () {
            $("#div_profile_login").fadeIn();
        });

        window.location.href = "/";

    }, null);
};

function DoLogin() {
    debugger;
    var valid = true;
    $("input[Login]").each(function () {
        if (!$(this).val() || $(this).val() == $(this).attr("DefaultText")) {
            valid = false;
            this.focus();
            $(this).addClass("LoginTextInvalid");
        }
        else {
            $(this).removeClass("LoginTextInvalid");
        }
    });

    function onSuccess(res) {
        $("#div_connecting").fadeOut(500, function () {
            var result = JSON.parse(res);

            // invalid username/password/diactive
            if (result.LoginResult != 0) {
                $("#div_profile_login").fadeIn(500);
                $("#div_profile_login_body").slideDown(200);
                $("input[Login]").addClass("LoginTextInvalid");
                document.getElementById("txt_login").focus();
            }
            else {
                $("#div_gender").html(result.User.Gender == "1" ? "آقای " : "خانم ");
                $("#div_username").html(result.User.FirstName + " " + result.User.LastName);
                $("#div_date").html(result.Date);
                document.getElementById("img_profile").src = result.User.ImageUrl;
                $("#div_profile_loggedin").fadeIn();
            }
        });
    };

    function onError() {
        $("#div_connecting").fadeOut(500, function () {
            $("#div_profile_login").fadeIn(500);
        });
        alert("اشکال در ارتباط با سرور");
    };

    if (valid) {
        $("#div_profile_login_body").slideUp(100, function () {
            $("#div_profile_login").fadeOut(400, function () {
                $("#div_connecting").fadeIn(400, function () {
                    PageMethods.Login($("#txt_login").val(), $("#txt_password").val(), onSuccess, onError);
                });
            });
        });
    }

    return false;
};

$(document).ready(function () {
    $("#div_profile_login_header").click(function () {
        $("#div_profile_login_body").slideDown(200);
    });

    $("#div_profile_loggedin_header").click(function () {
        $("#div_profile_loggedin_body").slideDown(200);
    });

    $("#div_profile").click(function (e) {
        e.stopPropagation();
    });

    $(document).click(function () {
        $("#div_profile_login_body").slideUp(100);
        $("#div_profile_loggedin_body").slideUp(100);
    });

    $("input[DefaultText]")
        .focus(function () {
            if ($(this).val() == $(this).attr("DefaultText")) {
                $(this).val("");
            }
        })
        .blur(function () {
            if ($(this).val() == "") {
                $(this).val($(this).attr("DefaultText"));
            }

            if ($(this).val() != "" && $(this).val() != $(this).attr("DefaultText")) {
                $(this).removeClass("LoginTextInvalid");
            }
        })
        .each(function () {
            this.value = $(this).attr("DefaultText");
        });
});


$(document).keydown(function (e) {
    if (e.keyCode == 13) {
        var res = false;
        if (window.Page_PressEnter)
            res = Page_PressEnter();

        if (res) {
            e.stopPropagation();
            e.preventDefault();
        }
    }
});


function TabStrip_Menu_Load(sender, e) {
    sender.selectTabById(TabStrip_Menu.getTabs(0).get_id());
    setTimeout(RenderMenu, 20);
};

function TabStrip_Menu_TabMouseOver(sender, e) {
    var tab = e.get_tab();
    var isGroupTab = Enumerable.From(TabStrip_Menu.getTabs()).Any(function (t) { return t.get_id() == tab.get_id() });
    if (isGroupTab) {
        sender.selectTabById(tab.get_id());
        RenderMenu();
    }
};


function Menu_Main_ItemBeforeSelect(sender, e) {
    var item = e.get_item();
    if (item.get_value()) {
        window.location.href = item.get_value();
    }
};


function RenderMenu() {
    var selectedTab = TabStrip_Menu.getSelectedTab();

    Menu_Main.beginUpdate();
    Enumerable.From(Menu_Main.get_items().get_itemArray()).ForEach(function (t) {
        t.set_visible(t.getProperty("Tab") == selectedTab.get_value());
    });
    Menu_Main.endUpdate();
};

Page.Load = function () {
};


Page.Alert = function (title, text, handler) {
    if (parent.Dialog1) {
        parent.Dialog1.Handler = handler;
        parent.Dialog1.OK = true;
        parent.Dialog1.set_title(title || " ");
        parent.Dialog1.set_content(text || " ");
        parent.Dialog1.show();
    }
    else {
        alert(text);
        if (handler) handler();
    }
};


Guid = {};
Guid.NewGuid = function () {
    var S4 = function () {
        return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
    };
    return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
};


Page.GetElement = function (id) {
    return document.getElementById(id) || {};
};


Page.GetElements = function (bound) {
    return Enumerable.From($(bound));
};

checkEmail = function (email) {
    var filter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
    return filter.test(email);
};

String.prototype.startsWith = function(prefix) {
    return this.indexOf(prefix) === 0;
}

Page.SetDefValue = function (ID) {

    var Element = document.getElementById(ID);

    $(Element).focus(function () {
        if ($(this).val() == $(this).attr("Errtxt")) {
            $(this).val("");
        }
    })
        .blur(function () {
            if ($(this).val() == "") {
                $(this).val($(this).attr("Errtxt"));
            }

            if ($(this).val() != "" && $(this).val() != $(this).attr("Errtxt")) {
                $(this).removeClass("LoginTextInvalid");
            }
        })
        .each(function () {
            this.value = $(this).attr("Errtxt");
        });

};

Page.getErrtxt = function (ID) {
    var Element = document.getElementById(ID);
    return $(Element).attr('Errtxt');
};

Page.checkLang = function (ID) {
    var Element = document.getElementById(ID);
    return /^[A-Za-z][A-Za-z0-9 /-_]*$/.test(Element.value);
};


Page.Validate = function () {
    {
        var req = this.GetElements("[RequiredF=true]");
        var reqEmpty = req.Where(function (t) { return t.value == '' || t.value == Page.getErrtxt(t.id) });

        req.ForEach("t => t.className = 'TextInput'");

        if (reqEmpty.Count() > 0) {
            reqEmpty.First().focus();
            reqEmpty.ForEach("t => t.className = 'Required' , Page.SetDefValue(t.id)");
            return false;
        }
        else {
            req.ForEach("t => t.className = 'TextInput'");
        }
    }

    {
        var emails = this.GetElements("[email=true]");
        var invalidEmails = emails.Where(function (t) { return t.value != '' && !t.disabled && (!checkEmail(t.value) ||  t.value.startsWith('www.'))});

        emails.ForEach("t => t.className = 'TextInput'");

        if (invalidEmails.Count() > 0) {
            invalidEmails.First().focus();
            invalidEmails.ForEach("t => t.className = 'Required' , Page.SetDefValue(t.id)");
            return false;
        }
        else {
            emails.ForEach("t => t.className = 'TextInput'");
        }
    }

    {
        var numbers = this.GetElements("[number=true]");
        var invalidNumbers = numbers.Where(function (t) { return t.value != '' && !t.disabled && isNaN(t.value) });

        numbers.ForEach("t => t.className = 'TextInput'");

        if (invalidNumbers.Count() > 0) {
            invalidNumbers.First().focus();
            invalidNumbers.ForEach("t => t.className = 'Required' , Page.SetDefValue(t.id)");
            return false;
        }
        else {
            numbers.ForEach("t => t.className = 'TextInput'");
        }
    }

    {
        var mobile = this.GetElements("[mobile=true]");
        var invalidmobile = mobile.Where(function (t) { return t.value != '' && !t.disabled && (t.value.length != 10 || t.value.startsWith('0')) });

        mobile.ForEach("t => t.className = 'TextInput'");

        if (invalidmobile.Count() > 0) {
            invalidmobile.First().focus();
            invalidmobile.ForEach("t => t.className = 'Required' , Page.SetDefValue(t.id)");
            return false;
        }
        else {
            mobile.ForEach("t => t.className = 'TextInput'");
        }
    }


    {
        var numbers10 = this.GetElements("[number10=true]");
        var invalidNumbers10 = numbers10.Where(function (t) { return t.value != '' && !t.disabled && t.value.length != 10 });

        numbers10.ForEach("t => t.className = 'TextInput'");

        if (invalidNumbers10.Count() > 0) {
            invalidNumbers10.First().focus();
            invalidNumbers10.ForEach("t => t.className = 'Required' , Page.SetDefValue(t.id)");
            return false;
        }
        else {
            numbers10.ForEach("t => t.className = 'TextInput'");
        }
    }

    {
        var LangEn = this.GetElements("[LangEn=true]");
        var invalidLangEn = LangEn.Where(function (t) { return !Page.checkLang(t.id) });

        LangEn.ForEach("t => t.className = 'TextInput'");

        if (invalidLangEn.Count() > 0) {
            invalidLangEn.First().focus();
            invalidLangEn.ForEach("t => t.className = 'Required' , Page.SetDefValue(t.id)");
            return false;
        }
        else {
            LangEn.ForEach("t => t.className = 'TextInput'");
        }
    }



    return true;
};


Page.Reset = function () {
    Page.GetElement("form1").reset();
    Page.GetElements(":text").ForEach("t => t.value = ''");
    Page.GetElements(":password").ForEach("t => t.value = ''");
    Page.GetElements("textarea").ForEach("t => t.value = ''");
};

Page.IsAddMode = function () {
    return this.Mode == "Add";
};

Page.IsEditMode = function () {
    return this.Mode == "Edit";
};

Page.SetAddMode = function () {
    this.Mode = "Add";
};

Page.SetEditMode = function () {
    this.Mode = "Edit";
};

var callback = null;
var className = null;
var saveSuccess = null;
var saveError = null;

Page.RegisterSaveMethod = function (callbackMethod, objClassName, onSaveSuccess, onSaveError) {
    callback = callbackMethod;
    className = objClassName;
    saveSuccess = onSaveSuccess;
    saveError = onSaveError;
};

Page.Save = function (validate) {

    if (Page.Validate() && (!validate || validate())) {
        if (callback && PageMethods[callback]) {

            var input = null;
            var inputJSON = null;

            if (className) {
                input = new className();
                input.ID = !Page.IsEditMode() ? Guid.NewGuid() : Page.ID;

                inputJSON = JSON.stringify(input);
            }


            var success = function (res) {
                var result = JSON.parse(res);

                if (result.Error) {
                    //alert("اشکال در انجام عملیات. " + result.Error);
                }
                else if (result.Success) {
                    Page.SetEditMode();
                    Page.ID = input ? input.ID : null;

                    document.getElementById("__PageProperties").value = JSON.stringify({ Properties: Page.Properties, Mode: Page.Mode, ID: Page.ID });

                    var msg = result.Value;
                    var showAlert = false;

                    switch (result.Value) {
                        case 0:
                            msg = "عملیات با موفقیت انجام شد";
                            showAlert = true;
                            break;

                        case 1:
                            msg = "اشکال در انجام عملیات";
                            showAlert = true;
                            break;

                        case 2:
                            msg = "سند مورد نظر یافت نشد";
                            showAlert = true;
                            break;

                        case 3:
                            msg = "اطلاعات ناقص است";
                            showAlert = true;
                            break;

                        case 4:
                            Page.SetAddMode();
                            msg = "شناسه تکراری می باشد";
                            showAlert = true;
                            break;

                        case 5:
                            Page.SetAddMode();
                            msg = "پست الکترونیک تکراری می باشد";
                            showAlert = true;
                            break;

                        case 6:
                            Page.SetAddMode();
                            msg = "کد ملی تکراری می باشد";
                            showAlert = true;
                            break;

                    }

                    if (!showAlert) {
                        if (saveSuccess) saveSuccess(result.Value);
                    }

                    else {
                        if (saveSuccess) saveSuccess(result.Value);
                    }
                }
                else {
                    //Page.Alert(" ", result.Value || "اشکال در انجام عملیات.");
                }
            };

            var error = function (res) {
                if (saveError) saveError(res);
            };

            PageMethods[callback](inputJSON, Page.Mode, success, error);
        }
    }

    return false;
};

Page.Postback = function (validate) {
    if (Page.Validate() && (!validate || validate())) {
        __doPostBack();
    }

    return false;
};






_f = function () {

    var grids = [];

    function IsPageControlsLoaded() {
        for (var i in window) {
            if (i.indexOf("ComponentArt_Init_") == 0) {
                var c = i.replace("ComponentArt_Init_", "");
                if (window[c] && window[c].nodeName != null) return false;
            }
        }

        return true;
    };

    function Render() {

        try {
            var h = __geometry.getViewportHeight();
            document.getElementById("table_main").style.height = h + "px";
            Enumerable.From(grids).ForEach(function (t) {
                //t.set_pageSize(Math.floor((Math.min(document.getElementById(t.Id).parentNode.clientHeight, h) - 100) / 20));
                t.render();
            });
        }
        catch (ex) { }
    };

    $(document).ready(function () {

        $("[required=true]").blur(function () {
            var el = $(this)[0];
            el.className = el.value == "" ? "Required" : "TextInput";
        });

        $(":text").focus(function () {
            var el = $(this)[0];
            setTimeout(function () {
                el.select();
            }, 1);
        });

        Page.GetElements(":text").ForEach("t => t.className = 'TextInput'");
        Page.GetElements(":password").ForEach("t => t.className = 'TextInput'");
        Page.GetElements("textarea").ForEach("t => t.className = 'TextInput'");

        __addHandler(document, "keydown", function (e) {
            if (e.keyCode == 27) {
                Page.HidePageLoading();
            }
        });
    });

    $(document).ready(function () {


        if (IsPageControlsLoaded()) {

            if (parent.Dialog1) {
                window.alert = function (text) {
                    Page.Alert(null, text);
                };

                window.confirm = function (text, handler) {
                    Page.Confirm(null, text, handler);
                };
            }

            if (window.ComponentArt_Grid) {
                var p = ComponentArt_Grid.prototype;
                var ws = p.WebServiceSelect;
                p.WebServiceSelect = function () {
                    ws.apply(this, arguments);
                };

                for (var i in window) {
                    try {
                        if (window[i] instanceof ComponentArt_Grid) {

                            if (!Enumerable.From(grids).Any(function (t) { return t.Id == window[i].Id })) {
                                grids.push(window[i]);
                            }
                        }
                    }
                    catch (ex) { }
                }

                p.getRows = function () {
                    var table = this.get_table();
                    var len = table.getRowCount();
                    var rows = [];
                    while (len--) {
                        row = table.getRow(len);
                        rows.push(row);
                    }

                    return rows;
                };
            }

            Render();

            if (window.Page_Load) Page_Load();

            Enumerable.From(grids).ForEach(function (t) {
                t.RunningMode = 3;
                t.webServiceSelect();
            });

            Page.Load();
        }
        else {
            setTimeout(arguments.callee, 50);
        }
    });

    $(document).keydown(function (e) {
        if (e.keyCode == 13) {
            var res = false;
            if (window.Page_PressEnter)
                res = Page_PressEnter();

            if (res) {
                e.stopPropagation();
                e.preventDefault();
            }
        }
    });

    var _resizing = false;
    $(window).resize(function (e) {
        if (IsPageControlsLoaded() && window.ComponentArt_Page_Loaded) {
            if (!_resizing) {
                _resizing = true;
                setTimeout(function () {
                    if (Page.Render) Page.Render();
                    Render();
                    _resizing = false;
                }, 10);
            }
        }
    });
} ();


_f = function () {
    var $C = __geometry = {};

    //-------------------------------- IE and others

    if (window.screenLeft != undefined) {
        $C.getWindowX = function () { return window.screenLeft; };
        $C.getWindowY = function () { return window.screenTop; };
    }

    //-------------------------------- Firefox and others

    else if (window.screenX != undefined) {
        $C.getWindowX = function () { return window.screenX; };
        $C.getWindowY = function () { return window.screenY; };
    }

    //-------------------------------- All browsers but IE

    if (window.innerWidth != undefined) {
        $C.getViewportWidth = function () { return window.innerWidth; };
        $C.getViewportHeight = function () { return window.innerHeight; };
        $C.getHorizontalScroll = function () { return window.pageXOffset; };
        $C.getVerticalScroll = function () { return window.pageYOffset; };
    }

    //-------------------------------- These functions are for IE 6 when there is a DOCTYPE

    else if (document.compatMode != 'BackCompat' && document.documentElement.clientWidth != undefined) {
        $C.getViewportWidth = function () { return document.documentElement.clientWidth; };
        $C.getViewportHeight = function () { return document.documentElement.clientHeight; };
        $C.getHorizontalScroll = function () { return document.documentElement.scrollLeft; };
        $C.getVerticalScroll = function () { return document.documentElement.scrollTop; };
    }

    //-------------------------------- These are for IE4, IE5, and IE6 without a DOCTYPE

    else {
        $C.getViewportWidth = function () { return document.body.clientWidth; };
        $C.getViewportHeight = function () { return document.body.clientHeight; };
        $C.getHorizontalScroll = function () { return document.body.scrollLeft; };
        $C.getVerticalScroll = function () { return document.body.scrollTop; };
    }

    //-------------------------------- These functions return the size of the document

    if (document.documentElement && document.documentElement.scrollWidth != undefined) {
        $C.getDocumentWidth = function () { return document.documentElement.scrollWidth; };
        $C.getDocumentHeight = function () { return document.documentElement.scrollHeight; };
    }

    else if (document.body.scrollWidth != undefined) {
        $C.getDocumentWidth = function () { return document.body.scrollWidth; };
        $C.getDocumentHeight = function () { return document.body.scrollHeight; };
    }

    $C.getScrollY = function () {
        var scroll = document.body.scrollTop;

        if (scroll == 0) {
            scroll = window.pageYOffset ? window.pageYOffset : ((document.body.parentElement) ? document.body.parentElement.scrollTop : 0);
        }

        return scroll;
    };

    $C.getScrollX = function () {
        var scroll = document.body.scrollLeft;

        if (scroll == 0) {
            scroll = window.pageXOffset ? window.pageXOffset : ((document.body.parentElement) ? document.body.parentElement.scrollLeft : 0);
        }

        return scroll;
    };

    $C.hasHoriozontalScroll = function () {
        return $C.getViewportWidth() < $C.getDocumentWidth();
    };

    $C.hasVerticalScroll = function () {
        return $C.getViewportHeight() < $C.getDocumentHeight();
    };
} ();



__events = {};
_f = function () {
    var $C = __events;

    $C.KeyDown = "keydown";
    $C.KeyPress = "keypress";
    $C.KeyUp = "keyup";

    $C.MouseDown = "mousedown";
    $C.MouseMove = "mousemove";
    $C.MouseOut = "mouseout";
    $C.MouseOver = "mouseover";
    $C.MouseUp = "mouseup";
    $C.MouseWheel = "mousewheel";

    $C.Change = "change";
    $C.FocusIn = "focus";
    $C.FocusOut = "blur";
    $C.Click = "click";
    $C.DoubleClick = "dblclick";
    $C.Cut = "cut";
    $C.Copy = "copy";
    $C.Paste = "paste";

    $C.DragEnter = "dragenter";
    $C.DragOver = "dragover";
    $C.DragLeave = "dragleave";
    $C.DragStart = "dragstart";
    $C.Drop = "drop";

    $C.Load = "load";
    $C.Unload = "unload";
    $C.Reset = "reset";
    $C.Scroll = "scroll";
    $C.Error = "error";
    $C.Submit = "submit";
    $C.Resize = "resize";
    $C.ContextMenu = "contextmenu";

    var _allHandlers = {};
    var _counter = 0;

    var GenerateHandlerID = function () { return "h" + _counter++; };

    var WheelHandler = function (e) {
        var delta = 0;
        var handler = arguments.callee[e.currentTarget.id + $C.MouseWheel];

        if (e.wheelDelta) { // IE, Opera
            delta = e.wheelDelta / 120;
        }
        else if (e.detail) { //Mozilla
            delta = -e.detail / 3;
        }

        if (delta) {
            e.delta = (delta < 0 ? Math.floor(delta) : Math.ceil(delta));
            handler(e);
        }
    };

    var FindHandler = function (element, eventType, handler) {
        var handlers = element._handlers;
        if (!handlers)
            return -1;

        var len = handlers.length;

        while (len--) {
            try {
                var handlerId = handlers[i];
                var h = _allHandlers[handlerId];
                if (h.eventType == eventType && h.handler == handler)
                    return i;
            }
            catch (ex) { }
        }

        return -1;
    };

    var RemoveAllHandlers = function () {
        for (id in _allHandlers) {
            if (_allHandlers.hasOwnProperty(id)) {
                var h = _allHandlers[id];

                try {
                    h.element.detachEvent("on" + h.eventType, h.wrappedHandler);
                    delete _allHandlers[id];
                }
                catch (ex) { }
            }
        }
    };


    if (document.addEventListener) {
        $C.addHandler = function (element, eventType, handler, isCapturingPhase) {
            if (!element)
                return;

            eventType = eventType.toString().toLowerCase();

            if (eventType == $C.MouseWheel) {
                WheelHandler[element.id + $C.MouseWheel] = handler;
                element.addEventListener('DOMMouseScroll', WheelHandler, Boolean(isCapturingPhase));
                element.addEventListener(eventType, WheelHandler, Boolean(isCapturingPhase));
            }
            else
                element.addEventListener(eventType, handler, Boolean(isCapturingPhase));
        };

        $C.removeHandler = function (element, eventType, handler, isCapturingPhase) {
            if (!element)
                return;

            eventType = eventType.toString().toLowerCase();

            if (eventType == $C.MouseWheel) {
                WheelHandler[element.id + $C.MouseWheel] = null;
                element.removeEventListener('DOMMouseScroll', WheelHandler, Boolean(isCapturingPhase));
                element.removeEventListener(eventType, WheelHandler, Boolean(isCapturingPhase));
            }
            else
                element.removeEventListener(eventType, handler, Boolean(isCapturingPhase));
        };
    }

    else if (document.attachEvent) {
        $C.addHandler = function (element, eventType, eventHandler) {

            if (!element)
                return;

            eventType = eventType.toString().toLowerCase();

            if (!element._handlers)
                element._handlers = [];

            var handler = eventHandler;

            if (eventType == $C.MouseWheel) {
                WheelHandler[element.id + $C.MouseWheel] = eventHandler;
                handler = WheelHandler;
            }

            if (FindHandler(element, eventType, handler) != -1)
                return;

            var wrappedHandler = function (e) {
                if (!e) e = window.event;

                var event =
			    {
			        _event: e,
			        type: e.type,
			        target: e.srcElement,
			        currentTarget: element,
			        wheelDelta: e.wheelDelta,
			        relatedTarget: e.fromElement ? e.fromElement : e.toElement,
			        eventPhase: (e.srcElement == element) ? 2 : 3,

			        clientX: e.clientX,
			        clientY: e.clientY,
			        screenX: e.screenX,
			        screenY: e.screenY,

			        altKey: e.altKey,
			        ctrlKey: e.ctrlKey,
			        shiftKey: e.shiftKey,
			        keyCode: e.keyCode,
			        isNavigationKey: $C.isNavigationKey(e),

			        stopPropagation: function () { this._event.cancelBubble = true; },
			        preventDefault: function () { this._event.returnValue = false; }
			    };

                handler.apply(element, [event]);
            };

            element.attachEvent("on" + eventType, wrappedHandler);

            var h = { element: element, eventType: eventType, handler: handler, wrappedHandler: wrappedHandler };
            var id = GenerateHandlerID();

            _allHandlers[id] = h;
            element._handlers.push(id);
        };

        $C.removeHandler = function (element, eventType, eventHandler) {

            if (!element)
                return;

            eventType = eventType.toString().toLowerCase();

            var handler = eventHandler;

            if (eventType == $C.MouseWheel) {
                WheelHandler[element.id + $C.MouseWheel] = null;
                handler = WheelHandler;
            }

            var i = FindHandler(element, eventType, handler);
            if (i == -1) return;

            var handlerId = element._handlers[i];
            var h = _allHandlers[handlerId];

            element.detachEvent("on" + eventType, h.wrappedHandler);
            element._handlers.splice(i, 1);

            delete _allHandlers[handlerId];
        };

        window.attachEvent($C.Unload, RemoveAllHandlers);
    };

    $C.isNavigationKey = function (e) {
        var code = e.keyCode;

        if (((e.charCode == undefined && !e.shiftKey) || e.charCode == 0) && ((code >= 33 && code <= 40) || code == 8 || code == 46)) {    // navigation, backspace, delete
            return true;
        }
        return false;
    };

    __addHandler = $C.addHandler;
    __removeHandler = $C.removeHandler;
} ();








//--------------------- JSON

var JSON;
if (!JSON) {
    JSON = {};
}

(function () {
    'use strict';

    function f(n) {
        // Format integers to have at least two digits.
        return n < 10 ? '0' + n : n;
    }

    if (typeof Date.prototype.toJSON !== 'function') {

        Date.prototype.toJSON = function (key) {

            return isFinite(this.valueOf()) ?
                this.getUTCFullYear() + '-' +
                f(this.getUTCMonth() + 1) + '-' +
                f(this.getUTCDate()) + 'T' +
                f(this.getUTCHours()) + ':' +
                f(this.getUTCMinutes()) + ':' +
                f(this.getUTCSeconds()) + 'Z' : null;
        };

        String.prototype.toJSON =
            Number.prototype.toJSON =
            Boolean.prototype.toJSON = function (key) {
                return this.valueOf();
            };
    }

    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        gap,
        indent,
        meta = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"': '\\"',
            '\\': '\\\\'
        },
        rep;


    function quote(string) {

        // If the string contains no control characters, no quote characters, and no
        // backslash characters, then we can safely slap some quotes around it.
        // Otherwise we must also replace the offending characters with safe escape
        // sequences.

        escapable.lastIndex = 0;
        return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
            var c = meta[a];
            return typeof c === 'string' ? c :
                '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
        }) + '"' : '"' + string + '"';
    }


    function str(key, holder) {

        // Produce a string from holder[key].

        var i,          // The loop counter.
            k,          // The member key.
            v,          // The member value.
            length,
            mind = gap,
            partial,
            value = holder[key];

        // If the value has a toJSON method, call it to obtain a replacement value.

        if (value && typeof value === 'object' &&
                typeof value.toJSON === 'function') {
            value = value.toJSON(key);
        }

        // If we were called with a replacer function, then call the replacer to
        // obtain a replacement value.

        if (typeof rep === 'function') {
            value = rep.call(holder, key, value);
        }

        // What happens next depends on the value's type.

        switch (typeof value) {
            case 'string':
                return quote(value);

            case 'number':

                // JSON numbers must be finite. Encode non-finite numbers as null.

                return isFinite(value) ? String(value) : 'null';

            case 'boolean':
            case 'null':

                // If the value is a boolean or null, convert it to a string. Note:
                // typeof null does not produce 'null'. The case is included here in
                // the remote chance that this gets fixed someday.

                return String(value);

                // If the type is 'object', we might be dealing with an object or an array or
                // null.

            case 'object':

                // Due to a specification blunder in ECMAScript, typeof null is 'object',
                // so watch out for that case.

                if (!value) {
                    return 'null';
                }

                // Make an array to hold the partial results of stringifying this object value.

                gap += indent;
                partial = [];

                // Is the value an array?

                if (Object.prototype.toString.apply(value) === '[object Array]') {

                    // The value is an array. Stringify every element. Use null as a placeholder
                    // for non-JSON values.

                    length = value.length;
                    for (i = 0; i < length; i += 1) {
                        partial[i] = str(i, value) || 'null';
                    }

                    // Join all of the elements together, separated with commas, and wrap them in
                    // brackets.

                    v = partial.length === 0 ? '[]' : gap ?
                    '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
                    '[' + partial.join(',') + ']';
                    gap = mind;
                    return v;
                }

                // If the replacer is an array, use it to select the members to be stringified.

                if (rep && typeof rep === 'object') {
                    length = rep.length;
                    for (i = 0; i < length; i += 1) {
                        k = rep[i];
                        if (typeof k === 'string') {
                            v = str(k, value);
                            if (v) {
                                partial.push(quote(k) + (gap ? ': ' : ':') + v);
                            }
                        }
                    }
                } else {

                    // Otherwise, iterate through all of the keys in the object.

                    for (k in value) {
                        if (Object.prototype.hasOwnProperty.call(value, k)) {
                            v = str(k, value);
                            if (v) {
                                partial.push(quote(k) + (gap ? ': ' : ':') + v);
                            }
                        }
                    }
                }

                // Join all of the member texts together, separated with commas,
                // and wrap them in braces.

                v = partial.length === 0 ? '{}' : gap ?
                '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
                '{' + partial.join(',') + '}';
                gap = mind;
                return v;
        }
    }

    // If the JSON object does not yet have a stringify method, give it one.

    if (typeof JSON.stringify !== 'function') {
        
        JSON.stringify = function (value, replacer, space) {

            // The stringify method takes a value and an optional replacer, and an optional
            // space parameter, and returns a JSON text. The replacer can be a function
            // that can replace values, or an array of strings that will select the keys.
            // A default replacer method can be provided. Use of the space parameter can
            // produce text that is more easily readable.

            var i;
            gap = '';
            indent = '';

            // If the space parameter is a number, make an indent string containing that
            // many spaces.

            if (typeof space === 'number') {
                for (i = 0; i < space; i += 1) {
                    indent += ' ';
                }

                // If the space parameter is a string, it will be used as the indent string.

            } else if (typeof space === 'string') {
                indent = space;
            }

            // If there is a replacer, it must be a function or an array.
            // Otherwise, throw an error.

            rep = replacer;
            if (replacer && typeof replacer !== 'function' &&
                    (typeof replacer !== 'object' ||
                    typeof replacer.length !== 'number')) {
                throw new Error('JSON.stringify');
            }

            // Make a fake root object containing our value under the key of ''.
            // Return the result of stringifying the value.

            return str('', { '': value });
        };
    }


    // If the JSON object does not yet have a parse method, give it one.

    if (typeof JSON.parse !== 'function') {
    
        JSON.parse = function (text, reviver) {

            // The parse method takes a text and an optional reviver function, and returns
            // a JavaScript value if the text is a valid JSON text.

            var j;

            function walk(holder, key) {

                // The walk method is used to recursively walk the resulting structure so
                // that modifications can be made.

                var k, v, value = holder[key];
                if (value && typeof value === 'object') {
                    for (k in value) {
                        if (Object.prototype.hasOwnProperty.call(value, k)) {
                            v = walk(value, k);
                            if (v !== undefined) {
                                value[k] = v;
                            } else {
                                delete value[k];
                            }
                        }
                    }
                }
                return reviver.call(holder, key, value);
            }


            // Parsing happens in four stages. In the first stage, we replace certain
            // Unicode characters with escape sequences. JavaScript handles many characters
            // incorrectly, either silently deleting them, or treating them as line endings.

            text = String(text);
            cx.lastIndex = 0;
            if (cx.test(text)) {
                text = text.replace(cx, function (a) {
                    return '\\u' +
                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                });
            }

            // In the second stage, we run the text against regular expressions that look
            // for non-JSON patterns. We are especially concerned with '()' and 'new'
            // because they can cause invocation, and '=' because it can cause mutation.
            // But just to be safe, we want to reject all unexpected forms.

            // We split the second stage into 4 regexp operations in order to work around
            // crippling inefficiencies in IE's and Safari's regexp engines. First we
            // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
            // replace all simple value tokens with ']' characters. Third, we delete all
            // open brackets that follow a colon or comma or that begin the text. Finally,
            // we look to see that the remaining characters are only whitespace or ']' or
            // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.

            if (/^[\],:{}\s]*$/
                    .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
                        .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
                        .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

                // In the third stage we use the eval function to compile the text into a
                // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
                // in JavaScript: it can begin a block or an object literal. We wrap the text
                // in parens to eliminate the ambiguity.

                j = eval('(' + text + ')');

                // In the optional fourth stage, we recursively walk the new structure, passing
                // each name/value pair to a reviver function for possible transformation.

                return typeof reviver === 'function' ?
                    walk({ '': j }, '') : j;
            }

            // If the text is not JSON parseable, then a SyntaxError is thrown.

            throw new SyntaxError('JSON.parse');
        };
    }

} ());
