/// <reference path="../_references.js" />
/// prointernet AjaxNav
/// Version: 1.8.6166.30335

//#region Events
/*
    live                Fires after page change via ajax - use this for your content updates like image modifications.
    statechanged        After page change, used in dynamic akkordeon lists for example where you change a clientid without the url.
    scrollTop           Before scrollTop - use this to use an custom scrollTop Event (see example).
*/
//#endregion

//#region Examples
/*
    AjaxNav.bind("[yourUniqueEventId]", "[eventName]", function (c) {
        ... your code here
    });
*/
//#endregion

//#region AjaxNav

$.ajaxSetup({
    cache: true
});

var AjaxNav = {

    initContainer: "master",
    goToStartOnError: true,
    clientParams: [],
    headers: [],
    ajax: true,
    scrollTop: true,
    preventScrollAnimation: true,
    scrollTopDelay: 0.5,
    lastLink: $(),
    html4: false,
    html5: false,

    useCustomEventLoadListener: false,

    // Init
    init: function () {
        AjaxNav.html4 = AjaxNav.isFallback();
        AjaxNav.html5 = !AjaxNav.isFallback();

        // Init lastUrl setzen damit wir beim ersten Seitenaufruf kein ContentUpdate auslösen
        // Ausnahme HTML4 mit aktiven Hashtags
        if (AjaxNav.html5 || location.href.indexOf("#") == -1) {
            AjaxNav.lastUrl = AjaxNav.getUrl();
        }

        AjaxNav.events.callHandlers("beforeinit", this);

        // HTML5 Statechange
        if (AjaxNav.html5) {
            window.onpopstate = AjaxNav.events.onpopstate;

            // HTML4 Statechange
        } else {
            $(window).bind("hashchange", AjaxNav.events.onhashchange);
        }

        // Links Handler für async Aktualisierung
        if (AjaxNav.ajax) {
            // Alle Links wenn ajax=true
            AjaxNav.setAsyncLinks("a:not(.static)");
        }

        // Call init StateChange Events
        $(document).ready(function () {

            var currentState = AjaxNav.getState();
            AjaxNav.events.beforestatechange({
                state: currentState,
                url: AjaxNav.getUrl(),
                init: true
            });

            // Call init Events
            AjaxNav.events.callHandlers("init", this);

        });
    },

    // Global Click Handler
    setAsyncLinks: function (selector) {

        if (location.href.match(/(c1mode|flowui)/i)) {
            return;
        }

        if (this._clickHandlers.indexOf(selector) > -1) {
            return;
        }
        this._clickHandlers.push(selector);

        // Click Handler
        $(document).on("click", selector, function (e) {
            var lnk = $(this);
            var baseUrl = lnk.attr("href");

            if (lnk.hasClass("x-btn")) {
                return;
            }

            if (!baseUrl) { return false; }

            var url = AjaxNav.getUrl(baseUrl);
            AjaxNav.lastLink = lnk;

            // No Ajax for Links with data[ajaxNav=false] or target _blank
            if (lnk.data("ajaxNav") == false || lnk.attr("target") == "_blank") {
                return true;
            }

            // No Ajax after FormBuilder Post
            if (location.href.indexOf("#form") > -1) {
                return true;
            }

            // Media Links
            if (baseUrl.indexOf("/media/") > -1 || baseUrl.indexOf("/media(") > -1) {
                return true;
            }

            // Language Switch
            if (lnk.closest("#langSwitcher").length > 0) {
                return true;
            }

            if (url) {
                AjaxNav.lastLink = lnk;
                if (url.match(/^\/.*/) && !url.match(/\./)) {
                    // Hashchange
                    AjaxNav.go(url);

                    e.preventDefault();
                    return false;
                }
            }

        });
    },
    _clickHandlers: [],

    // Events
    events: {

        // Custom Handlers
        customHandlers: [],
        callHandlers: function (event, e) {
            $.each(AjaxNav.events.customHandlers, function (hIdx, handler) {
                if (handler.event == event) {
                    handler.func(e);
                }
            });
        },

        // HTML4 OnHashChange
        onhashchange: function (e) {
            var hashUrl = AjaxNav.getUrl();

            if (hashUrl.indexOf("/") == -1) {
                return false;
            }

            AjaxNav.events.beforestatechange({
                state: AjaxNav.getState(),
                url: AjaxNav.getUrl(),
                init: (e.init ? e.init : false)
            });

            AjaxNav.events.callHandlers("onhashchange", e);
        },

        // HTML5 OnPopState
        onpopstate: function (e) {

            AjaxNav.events.beforestatechange({
                url: AjaxNav.getUrl(),
                state: AjaxNav.getState()
            });

            AjaxNav.events.callHandlers("onpopstate", e);
        },

        // Vor Stateänderung
        beforestatechange: function (e) {

            // Basisfunktion um Content zu laden via AjaxNav.load ...
            e.loadContentBase = function (e, callback) {

                var updateContent = true;

                if (AjaxNav.html4 && e.init) {
                    // Init ContentUpdate bei HTML4 nur wenn Hash aktiv
                    updateContent = (location.hash && location.hash.length > 0);
                }

                AjaxNav.load(e.url, {
                    updateContent: updateContent,
                    getCallback: callback
                });
            }

            // Prüfung ob sich basisurl des aktuellen Aufrufs geändert hat
            e.pageChanged = (AjaxNav.lastUrl && e.url) && (AjaxNav.getBaseUrl(AjaxNav.lastUrl) != AjaxNav.getBaseUrl(e.url));

            // Content funktion die überschrieben werden kann... nach dem Überschrieben führt man seine Animationen auf und ruft e.loadContentBase aus...
            e.loadContent = e.loadContentBase;

            // Erweiterte GetContent Funktion, kann in benutzerdefinierten Scripts verwendet werden z.B. wenn 
            // e.getContent überschrieben wurde und man den Content selbst verarbeiten möchte
            e.getContent = function (x) {
                AjaxNav.load((x.url ? x.url : e.url), {
                    updateContent: false,
                    forceLoad: true,
                    params: x.params,
                    getCallback: x.callback
                });
            }

            AjaxNav.events.callHandlers("beforestatechange", e);

            if (!e.preventDefault) {
                e.loadContent(e, function () {
                    AjaxNav.events.callHandlers("statechanged", e);
                    AjaxNav.events.callHandlers("afterstatechange", e);
                });
            }

        }

    },

    // Live Event
    live: function (handlerId, handlerFunc) {
        if (handlerId && handlerFunc) {
            // Abwärtskompatibilität zu alten C1 Versionen
            AjaxNav.bind(handlerId, "live", handlerFunc);
        } else {
            AjaxNav.events.callHandlers("live");
        }

        //console.log("live", { args: arguments });
    },

    // Event bind
    bind: function (id, event, func) {
        var activeHandlers = $.grep(AjaxNav.events.customHandlers, function (g) { return g.id == id });
        if (activeHandlers.length == 0) {
            AjaxNav.events.customHandlers.push({ id: id, event: event, func: func });
        }
    },

    // Event unbind
    unbind: function (id) {
        AjaxNav.events.customHandlers = $.grep(AjaxNav.events.customHandlers, function (h) {
            return h.id != id;
        });
    },

    // State abfragen
    getState: function (param) {
        var activeState = AjaxNav.getUrlVars();

        if (param) {
            if (activeState[param]) {
                return activeState[param];
            }
        } else {
            return activeState;
        }
    },

    // URL aufrufen
    go: function (url, params, config) {
        var base = this;


        AjaxNav.previousUrl = location.href;

        config = $.extend({
            preventDefault: false,
            paramMode: 0,
            callStateChangeHandler: true,
            renderId: null,
            replace: false
        }, config);

        if (config.sender) {
            AjaxNav.lastLink = config.sender;
        }

        if (config.renderId) {
            base.tempRenderId = config.renderId;
        }

        url = url.replace("&amp;", "&");

        // Extern
        if (url.indexOf("http") > -1 && url.indexOf(location.host) == -1) {
            location.href = url;
            return false;
        }

        // Aktuelle URL abfragen wenn nur ParameterUpdate und URL leer
        if (url == null || url == "") {
            url = AjaxNav.getUrl();
        }

        // QueryString mit params Object mergen 
        if (!config.replace) {
            params = $.extend(AjaxNav.getUrlVars(url), params);
        }

        var paramsQuery = $.param(params);
        var baseUrl = AjaxNav.getBaseUrl(url);
        var newUrl = baseUrl + (paramsQuery ? "?" + paramsQuery : "");

        // HTML5
        if (AjaxNav.html5 && $("[data-ajaxnavstatic]").length == 0) {
            window.history.pushState(params, document.title, newUrl);

            if (config.callStateChangeHandler) {
                AjaxNav.events.beforestatechange({
                    url: newUrl,
                    state: params
                });
            }

        } else {
            // HTML4
            if (paramsQuery.length > 0) {
                // Hash Url verwenden wenn State Query aktiv
                location.href = "#" + newUrl;
            } else {
                // Ansonsten vollständiges Reload mit neuer Url
                location.href = newUrl;
            }
        }

        // Google Analytics
        if (typeof _gaq != "undefined") _gaq.push(["_trackPageview", url]);
    },

    // State ändern
    pushState: function (state, config) {

        config = $.extend({
            url: "",
            replace: false
        }, config);

        AjaxNav.go(config.url, state, config);
    },

    // Hash ändern
    pushHash: function (state) {
        var hashUrl = $.param(state);
        location.hash = $.param(state);
    },

    // Aktuelle URL
    getUrl: function (url) {
        if (!url) { url = location.href; }
        url = url.replace(location.protocol + "//" + location.host, "");
        if (url.indexOf("#") > -1) {
            return url.substr(url.indexOf("#") + 1);
        } else {
            return url;
        }
    },

    // Aktuelle BasisURL ohne Querystring
    getBaseUrl: function (url) {
        var baseUrl = (url ? url : AjaxNav.getUrl());
        if (baseUrl.indexOf("?") > -1) {
            baseUrl = baseUrl.substr(0, baseUrl.indexOf("?"));
        }
        return baseUrl;
    },

    // QueryString in Objekt konvertieren
    getUrlVars: function (url) {
        if (!url) {
            url = AjaxNav.getUrl();
        }

        var vars = {};

        if (url.indexOf('?') > -1) {
            var hashes = url.slice(url.indexOf('?') + 1).split('&');

            for (var i = 0; i < hashes.length; i++) {

                if (vars == null) {
                    vars = {};
                }

                hash = hashes[i].split('=');

                vars[hash[0]] = decodeURI(hash[1]);
            }
        }

        return vars;
    },

    // QueryString abfragen
    getUrlVar: function (name, url) {
        if (!url) {
            url = AjaxNav.getUrl();
        }
        return $.getUrlVars(url)[name];
    },

    // ClientParameter hinzufügen
    // IDs in diesem Array lösen kein ContentUpdate aus (z.B. für OnPage Javascript Funktionen)
    setClientParams: function (params) {
        AjaxNav.clientParams = $.extend(params.split(","), AjaxNav.clientParams);
    },

    // Prüfung ob Fallback aktiv
    isFallback: function () {
        return (!window.history.pushState);
    },

    // Loader
    loader: function (hide) {
        if (hide) {
            $("body").removeClass("ajaxloading");
            $("body").focus();
        } else {
            $("body").addClass("ajaxloading");
        }
    },

    // Content laden
    load: function (url, config) {
        var nav = this;

        config = $.extend({
            params: {},
            updateContent: true,
            updateTitle: true,
            forceLoad: false,
            scrollTop: true,
            url: url
        }, config);

        var data = {
            type: "ajax",
            renderid: (nav.tempRenderId ? nav.tempRenderId : "master")
        }

        data = $.extend(data, config.params);
        data = $.extend(data, nav.headers);

        // Basislink suchen
        if (config.updateContent) {

            var lnk = $("a[href='" + url + "']");
            if (lnk.length > 0) {
                // Link: Queryerweiterung durch JSON Data Attribut
                if (lnk.attr("data") != null) {
                    data = $.extend(data, $.parseJSON(lnk.attr("data")));
                }

                // Link RenderID über Link
                if (lnk.attr("render") != null) {
                    data.renderid = lnk.attr("render");

                    // RenderID über parent div
                } else if (lnk.parents("div[render]").first().attr("render") != null) {
                    data.renderid = lnk.parents("div[render]").first().attr("render");
                }

            }
        }

        // HTML async laden
        var doUpdate = true;
        if (AjaxNav.lastUrl) {
            doUpdate = (AjaxNav.lastUrl != url);
        }

        // Nur PushState, kein ContentUpdate bei registrierten PushState Parametern
        if (AjaxNav.clientParams.length > 0) {
            $.each(AjaxNav.clientParams, function (idx, param) {
                if (url.indexOf(param + "=") > -1) {
                    doUpdate = false;
                    AjaxNav.lastUrl = url;
                    return false;
                }
            });
        }

        // Url prüfen
        var urlValid = (url && url.indexOf("/") > -1);

        // Content Update wenn Url gültig
        if ((doUpdate || config.forceLoad) && urlValid) {
            nav.loader();

            // Url prüfen
            if (url.indexOf("/") == -1) {
                return false;
            }

            $.get(url, data, function (result, status, e) {

                // X Redirect
                if (e.getResponseHeader("X-Location") != null) {
                    AjaxNav.go(e.getResponseHeader("X-Location"));
                    return;
                }

                // Standard ContentUpdate
                var resultObj = $(result);

                if (config.updateContent) {
                    $("#" + data.renderid).replaceWith(resultObj);

                    if (Site.live) {
                        Site.live();
                    }

                    // ScrollTop
                    AjaxNav.events.callHandlers("scrollTop", config);
                    if (config.scrollTop) {
                        var doScrollTop = AjaxNav.scrollTop;

                        // ScrollTop via link class "noscrolltop" deaktiviert
                        if (AjaxNav.lastLink) {
                            if (AjaxNav.lastLink.hasClass("noscrolltop")) {
                                doScrollTop = false;
                            }
                        } else {
                            // Wenn LastLink = null bei hinstory.back() dann kein Scrolltop
                            doScrollTop = false;
                        }

                        // Default
                        if (doScrollTop) {
                            var targetDiv = $("#" + data.renderid);
                            targetDiv.scrollToWhenNotVisible(0);
                        }
                    }

                    // Temporäre RenderId zurücksetzen falls genutzt
                    nav.tempRenderId = null;

                    // LastLink zurücksetzen
                    nav.lastLink = null;

                }

                AjaxNav.events.callHandlers("live", {
                    url: url,
                    data: data,
                    result: result,
                    config: config
                });


                // Callback
                var callbackParams = {
                    valid: true,
                    html: result,
                    loadConfig: config
                };
                if (config.getCallback) {
                    result.valid = true;
                    config.getCallback(callbackParams);
                }

                // Titel aktualisieren
                if (config.updateTitle) {
                    if (resultObj.attr("data-title")) {
                        document.title = resultObj.attr("data-title");
                    }
                }

                // PageId aktualisieren
                if (resultObj.attr("data-pageid")) {
                    $("body").attr("data-pageid", resultObj.attr("data-pageid"));
                }

                AjaxNav.events.callHandlers("afterPageChanged", callbackParams);

                nav.loader(true);

                // Startseite bei Error laden
            }).error(function (e) {
                AjaxNav.handleError(e);

                // Callback
                var callbackParams = {
                    valid: false,
                    error: true,
                    status: e.status,
                    html: "",
                    loadConfig: config
                };
                if (config.getCallback) {
                    config.getCallback(callbackParams);
                }

                AjaxNav.events.callHandlers("afterPageChanged", callbackParams);

                if (config.goToStartOnError) {
                    AjaxNav.go("/");
                }
            });

            AjaxNav.lastUrl = url;

        } else {
            // Kein ContentUpdate, nur LiveFunction ausführen
            AjaxNav.events.callHandlers("live", {
                url: url,
                data: data,
                config: config
            });

            if (Site.live) {
                Site.live();
            }

            // Callback
            if (config.getCallback) {
                config.getCallback();
            }
        }
    },

    // Error handling
    handleError: function (e) {
        AjaxNav.loader(true);

        if (e.status == 404 || e.status == 500) {
            var ex = $(e.responseText).filter("error");
            var url = AjaxNav.getUrl();
            var debug = (ex.attr("debug") == "true");

            var exTitle = "";
            var exMsg = "";
            var exDetails = "";

            if (ex != null && ex.attr("title") != null) {
                exTitle = ex.attr("title");
                exMsg = ex.attr("message");
                exDetails = ex.attr("details")
            } else {
                exTitle = "Es ist ein Fehler aufgetreten";

                var bodyMatch = e.responseText.match(/<body[^>]*>([\w|\W]*)<\/body>/im);
                if (bodyMatch.length > 0) {
                    exMsg = bodyMatch[1];
                }
            }

            // 404 im Live Modus auf Startseite umleiten
            if (e.status == 404) {
                if (debug) {
                    AjaxNav.go("/");
                    return true;
                }
            }

            // Fehlermeldung anzeigen
            var divError = $("#error");
            if (divError.length == 0) {

                $("head").prepend($("<style tyle='text/css'>" +
                    "#error { position:fixed; width:100%; height:0; bottom:0; left:0; background:#fff; z-index:9999; overflow-y:auto; border-top:solid 2px #000; }" +
                    "#error * { font-size:12px!important; }" +
                    "#error hr, #error br { display:none; }" +
                    "#error .excnt { padding:20px; }" +
                    "#error h1, #error h2 { font-size:22px!important; margin-bottom:10px; color:red!important; margin:0!important; }" +
                    "#error .exurl a { color:grey!important; text-decoration:none!important; border:none!important; }" +
                    "#error .exmsg { font-weight:bold; }" +
                    "#error .exdetails { font-family:Courier New; word-break:break-all; }" +
                    "#error a.close { position:absolute!important; right:10px!important; top:10px!important; }" +
                "</style>"));

                divError = $("<div id='error'>" +
                    "<a href='' class='close'>Fehlermeldung schließen</a>" +
                    "<div class='excnt'>" +
                        (!exMsg.match(/<h1>/gi) ? "<h1>" + exTitle + "</h1>" : "") +
                        "<div class='exurl'><a href='" + url + "' class='static' target='_blank'>" + url + "</a></div>" +
                        "<div class='exmsg'>" + exMsg + "</div>" +
                        "<div class='exdetails'>" + exDetails + "</div>" +
                    "</div>" +
                "</div>").appendTo($("body"));

                divError.find("a.close").click(function () {
                    divError.remove();
                });

                divError.animate({ "height": "35%" });

                AjaxNav.bind("hideError", "afterstatechange", function (e) {
                    $("#error").remove();
                });

                AjaxNav.go(AjaxNav.previousUrl, {}, { callStateChangeHandler: false });
            }
        }

    }

};

//#endregion

//#region AjaxForms

AjaxNav.Forms = {

    live: function () {
        this.initForms();
    },

    getFormUrl: function (form, element) {
        var formId = (form.attr("id") ? form.attr("id") : element.attr("id"));

        if (element) {
            // Form Group name via div attribut
            var parentGroupsWithName = element.parents("div[data-group-name]");
            if (parentGroupsWithName.length > 0) {
                formId = parentGroupsWithName.first().attr("data-group-name");
            }
        }

        var postbackUrl = (form.attr("action") ? form.attr("action") : location.href);
        var formUrl = postbackUrl + (postbackUrl.indexOf("?") > -1 ? "&" : "?") +
            "renderid=" + formId +
            "&type=ajax";
        return formUrl;
    },

    initForms: function () {
        var base = this;

        if (document.formsInitComplete) {
            return false;
        }

        // Form Submit
        $(document).on("submit", "form[data-async='true']", function (e) {
            var form = $(this);
            var formId = form.attr("id");

            var validationConfig = base.validationConfig.getConfig(formId);
            var validator = form.validate(validationConfig);

            var formId = form.attr("id");
            var formUrl = base.getFormUrl(form);

            var formData = form.serializeArray();
            formData.push({ name: "submit", value: "true" });

            var formInvalid = false;

            // Prüfung ob Form valid
            var formElements = form.find("input,textarea,select");
            formElements.each(function () {
                var input = $(this);
                if (!validator.element(input)) {
                    formInvalid = true;
                }
            });

            // Form via Ajax senden wenn valid
            if (!formInvalid) {
                $.ajax({
                    type: "POST",
                    url: formUrl,
                    data: formData,
                    success: function (result) {
                        base.processCallback({
                            form: form,
                            data: result
                        })
                    }
                });
            }

            e.preventDefault();
        });

        // FormBuilder Submit
        $(document).on("submit", "form.formbuilder", base.onFormBuilderSubmit);

        // Confirmations
        $(document).on("click", "a[data-confirm-message]", function (e) {
            var message = $(this).attr("data-confirm-message");
            message = message.replace(/\\n/gi, "\n");   // LineBreak Fix ... jQuery verarbeitet keine \n Linebreaks in Attributen
            if (!confirm(message)) {
                e.stopImmediatePropagation();
                return false;
            }
        });

        // Command Click
        $(document).on("click", "*[data-cmd]", function (e) {
            var lnk = $(this);

            var form = lnk.closest("form");
            var formId = form.attr("id");
            var formUrl = base.getFormUrl(form, lnk);
            var field = lnk.closest("[id^='field']");

            var data = form.serializeArray();
            data.push({ name: "form_cmd", value: lnk.attr("data-cmd") });
            if (lnk.attr("data-cmd-value")) {
                data.push({ name: "form_cmd_value", value: lnk.attr("data-cmd-value") });
            }
            data.push({ name: "callback", value: "true" });
            data.push({ name: "callback_field", value: field.attr("id") });

            $.ajax({
                type: "POST",
                url: formUrl,
                data: data,
                success: function (result) {
                    base.processCallback({
                        form: form,
                        data: result
                    })
                }
            });
        });

        // Auto Callback
        $(document).on("change", "*[data-autocallback='true'],*[data-autopostback='true']", function (e) {
            var input = $(this);
            var form = input.closest("form");
            var formId = form.attr("id");
            var formUrl = base.getFormUrl(form, input);
            var field = input.closest("[id^='field']");

            var data = form.serializeArray();

            data.push({ name: "form_cmd", value: input.attr("name") });
            data.push({ name: "form_cmd_value", value: input.val() });

            data.push({ name: "callback", value: "true" });

            if (input.attr("data-autocallback-field")) {
                data.push({ name: "callback_field", value: input.attr("data-autocallback-field") });
            } else {
                data.push({ name: "callback_field", value: field.attr("id") });
            }

            $.ajax({
                type: "POST",
                url: formUrl,
                data: data,
                success: function (result) {
                    base.processCallback({
                        form: form,
                        data: result
                    })
                }
            });
        });

        // File Upload
        $(document).on("change", "form[data-async='true'] *[type='file']", function (e) {
            var file = $(this);

            var form = file.closest("form");
            var formId = form.attr("id");
            var formUrl = base.getFormUrl(form, file);
            var field = file.closest("[id^='field']");

            var data = new FormData();
            data.append("callback", "true");
            data.append("callback_field", field.attr("id"));

            $.each(e.target.files, function (key, value) {
                data.append(file.attr("name") + "-" + key, value);
            });

            $.each(form.serializeArray(), function (idx, obj) {
                data.append(obj.name, obj.value);
            });

            $.ajax({
                type: "POST",
                url: formUrl,
                data: data,
                cache: false,
                dataType: 'json',
                processData: false,
                contentType: false,
                xhr: function () {
                    var myXhr = $.ajaxSettings.xhr();
                    if (myXhr.upload) {
                        myXhr.upload.addEventListener("progress", function (e) {
                            var progress = file.parent().find("progress");
                            if (progress.length == 0) {
                                progress = $("<progress id='" + file.attr("id") + "-progress'></progress>").appendTo(file.parent());
                            }
                            progress.attr({ value: e.loaded, max: e.total });
                        }, false);
                    }
                    return myXhr;
                },
                success: function (result) {
                    base.processCallback({
                        form: form,
                        data: result
                    })
                }
            });
        });

        document.formsInitComplete = true;
    },

    processCallback: function (e) {
        var base = this;
        var data = e.data;
        var form = e.form;
        var formId = form.attr("id");

        // Global Error
        if (data.globalError && data.globalError != "") {
            alert(data.globalError);
            return false;
        }

        // Validation Errors
        var formValid = true;
        var validationErrors = {};
        if (data.errors && data.errors.length > 0) {

            // Array in eindimensionales object umwandeln
            data.errors.forEach(function (e) {
                var element = form.find("[name='" + e.field + "']");

                if (element.length > 0) {
                    validationErrors[e.field] = e.message;
                    formValid = false;
                } else {

                    console.log("Validation Error: Field [" + e.field + "] not found");
                }
            });

        }

        // Valid
        if (formValid) {

            var htmlString = "";

            // JSON
            if (data.html) {
                htmlString = data.html
            } else if (typeof data === "string") {
                // HTML Response
                html = data;
            }

            if (htmlString != "") {
                var newElement = $(htmlString);

                var targetId = newElement.attr("id");

                if (targetId == null) {
                    alert("No FieldId found in HTML Result");
                    return false;
                }

                var targetElement = $("#" + targetId);
                targetElement.replaceWith(newElement);
            }

            // Script Response
            if (data.script) {
                setTimeout(data.script, 50);
            }

            // Live
            AjaxNav.live();

        } else {
            // Fehler
            var validationConfig = base.validationConfig.getConfig(formId);
            var validator = form.validate(validationConfig);
            validator.showErrors(validationErrors);
        }

    },

    validationConfig: {

        defaultConfig: {
            highlight: function (element) {
                // Scroll zu erstem ungültigen Feld
                if ($(".has-error").length == 0) {
                    $(element).focusInvalid();
                }
                $(element).closest('.form-group').addClass('has-error');
            },
            unhighlight: function (element) {
                $(element).closest('.form-group').removeClass('has-error');
            },
            errorElement: 'span',
            errorClass: 'help-block',
            errorPlacement: function (error, element) {
                if (element.parent('.checkbox, .checkbox-inline, .radio, .radio-inline').length) {
                    error.insertAfter(element.parent().parent());
                } else if (element.parent('.form-group, .btn').length) {
                    error.insertAfter(element);
                } else {
                    error.insertAfter(element);
                }
            },
            rules: {}
        },

        customConfigs: {},

        addRule: function (field, rule, ruleMessage) {
            if (typeof rule === "function") {

                if (this.defaultConfig.rules[field] != null) {
                    return;
                }

                var functionRule = {};
                functionRule[field] = field;

                this.defaultConfig.rules[field] = functionRule;

                if (ruleMessage == null) {
                    ruleMessage = "Ungültiges Format";
                }

                $.validator.addMethod(field, rule, ruleMessage);

            } else {
                this.defaultConfig.rules[field] = rule;
            }
        },

        add: function (formId, config) {
            this.customConfigs[formId] = config;
        },

        getConfig: function (formId) {
            var _config = this.defaultConfig;

            if (formId) {
                if (this.customConfigs[formId]) {
                    _config = $.extend(_config, this.customConfigs[formId]);
                }
            }

            return _config;
        }

    },

    onFormBuilderSubmit: function (e) {
        console.log("formbuilder submit");
        var base = AjaxNav.Forms;
        if ($(e.target).hasClass("voting")) {
            return;
        }

        try {
            var form = $(this);
            var formId = form.attr("id");
            var formContainer = form.closest("div[id]");
            var renderId = formContainer.attr("id");

            // Validation Config
            var validationConfig = base.validationConfig.getConfig(formId);
            var validator = form.validate(validationConfig);

            var formId = form.attr("id");
            var formUrl = form.attr("action");

            var formInvalid = false;

            // Prüfung ob Form valid
            var formElements = form.find("input,textarea,select");
            formElements.each(function () {
                var input = $(this);
                if (!validator.element(input)) {
                    formInvalid = true;
                }
            });

            // Form via Ajax senden wenn valid
            if (!formInvalid) {

                // Form erstellen
                var formData = new FormData(form[0]);
                formData.append("submit", "true");
                formData.append("type", "ajax");
                formData.append("renderid", renderId);

                $.ajax({
                    type: "POST",
                    url: formUrl,
                    data: formData,
                    contentType: false,
                    cache: false,
                    processData: false,
                    success: function (resultHtml) {
                        formContainer.html(resultHtml);
                        if (resultHtml.indexOf("validationErrors") == -1) {
                            formContainer.scrollToWhenNotVisible();
                        }

                        //jQuery(window).trigger('resize').trigger('scroll');
                        $('.parallax-window').parallax();
                        // Reinit countdown
                        countdown();

                        //var targetDiv = $("#_286f71a4-ef6f-4631-9110-c78a0b712e3e");
                        //targetDiv.scrollToWhenNotVisible(0);
                    }
                });
            }

            e.preventDefault();
            return false;

        } catch (e) {
            // Standard Form Submit bei Fehler
            return true;
        }

    }

}

AjaxNav.bind("asyncForms", "live", function () {
    if (AjaxNav.ajax) {
        AjaxNav.Forms.live();
    }
});

//#endregion

//#region Extensions

$.extend({
    getUrlVars: function () {
        var vars = [], hash;
        var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
        for (var i = 0; i < hashes.length; i++) {
            hash = hashes[i].split('=');
            vars.push(hash[0]);
            vars[hash[0]] = hash[1];
        }
        return vars;
    },
    getUrlVar: function (name) {
        return $.getUrlVars()[name];
    },
    getHashVars: function () {
        var vars = [], hash;
        var hashes = window.location.href.slice(window.location.href.indexOf('#') + 1).split('&');
        for (var i = 0; i < hashes.length; i++) {
            hash = hashes[i].split('=');
            vars.push(hash[0]);
            vars[hash[0]] = hash[1];
        }
        return vars;
    },
    getHashVar: function (name) {
        return $.getHashVars()[name];
    }
});

//#endregion

//#region SimpleUpload

!function ($) { $.fn.simpleUpload = function (options) { var def = { url: null, change: null, error: null, types: null, fields: null, size: 5120 }; return this.each(function () { function send() { var a = $this.attr("name"), b = new FormData; for (var c in $this[0].files) if ("object" == typeof $this[0].files[c]) { var d = $this[0].files[c]; if (!typeCheck(d.name)) return "function" == typeof params.error && params.error({ type: "fileType" }), !1; if (d.size / params.size > params.size) return "function" == typeof params.error && params.error({ type: "size" }), !1; b.append(a + "[" + c + "]", d) } if ("object" == typeof params.fields) for (var c in params.fields) if ($.isArray(params.fields[c])) for (var e in params.fields[c]) b.append(c + "[" + e + "]", params.fields[c][e]); else b.append(c, params.fields[c]); var f = { url: params.url, data: b, cache: !1, contentType: !1, processData: !1, type: "POST", complete: function () { $this.val(""), params.complete && params.complete(arguments) } }; null != params.error && (f.error = params.error), params.success && (f.success = params.success), params.async && (f.async = params.async), params.beforeSend && (f.beforeSend = params.beforeSend), params.global && (f.global = params.global), params.dataType && (f.dataType = params.dataType), params.contents && (f.contents = params.contents), params.jsonp && (f.jsonp = params.jsonp), params.jsonpCallback && (f.jsonpCallback = params.jsonpCallback), params.password && (f.password = params.password), params.username && (f.username = params.username), params.statusCode && (f.statusCode = params.statusCode), $.ajax(f) } function typeCheck(a) { return $.isArray(params.types) ? params.types.indexOf($.getExt(a)) > -1 ? !0 : !1 : !0 } var $this = $(this); options || (options = {}), $.each(this.attributes, function () { if (this.specified && this.name.indexOf("data-") > -1) { var name = this.name.replace("data-", ""); options[name] = "function" == typeof window[this.value] ? eval(this.value) : this.value } }); var params = $.extend({}, def, options); "function" == typeof params.change && $this.change(function () { params.change($this[0].files) }), params.trigger ? $(params.trigger).click(send) : $this.change(send) }) }, $.extend(!0, { getExt: function (a) { return a.substr(a.lastIndexOf(".") + 1) } }) }(jQuery);

//#endregion

//#region IE8 / IE9 Hotfix
if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function (elt /*, from*/) {
        var len = this.length >>> 0;

        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;
    };
}
//endregion

// Window Load Funktion überschreiben, weil wir sonst das Problem haben dass Javascripts im HTML Response nicht ausgeführt werden bei Ajax Navigation
if (!window.addEventListenerBase) {
    window.addEventListenerBase = window.addEventListener;
    if (!window.addEventListenerBase) {
        window.addEventListenerBase = window.attachEvent;
    }
    window.addEventListener = function (type, listener, useCapture) {
        if (type == "load" && AjaxNav.useCustomEventLoadListener) {
            $(document).ready(listener);
        } else {
            if (window.addEventListenerBase) {
                window.addEventListenerBase(type, listener, useCapture);
            }
            else {
                console.warn("AddEventListener not supported");
            }
        }
    }
}

//#region Init

if (typeof (Site) == 'undefined') Site = {};
Site.Nav = AjaxNav;

document.ajaxNav = AjaxNav;

$(document).ready(document.ajaxNav.init);

//#endregion


