﻿/// <reference path="json2.js" />
/// <reference path="jquery-1.4.1.js" />
/// <reference path="jquery.timers-1.1.3.js" />
/// <reference path="jqModal.js" />
/// <reference path="text/libCore_js.Sv.js" />

// Creating the library
function library() {
}
library.prototype = {
    Core: {
        logout: function (callback) {
            lib.Core.sendAjax('wsAjax.asmx/logout',
                    '{}',
                    function (msg) {
                        var response = JSON.parse(msg.d);
                        if (callback
                            && typeof (callback) === 'function')
                            callback(response);
                        else {
                            if (response.Success
                            && response.Data != null)
                                location.href = response.Data;
                        }
                    },
                    function (err) {
                        alert('Logout failed');
                    });
            return false;
        },
        UserSettings: {
            ContractSettings: { canChangeSenderName: false, hasMessageLimit: true }
        },
        // Gör det lite enklare att posta ett ajaxanrop
        sendAjax: function (uri, data, success, error) {
            $.ajax({
                async: true,
                type: "POST",
                url: uri,
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                data: data,
                success: success,
                error: error
            });
        },
        compareTo: function (source, compare) {
            for (i in source) {
                if (compare[i] !== undefined
                        && source[i] === compare[i])
                    continue;
                else
                    return false;
            }
            return true;
        },
        clone: function (obj) {
            var newObj = (this instanceof Array) ? [] : {};
            for (i in obj) {
                if (i == 'clone') continue;
                if (obj[i] && typeof obj[i] == "object") {
                    newObj[i] = this.clone(obj[i]);
                } else newObj[i] = obj[i]
            } return newObj;
        },
        modalPopup: function (head, content, options) {
            /// <summary>Öppnar en modal popupruta</summary>
            /// <param name="head">Rukriken för meddelandet</param>
            /// <param name="content">Själva meddelandeinnehållet</param>
            /// <param name="options">Valfri, Ett objekt med inställningar för meddelandet. { button : true, delayHide : 1500, loader: false }</param>
            applyScaleButtons($('#popupwindow'), true);

            // Stoppar eventuell timer
            $(this).stopTime('modalHide');
            if (options != undefined
        || options != null) {
                if (options.button != undefined
            || options.button != null) {
                    if (options.button)
                        $('#popupwindow #body #close').css('display', 'block');
                    else
                        $('#popupwindow #body #close').css('display', 'none');
                }
                else
                    $('#popupwindow #body #close').css('display', 'block');

                hideScaleButtons($('#popupwindow').find('input[type=button]'), false);

                if (options.delayHide != undefined
            || options.delayHide != null) {
                    if (options.delayHide > 0) {
                        $(this).oneTime(options.delayHide, 'modalHide', function () {
                            $('#popupwindow').jqmHide();
                        });
                    }
                    else {
                        $('#popupwindow').jqmHide();
                    }
                }

                if (options.loader != undefined
            || options.loader != null) {
                    if (options.loader)
                        $('#loader').css('display', 'block');
                    else
                        $('#loader').css('display', 'none');
                }
                else
                    $('#loader').css('display', 'none');
            }
            else {
                hideScaleButtons($('#popupwindow').find('input[type=button]'), false);
                $('#loader').css('display', 'none');
            }

            $('#popupwindow').find('#head').html(head);
            $('#popupwindow').find('#body #cont').html(content);
            $('#popupwindow').jqm({ 'modal': true });
            $('#popupwindow').jqmShow();
        },
        modalPopupHide: function (delay) {
            /// <summary>Döljer den aktuella popuputan</summary>
            /// <param name="delay">Valfri. Skapar en fördröjning före popuprutan tas bort, anges i ms</param>
            if (delay)
                $(this).oneTime(delay, 'modalHide', function () {
                    $('#popupwindow').jqmHide();
                });
            else
                $('#popupwindow').jqmHide();
        },
        toDate: function (JsonDate) {
            if (JsonDate != undefined
                || JsonDate != null) {
                var DateValue = parseInt(JsonDate.replace('Date', '').replace('/(', '').replace(')/', ''));
                if (DateValue != NaN)
                    return new Date(DateValue);
            }
            return new Date();
        },
        isArray: function (val) {
            /// <summary>Kollar om indatan är en array eller ej</summary>
            /// <param name="val">Datan som ska kontrolleras</param>
            return val && !(val.propertyIsEnumerable('length')) && typeof val === 'object' && typeof val.length === 'number';
        },
        cookie: {
            set: function (name, value, expDays) {
                /// <summary>Adds a cookie at the users browser (currently only adds one cookie)</summary>
                /// <param name="name">The cookies namne</param>
                /// <param name="value">The cookies value</param>
                /// <param name="expDays">Defines for how long the cookie should be active</summary>
                var days = new Date();
                days.setDate(days.getDate() + expDays);
                document.cookie = name + "=" + escape(value)
                            + ((expiredays == null) ? "" : ";expires=" + days.toUTCString());
                return document.cookie;
            },
            get: function (name) {
                /// <summary>Gets the cookie from the browser, returns null if not found</summary>
                var cookie = null;
                if (document.cookie.length > 0) {
                    var start = document.cookie.indexOf(name + "=");
                    if (start != -1) {
                        start = start + name.length + 1;
                        var end = document.cookie.indexOf(";", start);
                        if (end == -1) end = document.cookie.length;
                        cookie = unescape(document.cookie.substring(start, end));
                    }
                }
                return cookie;
            }
        },
        List: {
            _listId: '',
            addList: function (target, listId, columns, settings) {
                /// <summary>Skapar en lista och placerar den i target</summary>
                /// <param name="target">Platsen där listan ska placeras</param>
                /// <param name="listId">Idt på listan, behövs för att identifiera listan senare</param>
                /// <param name="colmns">Ska vara ett listItem objekt, name och width används (står om det nedanför)</param>
                /// <param name="settings">Ett listSettings objekt för olika inställningar i listan</param>
                var that = this;
                var $target = $(target);
                this.listId(listId);
                settings = settings || new this.listSettings();
                if ($target.length > 0) {
                    var html = [];
                    var columnWidths = [];
                    html.push('<div id="' + listId + '" class="list">');
                    if (columns != undefined
                        && columns != null) {
                        html.push('<div class="header">');
                        for (var i = 0; i < columns.length; i++) {
                            html.push('<div style="float : left; width : ' + columns[i].width + 'px;">' + columns[i].name + '</div>');
                            columnWidths.push(columns[i].width);
                        }
                        html.push('<div style="clear:left"></div></div>');
                    }
                    html.push('<div');
                    if (settings.maxHeight() > 20)
                        html.push(' style="max-height: ' + (settings.maxHeight() - 19) + 'px; overflow : auto;"');
                    html.push('><ul class="items"></ul></div>');
                    html.push('</div>');
                    $target.html(html.join(''));
                    $target.find('#' + listId).data('columnWidths', columnWidths);
                    this.settings(settings);

                    if (settings.addable()) {
                        var valgroup = new lib.Core.ValidationGroup();
                        html = [];
                        var addableSettings = settings.addableSettings();
                        var hasValidation = false;
                        html.push('<div id="addLocation">');
                        for (var i = 0; i < columnWidths.length; i++) {
                            var itmSetting = addableSettings[i] || new lib.Core.List.addableItem();
                            html.push('<div '
                                    + ((itmSetting.id && 'id="' + itmSetting.id() + '"') || '')
                                    + ' style="float : left; width : ' + columnWidths[i] + 'px;">'
                                    + ((itmSetting.title || '') && '<span style="font-weight : bold;">' + itmSetting.title() + '</span><br />')
                                        + '<input type="text" style="width : ' + (columnWidths[i] - 5) + 'px;"'
                                        + ((itmSetting.defaultValue || '') && ' value="' + itmSetting.defaultValue() + '"')
                                        + ' />');
                            html.push('</div>');
                            if ((itmSetting.validation)
                                && itmSetting.validation())
                                hasValidation = true;
                        }
                        html.push('<div style="float : left; margin-left : 5px; margin-top : 12px;"><input id="btnAddItem" type="button" value="Lägg till" /></div>'
                                    + '<div style="clear : left;"></div>');
                        if (hasValidation)
                            html.push('<div id="lblValidation"></div>');
                        html.push('</div>');
                        $target.find('.list').append(html.join(''));
                        $target.find('.items').parent().css('max-height',
                                                            (+$target.find('.items').parent().css('max-height').replace('px', '')
                                                            - $target.find('#addLocation').height())
                                                            + 'px');
                        var $addLocation = $target.find('#addLocation');
                        $addLocation.find('#btnAddItem').click(function () {
                            if (valgroup.validate().validated) {
                                if (that.addClick())
                                    that.addClick()($addLocation);
                            }
                        });
                        if (hasValidation) {
                            valgroup.items = [];
                            for (var i = 0; i < addableSettings.length; i++) {
                                var setting = addableSettings[i];
                                setting.validation().item = $addLocation.find('input:eq(' + i + ')');
                                setting.validation().label = $addLocation.find('span');
                                setting.validation().notification = $addLocation.find('#lblValidation');
                                setting.validation().setup();
                                valgroup.items.push(setting.validation());
                            }
                        }
                        lib.Core.Buttons.applyScaleButtons($target, true);
                        $target.find('div.removable').live('click', this.deleteClick());
                    }
                }
                return this;
            },
            addItems: function (listId, items, clearOld) {
                var $target = $('#' + listId);
                var settings = this.settings();
                if ($target.length > 0) {
                    var html = [];
                    if (items != undefined
                        && items != null) {
                        var columnWidths = $target.data('columnWidths');
                        var totalWidth = 0;
                        for (var i = 0; i < columnWidths.length; i++) {
                            totalWidth += columnWidths[i];
                        }
                        for (var i = 0; i < items.length; i++) {
                            var itm = [];
                            itm.push('<li ');
                            if (items[i].id != undefined
                                && items[i].id != null)
                                itm.push('id="' + items[i].id + '" ');
                            itm.push('class="item');
                            if (i % 2 == 1)
                                itm.push(' alternatingItem');
                            itm.push('" style="');
                            //                            if (settings.removable())
                            //                                itm.push('background-position : ' + totalWidth + 'px;');
                            itm.push('">');
                            for (var x = 0; x < items[i].columns.length; x++) {
                                itm.push('<div style="float : left;');
                                if (columnWidths[x] != null)
                                    itm.push('width : ' + columnWidths[x] + 'px;');
                                itm.push('">' + items[i].columns[x] + '</div>');
                            }
                            if (settings.removable()) {
                                itm.push('<div class="removable"></div>');
                            }
                            itm.push('<div style="clear : left;"></div>');
                            itm.push('</li>');
                            html.push(itm.join(''));
                        }
                    }
                    if (clearOld != undefined
                        && clearOld != null
                        && !clearOld) {
                        $target.find('.items').append(html.join(''));
                    }
                    else
                        $target.find('.items').html(html.join(''));
                }
            },
            addItem: function (listId, item) {
                if (typeof listId === 'object' && !item) {
                    item = listId;
                    listId = this.listId();
                }

                this.addItems(listId, [item], false);
            },
            removeItem: function (listId, itemId) {
                if (!itemId) {
                    itemId = listId;
                    listId = this.listId();
                }
                var $item = $('#' + listId + ' #' + itemId);
                $item.slideUp('slow', function (event) {
                    $item.remove();
                });
            },
            addData: function (listId, data) {
                $('#' + listId).data('data', data);
            },
            retrieveData: function (listId) {
                return $('#' + listId).data('data');
            },
            listId: function (val) {
                return (val && ((this._listId = val) && this) || this._listId);
            },
            settings: function (val) {
                return (val && ($('#' + this.listId()).data('settings', val) && this)
                    || ($('#' + this.listId()).data('settings')));
            },
            deleteClick: function (val) {
                var that = this;
                return (val && ($('#' + this.listId()).data('deleteClick', val) && this)
                    || (function (data) { $('#' + that.listId()).data('deleteClick')(data); }));
            },
            addClick: function (val) {
                var that = this;
                return (val && ($('#' + this.listId()).data('addClick', val) && this)
                    || (function (data) { $('#' + that.listId()).data('addClick')(data); }));
            },
            listItem: function () {
                this.id = '';
                this.name = '';
                this.width = 0;
                this.columns = [];
                this.data = null; /* data används inte nu */
            },
            listSettings: function () {
                var that = this;
                this.maxHeight = 0;
                this.removable = false;
                this.addable = false;
                this.sortable = false;
                this.selectable = false;
                this.addableSettings = [];
                return {
                    maxHeight: function (val) {
                        return (val && ((that.maxHeight = val) && this) || that.maxHeight);
                    },
                    removable: function (val) {
                        return (val && ((that.removable = val) && this) || that.removable);
                    },
                    addable: function (val) {
                        return (val && ((that.addable = val) && this) || that.addable);
                    },
                    sortable: function (val) {
                        return (val && ((that.sortable = val) && this) || that.sortable);
                    },
                    selectable: function (val) {
                        return (val && ((that.selectable = val) && this) || that.selectable);
                    },
                    addableSettings: function (val) {
                        return (val && ((that.addableSettings = val) && this) || that.addableSettings);
                    }
                }
            },
            addableItem: function () {
                var that = this;
                this.title = '';
                this.validation = null;
                this.id = null;
                this.defaultValue = '';
                return {
                    title: function (val) {
                        return (val && ((that.title = val) && this) || that.title);
                    },
                    validation: function (val) {
                        return (val && ((that.validation = val) && this) || that.validation);
                    },
                    id: function (val) {
                        return (val && ((that.id = val) && this) || that.id);
                    },
                    defaultValue: function (val) {
                        return (val && ((that.defaultValue = val) && this) || that.defaultValue);
                    }
                }
            }
        },
        Validation: function (item, notification, label, type, manualSetup) {
            /// <summary>
            /// Skapar valideringsfunktioner för formulärfält (inputs)
            /// </summary>
            /// <param name="item">Det fält som ska valideras (ofta en input)</param>
            /// <param name="notification">Det fält där notifikationstexten ska placeras</param>
            /// <param name="label">Label platsen där texten som beskriver fältet är</param>
            /// <param name="type">Anger vad det ska vara för typ av regexp (kommer finnas några fördefinerade, typ telefon, epost)
            /// <param name="manualSetup">Om true, kommer inte this.setup() köras, kan vara bra om man ska göra fler inställingar än konstruktorn stödjer</param>
            if (item != undefined)
                this.item = item;
            if (notification != undefined)
                this.notification = notification;
            if (label != undefined)
                this.label = label;
            if (type != undefined)
                this.type = type;
            if (!manualSetup)
                this.setup();
        },
        ValidationGroup: function (items, notification) {
            /// <summary>
            /// Kontrollerar ett flertal Validationobjekt samtidigt, dig exempelvis en submit
            /// </summary>
            /// <param name="items">En samling Validationitems som ska valideras</param>
            /// <param name="notification">Det fält där notifikationstexten ska placeras</param>
            if (items != undefined)
                this.items = items;
            if (notification != undefined)
                this.notification = notification;
            this.setup();
        },
        Progress: (function () {
            var ret = {
                Create: function (target, options) {
                    var item = null;
                    var value = 0;
                    var min = 0;
                    var max = 100;
                    var oversize = false;
                    var displayType = 0;    //  Anger hur värdet ska anges och visas, 
                    //  0 = antal
                    //  1 = antal/max
                    //  2 = procent
                    var displayValue = true;
                    var $progressbar = null;

                    /// <summary>
                    /// Skapar en progressbar
                    /// </summary>
                    /// <param name="target">Ställe där du vill placera progressbaren. (Behövs inte)</param>
                    /// <param name="options">Inställningar för progressbaren. (min, max, value, oversize)</param>
                    /// <returns>Returnerar en progresbar</returns>
                    $progressbar = $('<div class="progressbar">'
                                           + '<div class="bar"></div>'
                                           + '<div class="value"></div>'
                                        + '</div>');

                    if (options) {
                        if (options.width)
                            $progressbar.css('width', options.width);
                        if (options.min)
                            min = options.min;
                        if (options.max)
                            max = options.max;
                        if (options.value)
                            value = options.value;
                        if (options.oversize)
                            oversize = options.oversize;
                        if (options.displayType)
                            displayType = options.displayType;
                    }

                    function setValue(val) {
                        if (val
                            || val === 0)
                            value = val;
                        if (item) {
                            if (oversize)
                                item.addClass('oversize');

                            var width = $progressbar.width();
                            // Kollar så alla värden stämmer.
                            if (max <= min)
                                min = max - 1;
                            if (max < value)
                                value = max;
                            if (min > value)
                                value = min;

                            var pixelPerValue = ((width) / (max - min));
                            $progressbar.find('.bar').css('width', (pixelPerValue * (value - min)));

                            var lblValue = $progressbar.find('.value');
                            if (displayValue) {
                                lblValue.css('display', 'block');
                                var valueText = '';
                                switch (displayType) {
                                    case 0:
                                        valueText = value;
                                        break;
                                    case 1:
                                        valueText = value + '/' + max;
                                        break;
                                    case 2:
                                        valueText = value + '%';
                                        break;
                                }
                                lblValue.text(valueText);
                            }
                            else
                                lblValue.css('display', 'none');
                        }
                        return this;
                    }

                    item = {
                        Progressbar: function () {
                            return item;
                        },
                        Value: function (val) {
                            if (val
                            || val === 0) {
                                setValue(val);
                                return this;
                            }
                            return value;
                        },
                        DecreaseValue: function (val) {
                            if (val)
                                Value(value -= val);
                            else
                                Value(--value);
                            return this;
                        },
                        IncreaseValue: function (val) {
                            if (val)
                                Value(value += val);
                            else
                                Value(++value);
                            return this;
                        },
                        Min: function (val) {
                            if (val) {
                                min = val;
                                setValue();
                                return this;
                            }
                            return min;
                        },
                        Max: function (val) {
                            if (val) {
                                max = val;
                                setValue();
                                return this;
                            }
                            return max;
                        },
                        DisplayType: function (val) {
                            if (val) {
                                displayType = val;
                                setValue();
                                return this;
                            }
                            return displayType;
                        },
                        Oversize: function (val) {
                            if (val) {
                                oversize = val;
                                setValue();
                                return this;
                            }
                            return oversize;
                        }
                    }
                    setValue();
                    if (target != null)
                        $(target).append($progressbar);
                    return item;
                }
            }
            return ret;
        })(),
        Buttons: {
            /* 
            target = Den panel eller knapp som man vill använda (knapp ej klarbyggd)
            allButtons = Om true, tar även dolda knappar 
            */
            applyScaleButtons: function (target, allButtons) {
                var Location = $();
                if (target != undefined
                    && target != null) {
                    Location = $(target);
                }
                if (Location != null) {
                    var Buttons = null;
                    if (!allButtons)
                        Buttons = Location.find(":submit:visible, :button:visible");
                    else
                        Buttons = Location.find(":submit, :button");
                    if (Buttons != null) {
                        for (var i = 0; i < Buttons.length; i++) {
                            if (!$(Buttons[i]).data('scaleApplied')) {
                                $(Buttons[i]).data('scaleApplied', true)
                                $(Buttons[i]).data('hidden', false);
                                $(Buttons[i]).wrap('<div></div>');
                                $(Buttons[i]).before("<div class=\"btnLeft\"></div>");
                                $(Buttons[i]).after("<div class=\"btnRight\" style=\"clear: right;\"></div>");
                            }
                            if ($(Buttons[i]).is(':disabled'))
                                disableScaleButtons($(Buttons[i]), true);
                        }
                    }
                }
            },
            /*
            target  = knappen
            hide    = om den ska döljas eller ej
            (speed) = valfritt, om man vill ha en slideeffekt, anger man hastighet här
            */
            hideScaleButtons: function (target, hide, speed) {
                if (hide) {
                    if (speed == undefined
                        || speed == null)
                        $(target).parent().css('display', 'none');
                    else
                        $(target).parent().slideUp(speed);
                    $(target).data('hidden', true);
                }
                else {
                    $(target).css('display', 'block');
                    if (speed == undefined
                        || speed == null)
                        $(target).parent().css('display', 'block');
                    else
                        $(target).parent().slideDown(speed);
                    $(target).data('hidden', false);
                }
            },
            disableScaleButtons: function (target, disabled) {
                if (disabled) {
                    $(target).parents('div:first').addClass('btnDisabled');
                    $(target).attr('disabled', 'disabled');
                }
                else {
                    $(target).parents('.btnDisabled').removeClass('btnDisabled');
                    $(target).removeAttr('disabled');
                }
            }
        },
        EventChecker: {}
    },
    Questions: function () {
        $.getScript("js/libQuestion.js");
    },
    text: { // I text ska olika sidors texter hamna, kommer användas vid flerspråksstöd
        libCore_js: coreText.libCore_js
    }
};

library.prototype.Core.EventChecker = new function () {

    // "private" members
    var that = this;
    this.user = null;
    this.succeded = 0;
    this.failedSession = 0;
    this.failedSession_Total = 0;
    this.failedConnection = 0;
    this.failedConnection_Total = 0;
    this.displayingSessionError = false;
    this.displayingConnectionError = false;
    this.popupPanel = null;

    var texts = library.prototype.text.libCore_js.EventChecker;

    // "private" functions
    this.checkEvent = function () {
        /// <summary>Funktionen som kontrollerar anslutningen till servern</summary>
        lib.Core.sendAjax('wsAjax.asmx/checkEvent',
                    JSON.stringify({ page: location.pathname }),
                    function (msg) {
                        var response = JSON.parse(msg.d);
                        that.failedConnection = 0;
                        if (response.Success) {
                            if (that.displayingConnectionError
                                && !that.displayingSessionError)
                                that.removeFailedConnection();
                            // Lägger till info om den inloggade användaren
                            if (that.user == null)
                                that.user = {
                                    uName: response.Data.UserName,
                                    fName: response.Data.UserFName,
                                    sName: '',
                                    phone: response.Data.UserPhone,
                                    email: response.Data.UserEmail,
                                    id: response.Data.UserId
                                };
                            // Lägger till Usermessages
                            for (var i = 0; i < response.Data.UserMessages.length; i++) {
                                UserMessage(response.Data.UserMessages[i]);
                            }
                            // Kolla om några meddelandebars ska uppdateras
                            if (response.Data.MessageData.length > 0
                                && updateMessageBars != null)
                                updateMessageBars(response.Data.MessageData);

                            // Kollar om vi är i en importsession. Uppdaterar isåfall statusen för den
                            if (response.Data.CurrentUserImportStatus
                                && lib.Users)
                                lib.Users.ManagePanel.setImportStatusViewContents(response.Data.CurrentUserImportStatus);

                            // Kollar om vi stödjer debugging
                            if (lib.Debug
                                && response.Data.DebuggerSettings) {
                                lib.Debug.setupDebuggerSettings(response.Data.DebuggerSettings);
                            }

                            that.failedSession = 0;
                        }
                        else {
                            switch (response.Data) {
                                case 'noSession':
                                    that.failedSession++;
                                    that.failedSession_Total++;
                                    if (!that.displayingSessionError)
                                        that.displayFailedSession();
                                    break;
                            }
                        }
                    },
                    function (err) {
                        that.failedConnection++;
                        that.failedConnection_Total++;
                        if (!that.displayingConnectionError) {
                            if (that.failedConnection == 1) {
                                UserMessage({
                                    DisplayMethod: 0,
                                    Id: '00000000-0000-0000-0000-000000000000',
                                    Header: texts.checkEvent.sendAjax.error.head,
                                    Message: texts.checkEvent.sendAjax.error.body,
                                    IconUrl: 'img/usermsg_Info.png',
                                    FadeOutTime: 20000,
                                    MustBeConfirmed: false
                                });
                            }
                            else if (that.failedConnection >= 2) {
                                that.displayFailedConnection();
                            }
                        }
                    });
        return this;
    };
    this.displayFailedSession = function () {
        if (this.user) {
            this.displayingSessionError = true;
            this.displayingConnectionError = false;
            this.displayOpen({ height: 180, width: 340 });
            this.popupPanel.find('#head').text(texts.displayFailedSession.head);
            this.popupPanel.find('#ingress').html(texts.displayFailedSession.ingress);
            var html = $('<form action="#" onsubmit="return false;"><table class="infoSubHeading" style="margin-left: 15px;"><tr><td>' + texts.displayFailedSession.user + ':</td><td><input type="text" id="txtUsername" disabled="disabled" class="large"/></td></tr>'
                   + '<tr><td>' + texts.displayFailedSession.password + ':</td><td><input type="password" id="txtPassword" class="large" /></td></tr>'
                   + '<tr><td colspan="2"><div style="height : 30px; width : 100%; position : relative;">'
                   + '<div style="position : absolute; bottom : 5px; left : 0px;"><input type="button" onclick="lib.Core.EventChecker.cancel()" value="' + texts.displayFailedSession.btnCancel + '" /></div>'
                   + '<div style="position : absolute; bottom : 5px; right : 0px;"><input type="submit" onclick="lib.Core.EventChecker.login()" value="' + texts.displayFailedSession.btnLogin + '" /></div>'
                   + '</div></td></tr></table></form>');
            this.popupPanel.find('#contents').html(html);
            this.popupPanel.find('#contents #txtUsername').val(this.user.uName);
            lib.Core.Buttons.applyScaleButtons(html, true);
        }
        else
            location.href = 'default.aspx';
        return this;
    };

    this.login = function () {
        var pnl = that.popupPanel;
        var data = {};
        data.username = pnl.find('#txtUsername').val();
        data.password = pnl.find('#txtPassword').val();
        data.userId = (that.user && that.user.id) || '00000000-0000-0000-0000-000000000000';
        lib.Core.sendAjax('wsUsers.asmx/loginUser',
                            JSON.stringify(data),
                            function (msg) {
                                var response = JSON.parse(msg.d);
                                var $message = $('<p id="msg" class="infoLargeText" style="text-align : center; vertical-align : middle; height : 100%; ">' + response.Message + '</p>');
                                if (response.Success) {
                                    pnl.find('table').replaceWith($message);
                                    pnl.oneTime(3000, function () {
                                        that.displayClose();
                                    });
                                }
                                else {
                                    pnl.find('table').css('display', 'none');
                                    pnl.append($message);
                                    pnl.oneTime(3000, function () {
                                        $message.remove();
                                        pnl.find('table').css('display', 'table');
                                    });
                                    if (response.Data && response.Data.clear) {
                                        pnl.find('#txtUsername').val('');
                                        pnl.find('#txtPassword').val('');
                                    }
                                }
                            },
                            function (err) {
                                var $message = $('<p id="msg" class="infoLargeText" style="text-align : center; vertical-align : middle; height : 100%; ">' + texts.login.failText + '</p>');
                                pnl.find('table').css('display', 'none');
                                pnl.append($message);
                                pnl.oneTime(3000, function () {
                                    that.displayingSessionError = false;
                                    $message.remove();
                                    pnl.find('table').css('display', 'table');
                                });
                            });
    };

    this.displayFailedConnection = function () {
        this.displayingConnectionError = true;
        that.displayingSessionError = false;
        this.displayOpen({ height: 180, width: 340 });
        var pnl = that.popupPanel;
        pnl.find('#head').html(texts.displayFailedConnection.head);
        pnl.find('#ingress').html(texts.displayFailedConnection.ingress);
        pnl.find('#contents').html('<div class="infoLargeText" style="margin-top : 5px; text-align : center;">' + texts.displayFailedConnection.text + '<br /><img src="img/loading_1.gif" alt="' + texts.displayFailedConnection.imgAlt + '" /></div>');
        return this;
    };

    this.removeFailedConnection = function () {
        this.displayClose();
        return this;
    };

    this.displayOpen = function (size) {
        var $overlay; // Placerar overlaydiven här temporärt
        if (!this.popupPanel
                || this.popupPanel.length == 0) {
            this.popupPanel = $('#connectionError');
            if (this.popupPanel.length == 0) {
                var $html = $('<div id="connectionError" class="modalPanel" style="height : 200px;">'
                            + '<p id="head" class="infoBigHeading"></p><p id="ingress" class="infoIngressText"></p><div id="contents"></div></div>');
                $('body').append($html);
                $html.jqm({ 'modal': true });
                this.popupPanel = $html;
            }
        }
        if (size) {
            if (size.width)
                this.popupPanel.css('width', size.width);
            if (size.height)
                this.popupPanel.css('height', size.height);
        }
        this.popupPanel.jqmShow();
        this.popupPanel.css('z-index', this.popupPanel.css('z-index') + 2);
        $overlay = $('.jqmOverlay:first');
        $overlay.css('z-index', $overlay.css('z-index') + 2);
        return this;
    }

    this.displayClose = function () {
        if (!this.popupPanel
                || this.popupPanel.length == 0)
            this.popupPanel = $('$connectionError');
        this.popupPanel.jqmHide();
        this.popupPanel.find('#head').text('');
        this.popupPanel.find('#ingress').text('');
        this.popupPanel.find('#contents').html('');
        this.displayingConnectionError = false;
        this.displayingSessionError = false;
        return this;
    }

    // "public" parts
    return {
        startTimer: function () {
            /// <summary>Startar timern som kontrollerar anslutningen, samt ifall man fått några meddelanden eller ngt annat hänt</summary>
            var $connStatus = $('#eventChecker');
            if ($connStatus.length == 0) {
                $connStatus = $('<div id="eventChecker" style="display : none;"></div>');
                $('body').append($connStatus);
            }
            that.checkEvent();
            $connStatus.everyTime(5000, 'eventChecker', function () {
                that.checkEvent();
            });
            return this;
        },
        endTimer: function () {
            /// <summary>Avslutar timern</summary>
            var $connStatus = $('#eventChecker');
            $connStatus.stopTime('eventChecker');
            return this;
        },
        login: function () {
            that.login();
        },
        cancel: function () {
            location.href = 'default.aspx';
        },
        user: function () {
            return that.user;
        }
    }
}

library.prototype.Core.Validation.prototype = {
    _required: true,
    item: null,
    notification: null,
    label: null,
    type: 0,
    validated: false,
    defaultText: '',
    succedText: '',
    failedText: library.prototype.text.libCore_js.Validation.failedText,
    regExp: '',
    types: {
        regexp: 0,
        phone: 1,
        email: 2,
        date: 3,
        length: 4,
        password: 5,
        ajax: 6
    },
    required: function(val) {
        if (val !== undefined) {
            this._required = val;
            this.setup();   // banta ner till endast den nödvändiga delen
            return this;
        }
        return this._required;
    },
    setup: function() {
        /// <summary> Gör alla inställningar som behövs för att valideringen ska fungera, behöver köras när något av objekten har ändrats </summary>
        /// <returns type="library.prototype.Core.Validation">Den aktuella valideringen</returns>
        if (this.item != null) {
            if (typeof (this.item) == 'string')
                this.item = $(this.item);
            if (typeof (this.label) == 'string')
                this.label = $(this.label);

            if (typeof (this.notification) == 'string')
                this.notification = $(this.notification);
            else if (this.notification == null) {
                this.notification = $('<span style="padding-left : 3px;" id="notify"></span>');
                this.item.after(this.notification);
            }
            //            else if (this.item.parent().find('span#notify').length == 1)
            //                this.item.parent().find('span#notify').remove();
            if (this.notification != null
            && this.notification.jquery != undefined
                && this.notification.length > 0) {
                if (this.notification[0].nodeName != 'INPUT')
                    this.notification.text(this.defaultText);
                else
                    this.notification.val(this.defaultText);
            }
        }

        if (this.label != null) {
            if (this.required()
                && this.label.find('span#star').length == 0)
                this.label.append('<span id="star">*</span>');
            else if (!this.required()
                && this.label.find('span#star').length == 1)
                this.label.find('span#star').remove();
        }
        return this;
    },
    validate: function(callback) {
        /// <summary> Gör alla inställningar som behövs för att valideringen ska fungera, behöver köras när något av objekten har ändrats </summary>
        /// <returns type="library.prototype.Core.Validation">Den aktuella valideringen,  validated uppdateras</returns>
        var texts = library.prototype.text.libCore_js.Validation;

        switch (this.type) {
            case this.types.regexp:
                if (this.required() || this.item.val().length > 0) {
                    this.validated = false;
                    var val = this.item.val().match(this.regExp);
                    if (val) {
                        if (val.length === 1
                            && val[0] === this.item.val())
                            this.validated = true;
                    }
                }
                else
                    this.validated = true;
                break;
            case this.types.phone:
                if (this.required() || this.item.val().length > 0) {
                    this.validated = true;
                    if (callback != undefined
                        && typeof (callback) != 'function') {
                        var sender = this.item[0];

                        var iKeyCode, strKey;
                        var validChars = '[0-9]';

                        if (sender.value.length == 0)
                            validChars = '[0-9\+]';

                        if (isIE)
                            iKeyCode = event.keyCode;
                        else
                            iKeyCode = event.which;

                        strKey = String.fromCharCode(iKeyCode);

                        if (iKeyCode != 8) {   // Kollar så vi inte blockar någon som ska sudda
                            if ((sender.value.substr(0, 1) == '+'
                            && sender.value.length > 15)
                        || (sender.value.substr(0, 1) != '+'
                            && sender.value.length > 14)) {
                                this.validated = false;
                                //this.failedText = 'Du kan inte använda fler tecken';
                                this.failedText = texts.validate.phone.toManyChars;
                            }
                            else if (!strKey.match(validChars)) {
                                this.validated = false;
                                //                        if (iKeyCode == 32)
                                //                            strKey = 'Mellanslag ';
                                //                        this.failedText = strKey + ' är ett oglitigt tecken';
                                this.failedText = texts.validate.phone.invalidChar;
                            }
                        }
                    }
                    else {
                        this.validated = (this.item.val().length >= 10);
                        if (!this.validated)
                            this.failedText = texts.validate.phone.toFewChars;
                    }
                }
                else
                    this.validated = true;

                break;
            case this.types.email:
                this.regExp = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
                this.validated = (!this.required() && this.item.val().length < 1)
                                    || this.item.val().match(this.regExp) != null;
                break;
            case this.types.date:
                this.regExp = '(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])';
                this.validated = true;
                break;
            case this.types.length:
                this.validated = (!this.required() && this.item.val().length < 1)
                                || (this.item.val().length >= this.regExp);
                break;
            case this.types.password:
                this.regExp = 5; // Här skulle jag senare kunna utöka funktionerna för att kolla hur bra lösenordet är.
                this.validated = (!this.required()
                                    && this.item.val().length < 1)
                                || (this.item.val().length >= this.regExp);
                break;
            case this.types.ajax:

                break;
            default:
                this.validated = true;
                break;
        }
        if (typeof (this.notification) == 'object') {
            if (this.validated) {
                $(this.notification).text(this.succedText);
            }
            else {
                $(this.notification).text(this.failedText);
            }
        }
        if (callback != undefined
            && callback != null
            && typeof (callback) == 'function')
            callback(this);
        return this;
    },
    value: function(val) {
        if (this.item != null) {
            if (this.value != undefined
            || this.value != null) {
                return $(this.item).val();
            }
            else
                $(this.item).val(val);
        }
        return this;
    },
    bindToEvent: function(event) {
        var sender = this;
        $(this.item).bind(event, sender, function(event) {
            return sender.validate(event).validated;
        });
        return this;
    }
};

library.prototype.Core.ValidationGroup.prototype = {
    _required: true,
    id: '',
    items: [],
    notification: null,
    validated: false,
    succedText: '',
    failedText: library.prototype.text.libCore_js.ValidatinGroup.failedText,
    type: 0,
    types: {
        standard: 0,
        mustMatch: 1
    },
    required: function(val) {
        if (val !== undefined) {
            this._required = val;
            if (this.items.length > 0) {
                for (var i = 0; i < this.items.length; i++) {
                    this.items[i].required(this.required());
                }
            }
            return this;
        }
        return this._required;
    },
    setup: function() {
        /// <summary> Gör alla inställningar som behövs för att valideringen ska fungera, behöver köras när något av objekten har ändrats </summary>
        /// <returns type="library.prototype.Core.Validation">Den aktuella valideringen</returns>
        return this;
    },
    validate: function() {
        /// <summary> Gör alla inställningar som behövs för att valideringen ska fungera, behöver köras när något av objekten har ändrats </summary>
        /// <returns type="library.prototype.Core.Validation">Den aktuella valideringen,  validated uppdateras</returns>
        this.validated = true;
        var notificItems = [];
        for (var i = 0; i < this.items.length; i++) {
            var sameLabel = false;
            //            for (var x = 0; x < notificItems.length; x++) {
            //                if (notificItems[x].selector == this.items[i].label.selector) {
            //                    sameLabel = true;
            //                    break;
            //                }
            //                else
            //                    notificItems.push(this.items[i].label);
            //            }
            //            if (notificItems.length == 0)
            //                notificItems.push(this.items[i].label);

            if (/*!sameLabel
                &&*/!this.items[i].validate()
                              .validated) {
                this.validated = false;
            }
        }
        switch (this.type) {
            case this.types.standard:
                break;
            case this.types.mustMatch:
                if (this.validated
                    && this.items.length > 0) {
                    var value = this.items[0].value();
                    for (var i = 1; i < this.items.length; i++) {
                        if (this.items[i].value() != value) {
                            this.validated = false;
                            break;
                        }
                    }
                }
                break;
        }

        if (this.notification != null) {
            this.notification = $(this.notification);
            if (this.validated)
                this.notification.html(this.succedText);
            else
                this.notification.html(this.failedText);
        }
        if (!this.required)
            this.validated = true;

        return this;
    },
    findByItemId: function(id) {
        /// <summary>Söker igenom alla this.items efter ett validation-item vars item har det eftersökta idt</summary>
        /// <returns type="library.prototype.Core.Validation">Det hittade objektet, eller ett tommt objekt</returns>
        /// <param name="id">Id't som eftersöks</param>
        for (var i = 0; i < this.items.length; i++) {
            if ((this.items[i].item != null
                && (this.items[i].item.attr('id') == id)
                || this.items[i].id == id))
                return this.items[i];
        }
        return new library.prototype.Core.Validation();
    },
    bindToEvent: function(event) {
        var sender = this;
        for (var i = 0; i < this.items.length; i++) {
            var item = this.items[i].item;
            if (item != undefined
                && item != null)
                $(item).bind(event, sender, function(event) {
                    return sender.validate(event).validated;
                });
        }
        return this;
    }
};

var lib = new library();


// Extending clients Javascript

//This prototype is provided by the Mozilla foundation and
//is distributed under the MIT license.
//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license

if (!Array.prototype.filter) {
    Array.prototype.filter = function(fun /*, thisp*/) {
        var len = this.length;
        if (typeof fun != "function")
            throw new TypeError();

        var res = new Array();
        var thisp = arguments[1];
        for (var i = 0; i < len; i++) {
            if (i in this) {
                var val = this[i]; // in case fun mutates this
                if (fun.call(thisp, val, i, this))
                    res.push(val);
            }
        }

        return res;
    };
}

////This prototype is provided by the Mozilla foundation and
////is distributed under the MIT license.
////http://www.ibiblio.org/pub/Linux/LICENSES/mit.license

//if (!Array.prototype.some) {
//    Array.prototype.some = function(fun /*, thisp*/) {
//        var len = this.length;
//        if (typeof fun != "function")
//            throw new TypeError();

//        var thisp = arguments[1];
//        for (var i = 0; i < len; i++) {
//            if (i in this &&
//          fun.call(thisp, this[i], i, this))
//                return true;
//        }

//        return false;
//    };
//}

//This prototype is provided by the Mozilla foundation and
//is distributed under the MIT license.
//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function(elt /*, from*/) {
        var len = this.length;

        var from = Number(arguments[1]) || 0;
        from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
        if (from < 0)
            from += len;

        for (; from < len; from++) {
            if (from in this &&
          this[from] === elt)
                return from;
        }
        return -1;
    };
}

//This prototype is provided by the Mozilla foundation and
//is distributed under the MIT license.
//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license

if (!Array.prototype.some) {
    Array.prototype.some = function(fun /*, thisp*/) {
        var len = this.length;
        if (typeof fun != "function")
            throw new TypeError();

        var thisp = arguments[1];
        for (var i = 0; i < len; i++) {
            if (i in this &&
          fun.call(thisp, this[i], i, this))
                return true;
        }

        return false;
    };
}

// implementing a trim function for strings in javascript
String.prototype.trim = function() {
    return this.replace(/^\s*/, "").replace(/\s*$/, "");
}