var serverobjecturl = "/serverobject2.asp";

////////////////////////////////////////////////////////////////////////////////
///// for long content strings
function toggleMoreLess(el, imgMore, imgLess) {
    if (!el || !el.previousSibling || !el.previousSibling.previousSibling) { return; }
    var textEl = el.previousSibling.previousSibling;
    var displ = (!textEl.style.display);
    textEl.style.display = (displ) ? "inline" : "";
    el.src = (displ) ? imgLess : imgMore;
}

////////////////////////////////////////////////////////////////////////////////
///// for detail pages (agents)
function openBrWindow(URLPARAMS, type, comtype, email, sms, price, winName,features) {
    var inputerror = 0;
    var errormessage = "";
    if (comtype == "email") {
        if ((email == "") || (email == "EMail-Adresse")) {
            inputerror = 1;
            errormessage = errormessage + "Bitte geben Sie Ihre E-Mail-Adresse an!\n";
        }
    }
    if (comtype == "sms") {
        if ((sms == "") || (sms == "01xx/")) {
            inputerror = 1;
            errormessage = errormessage + "Bitte geben Sie Ihre Handynummer an!\n";
        }
    }
    if ((type == "price") && (price == "")){
        inputerror = 1;
        errormessage = errormessage + "Bitte geben Sie eine Preisgrenze an!\n";
    }
    if (inputerror == 0) {
        if (type == "price") {
            if (comtype == "email") {
                URL = URLPARAMS + "&EMail=" + email + "&Preis=" + price;
            } else {
                URL = URLPARAMS + "&Handy=" + sms + "&Preis=" + price;
            }
        } else {
            if (comtype == "email") {
                URL = URLPARAMS + "&EMail=" + email;
            } else {
                URL = URLPARAMS + "&Handy=" + sms;
            }
        }
        window.open(URL,winName,"toolbar=no,location=no,directories=no,status=0,resizable=no,scrollbars=yes,menubar=no,"+features);
    } else {
        alert(errormessage);
    }
}

////////////////////////////////////////////////////////////////////////////////
///// upsize/downsize images
function UpsizePicture(el, tnPIC, picURL) {
    if (el.src.indexOf(picURL) >= 0) {
        el.src = tnPIC;
    } else {
        el.src = picURL;
        el.removeAttribute("width");
        el.removeAttribute("height");
    }
}

////////////////////////////////////////////////////////////////////////////////
//// bookmark
function BookmarkPage(url, text) {
    if ((typeof window.sidebar == "object") && (typeof window.sidebar.addPanel == "function")) {
        window.sidebar.addPanel(text, url, "");
    } else if (document.all && !window.opera) {
        window.external.AddFavorite(url, text);
    }
}

////////////////////////////////////////////////////////////////////////////////
//// Elemente mit Ziel versehen
function contentMenuButtonClick(uri) {
    top.document.location.href = uri;
}

////////////////////////////////////////////////////////////////////////////////
//function openSourceCode(optionalFilename, optionalLineNumber) {
//    var filename;
//    if (optionalFilename) {
//        filename = optionalFilename;
//    } else {
//	filename = window.location.pathname;
//	filename = filename.replace(/\/\d+\//, "");
//    }
//    var translated_filename = new ServerObject().Method("base::Shop::ShopApp->FindFile", filename);
//    var url = "komodo://" + translated_filename + (optionalLineNumber ? " -l " + optionalLineNumber : "");
//    //alert(url);
//    document.body.insertAdjacentHTML("BeforeEnd", "<iframe style='display: none' src='" + url + "'></iframe>");
//}

////////////////////////////////////////////////////////////////////////////////
// doppelclick-sourcecode-oeffner
function design_mode_window_dblclick(e) {
    if (!e) { e = event; }
    if (!e) { return; }
    var el = e.srcElement || e.target;
    if (!el) { return; }

    var stack = new Array();
    while (el) {
        if (el.getAttribute && el.getAttribute("template")) {
            stack.push({ template : el.getAttribute("template"), callerpackage : el.getAttribute("callerpackage") });
        }
        el = (el.previousSibling) ? el.previousSibling : el.parentNode;
    }

    var package_file_to_open;
    var template_file_to_open;
    var debug_str = "";
    for (var idx = 0; idx < stack.length; idx++) {
        debug_str += stack[idx]["template"] + " : " + stack[idx]["callerpackage"] + "\n";
        package_file_to_open = stack[idx]["callerpackage"];
        if (stack[idx]["template"].indexOf("wrapper") < 0) {
            template_file_to_open = (template_file_to_open) ? template_file_to_open : stack[idx]["template"];
        }
    }
    alert(debug_str);

    // caller-package-file:
    if (package_file_to_open) {
        var file_and_line = package_file_to_open.split("#");
        openSourceCode(file_and_line[0], file_and_line[1]);
//        if (file_and_line.length == 2) {
//            openSourceCode(file_and_line[0], file_and_line[1]);
//        } else {
//            openSourceCode(package_file_to_open);
//        }
    }
    // template-file:
    if (template_file_to_open) {
        openSourceCode(template_file_to_open)
    }
}

////////////////////////////////////////////////////////////////////////////////
function design_mode_find_anchor(el) {
    while (el) {
        if (el.getAttribute && el.getAttribute("template")) {
            return el;
        }
        el = (el.previousSibling) ? el.previousSibling : el.parentNode;
    }
    return null;
}

////////////////////////////////////////////////////////////////////////////////
function design_mode_hover(el) {
    var anchor = design_mode_find_anchor(el);
    if (!anchor) { return; }

    el = anchor;
    while (el && el.tagName != "TD" && el.tagName != "TABLE" && el.tagName != "DIV" && el.tagName != "SPAN") {
        el = (el.previousSibling) ? el.previousSibling : el.parentNode;
    }
    if (!el) { return; }

    el.style.border = "1px dashed red";
    el.title = anchor.getAttribute("template");
    el.onclick = function() {
        openSourceCode(anchor.getAttribute("template"));
    };
    el.onmouseout = function () {
        el.style.border = "";
        el.title = "";
        el.onclick = null;
    };
}

////////////////////////////////////////////////////////////////////////////////
function design_mode_window_mouseover(e) {
    if (!e) { e = event; }
    if (!e) { return; }
    var el = e.srcElement || e.target;

    if (e.shiftKey) {
        design_mode_hover(el);
    }
}

////////////////////////////////////////////////////////////////////////////////
function attach_designhandlers() {
    var main_element;
    if (isMozilla())    { main_element = window; }
    if (isIE())         { main_element = window.document; }
    main_element.ondblclick = design_mode_window_dblclick;
    main_element.onmouseover = design_mode_window_mouseover;
}

////////////////////////////////////////////////////////////////////////////////
// Testen, ob im aktuellen Namespace eine Funktion namens 'DoInit' exisitert. Wenn ja, dann onload=DoInit
function window_OnLoad(e) {
    if (window.DoInit) { DoInit(e); }
    if (document.body.getAttribute("design_mode")) { attach_designhandlers() }
}
window.onload = window_OnLoad;

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Darstellungsbox rechts am Rand
addEvent(window, 'load', initDisplayBox)

function initDisplayBox() {
    var darstellungsForm = document.forms.darstellungsAuswahl;

    //Box zur Auswahl der Darstellungen
    if (darstellungsForm) {
        darstellungen = darstellungsForm.getElementsByTagName('select');
        for (var i = 0; i < darstellungen.length; i++) {
            addEvent(darstellungen[i], 'change', submitWrapperForDarstellung);
            addEvent(darstellungen[i], 'keypress', onEnterSubmit);
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// sonst drecht der FF durch
function submitWrapperForDarstellung(){
    document.forms.darstellungsAuswahl.submit();
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// NaviJS (Suchfeld, linkes Menue usw)
addEvent(window, 'load', initNavi);
//addEvent(window, 'unload', rememberScrollBar);

////////////////////////////////////////////////////////////////////////////////
function initNavi(){
    var suchKategorie   = document.getElementsByName('selectedRootCategory')[0];
    var headNavi        = document.getElementById('headNavi');
    headNavi        = headNavi || document.getElementById('searchNavi');
    if(!suchKategorie || !headNavi) { return; }

    //hässlicher grauer Rahmen beim Menü wird daduch beseitigt
    removeFocus();
    //resetScrollBar();

    var topNaviTabs = headNavi.getElementsByTagName('table');
    for(var i=0; i<topNaviTabs.length; i++) {
        addEvent(topNaviTabs[i], 'keyup', keepNaviTabOpen.bind(topNaviTabs[i].tBodies[0]) );
        addEvent(topNaviTabs[i], 'click', keepNaviTabOpen.bind(topNaviTabs[i].tBodies[0]) );
    }


    addEvent(document, 'click', closeNaviTabs);
    addEvent(suchKategorie, 'keypress', onEnterSubmit);
}

////////////////////////////////////////////////////////////////////////////////
function onEnterSubmit(e) {
    if (!e) { e = window.event; }
    var key = e.charCode || e.keyCode;
    var el = e.srcElement || e.target;

    if (key != 13) { return; }

    while (el && el.tagName.toUpperCase() != "FORM") {
        el = el.parentNode;
    }

    if(el.tagName.toUpperCase() == 'FORM') el.submit();
}

////////////////////////////////////////////////////////////////////////////////
//sobald man in das suchfeld geklick hat, bleibt der weiße Hintergrund da
function keepNaviTabOpen(e) {
    closeNaviTabs();
    this.className = 'staysVisible';
    this.parentNode.wasActivatedByClick = true;
}

////////////////////////////////////////////////////////////////////////////////
function closeNaviTabs(e) {
    if(e) {
        var el = e.target;
        while(el) {
            if( el.id && el.id == 'headNavi' ) { return; }
            if( el.className && el.className == 'optionList' ) { return; }
            el = el.parentNode;
        }
    }
    var headNavi        = document.getElementById('headNavi');
    var topNaviTabs     = headNavi.getElementsByTagName('table');
    if( !headNavi || !topNaviTabs ) { return; }

    // foreach
    var headNaviButton;
    for(var i = 0; (headNaviButton = topNaviTabs[i]) || (i < topNaviTabs.length); i++)
    {
        headNaviButton.tBodies[0].className = '';
        headNaviButton.wasActivatedByClick = false;
    }
}

////////////////////////////////////////////////////////////////////////////////
// findet die Tabelle, in der sich der Buttonlink befindet
function getButton(el)
{
    while (el) {
        if(el.tagName && el.tagName == 'table') {
            return el;
        }
        el = el.parentNode;
    }
    return undefined;
}



////////////////////////////////////////////////////////////////////////////////
//hässlicher grauer Rahmen beim Menü wird daduch beseitigt
// bissel kompliziert, weil das nur beim mausclick passieren soll, nicht beim
// Tab drücken, aber klick event reicht nicht, aus
function removeFocus(){
    var menuLinks = [];
    var menus =     [
        document.getElementById('rubrikInhalt'),
        document.getElementById('headNavi'),
        document.getElementById('searchNavi'),
        document.getElementById('menu'),
    ];

    for(var i=0; i<menus.length; i++)
    {
        if(!menus[i]) { continue; }
        menuLinks = menus[i].getElementsByTagName('a');
        for(var j=0; j<menuLinks.length; j++) {
            addEvent(menuLinks[j], 'mousedown', function (e) { this.focusedByMouse = true; });
            addEvent(menuLinks[j], 'focus', function () {
                if( !this.focusedByMouse ) { return; }
                this.blur();
            });
            addEvent(menuLinks[j], 'mouseup', function () { this.focusedByMouse = false; } )
            addEvent(menuLinks[j], 'mouseout', function () { this.focusedByMouse = false; } )
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
function rememberScrollBar() {
    var scrollBarPosition = window.pageYOffset || document.documentElement.scrollTop;
    document.cookie = "scrollBarPosition=" + scrollBarPosition;
}

////////////////////////////////////////////////////////////////////////////////
function resetScrollBar() {
    var oldScrollPosition = getValueFromCookie('scrollBarPosition');
    if (!oldScrollPosition) { return; }

    window.scrollTo(0,oldScrollPosition);
}

////////////////////////////////////////////////////////////////////////////////
function getValueFromCookie(searchKey) {
    if( !document.cookie ) { return; }
    // REGEX : alles zwischen dem zu suchenden Wert bis zu einem
    //         Semikolon in der Variablen RegExp.$1 ablegen
    if( document.cookie.match( searchKey + "=([^;.]*)" ) ) { return RegExp.$1; }
    return undefined;
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// verhindert das Einfuegen ueber Strg+V und rechte Maustaste
// funktioniert nur im FF und IE, teilweise im Opera
var fieldLength = 0;
var initialValue = '';

addEvent(window, 'load', initDenyPasteFields);

////////////////////////////////////////////////////////////////////////////////
// Initialisierung, für alle Elemente, die als Attribut 'paste="deny"' haben
// zB <input type="text" paste="deny">
// Raussuchen der Elemente
function initDenyPasteFields() {
    var inputs = document.getElementsByTagName('input');

    for (var i = inputs.length - 1; i > -1; i--)
    {
        if (inputs[i].getAttribute('paste') && inputs[i].getAttribute('paste') == "deny") {
            denyPaste(inputs[i]);
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// Anhängen der EventHandler
function denyPaste(el) {
    fieldLength = el.value.length;
    if(isIE())
    {
        addEvent(el, 'paste', denyPasteIE);
        addEvent(el, 'drop', denyPasteIE);
        return;
    }
    if(isMozilla() || isOpera()) // funzt lustigerweise auch im Safari
    {
        fieldLength = el.value.length;
        addEvent(el, 'click', function () {fieldLength = el.value.length; initialValue=el.value;});
        addEvent(el, 'focus', function () {fieldLength = el.value.length; initialValue=el.value;});
        // verhindert drag and drop, leider nur beim FF (nich opera)
        addEvent(el, 'dragover', function () {fieldLength = el.value.length; initialValue=el.value;});
        addEvent(el, 'dragdrop', denyPasteFF);
        addEvent(el, 'input', denyPasteFF);
    }
}
////////////////////////////////////////////////////////////////////////////////
// EventHandler IE
function denyPasteIE(e) {
    e.preventDefault();
    raisePasteError(e.target);
    return false;
}

////////////////////////////////////////////////////////////////////////////////
// EventHandler FF
function denyPasteFF(e) {
    el = e.target;
    var newFieldLength = el.value.length;

    // wenn mans kleiner 1 macht, kann man zwar keine kuerzeren strings einfuegen,
    // aber loeschen mit markieren geht dann auch nicht mehr.
    // erlaubt man das loeschen mit markieren, kann auch etwas markiert werden
    // und da wieder eingefuegt werden => ein teufelskreis
    // vlt trotzdem was mit onselect basteln
    if (newFieldLength - fieldLength > 1)
    {
        raisePasteError(el);
    } else {
        fieldLength = newFieldLength;
        initialValue= el.value;
    }
}

////////////////////////////////////////////////////////////////////////////////
// Popup, was bescheid sagt, sobald was eingefuegt wurde
function raisePasteError(el) {
    if(!isIE())
    {
        el.value = initialValue;
        fieldLength = initialValue.length;
    }
    el.focus();
    alert("Das Einfügen ist für dieses Element deaktiviert.");
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// das Umsatzsteuerid-Feld in der, zB auf der Benutzerprofilseite,
// wird erst eingeblendet, wenn man einen Firmennamen eingibt
addEvent(window, 'load', initUSTID);

////////////////////////////////////////////////////////////////////////////////
function initUSTID() {
    trigger = document.getElementsByName('FIRMA');
    if(!trigger) { return; }

    for(var i=0; i<trigger.length; i++)
    {
        if(trigger[i].getAttribute('toggle'))
        {
            trigger[i].toggleEl = trigger[i].parentNode
            do{
                trigger[i].toggleEl = trigger[i].toggleEl.nextSibling;
            } while (trigger[i].toggleEl.tagName != 'DIV')

            addEvent(trigger[i], 'keyup', makeVisible);
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
function makeVisible(e)
{
    if (!e) { e = window.event; }
    var el = e.srcElement || e.target;

    if(el.value.length == 0) {
        el.toggleEl.style.display = 'none';
        return 0;
    }

    if(el.toggleEl.style.display != 'block') {
        el.toggleEl.style.display = 'block';
    }

}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// der Bestellen-Button auf der Bestellung-Abschicken-Seite wird nur
// eingeblendet, wenn man die Widerrufserklaerung bestaetigt hat.
addEvent(window, 'load', initBestellung);

////////////////////////////////////////////////////////////////////////////////
// initialisiert die kleinen sachen auf der Bestellübersicht-Seite
function initBestellung() {
    initSendOrder();
    disableConfirmationButton();
    initHausnummer();
}

////////////////////////////////////////////////////////////////////////////////
// beim Adressfeld STRASSE+Hausnummer muss eine Nummer drin vorkommen
function initHausnummer() {
    var strasse_feld = document.getElementById('strasse');
    if (!strasse_feld) { return; }
    addEvent(strasse_feld, 'blur', function (e) {
        if (this.value.match(/\d/)) { return; }
        alert('Bitte vergessen sie nicht, ihre Hausnummer im Feld "Straße und Hausnummer" anzugeben.')
    });
}

////////////////////////////////////////////////////////////////////////////////
function disableConfirmationButton() {
    var confButton = document.getElementById('confirmationButton');
    if(!confButton) { return; }
    confButton.disabled = true;
}

////////////////////////////////////////////////////////////////////////////////
function initSendOrder() {
    var sendButton = document.getElementById('sendOrderConfirmation');
    if(!sendButton) { return; }

    addEvent(sendButton, 'click', toggleSendButtonActive);
}

////////////////////////////////////////////////////////////////////////////////
// aktiviert/deaktiviert den Widerrufsbelehrung-Bestätigen-Knopf
// auf der Bestellung-Abschicken-Seite
function toggleSendButtonActive(e) {
    if (!e) { e = window.event; }
    var el = e.srcElement || e.target;

    if(el.checked) {
        document.getElementById('confirmationButton').disabled = false;
    } else {
        //knopf deaktivieren
        document.getElementById('confirmationButton').disabled = true;
    }
    return;
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// auf der Bestellung-Abschicken-Seite kann man die Lieferadressen mit so einem
// Dropdownteil auswaehlen, sobald man eine Adresse gewaehlt hat, wird submittet
addEvent(window, 'load', initReloadAfterAdressSelection);

////////////////////////////////////////////////////////////////////////////////
function initReloadAfterAdressSelection(e) {
    var deliveryAdressButton = document.getElementById('deliveryAdressButton');
    if( !deliveryAdressButton ) { return; }

    addEvent(
        document.getElementsByName('ADRESSNR')[1],
        'change',
        function(e){ submitFormForElement(this); }
    );

    deliveryAdressButton.parentNode.removeChild(deliveryAdressButton);
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// auf der Bestellung-Abschicken-Seite muss die Groesse vom Warenkorb dynamisch
// angepasst werden. Ging mit CSS nicht.
addEvent(window, 'load', initResizeCart);

////////////////////////////////////////////////////////////////////////////////
// bringt den Warenkorb auf der Bestellung-Abschicken-Seite auf die richtige
// Groesse, damit der Warenkorb nicht unter dem Pfeil verschwindet.
// das spielt noch mit der CSS-Eigenschaft overflow:auto zusammen
// gibt also nen Scrollbalken, wenn der Warenkorb zu lang wird
function initResizeCart(e) {
    var cart = document.getElementById('warenkorb');
    var orderOverview = document.getElementById('corners');
    if(!cart || !orderOverview) { return; }
    var cartContent = document.getElementsByClassName('ContentInnerFrame', cart)[0];

    //if( cartContent.offsetHeight > orderOverview.offsetHeight - 320 ) { return; }

    cartContent.style.overflow = 'auto';

    if(isIE6()) {
        cartContent.style.height    = (orderOverview.offsetHeight - 320) + 'px';
    } else {
        var maxHeight = orderOverview.offsetHeight - 320;
        var minHeight = cartContent.offsetHeight + 5;
        cartContent.style.maxHeight =  maxHeight + 'px';
        if( minHeight < maxHeight ) { cartContent.style.minHeight = minHeight + 'px'; }
    }
}


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// labels werden nicht mehr versehentlich selektiert, wenn man draufklickt
addEvent(window, 'load', initPreventLabelSelection);

////////////////////////////////////////////////////////////////////////////////
function initPreventLabelSelection() {
    // beim FF+Safari stehts im CSS, bei Opera kann man eh keine Labels versehentlich selektieren
    if(!isIE()) { return; }
    var labels = document.getElementsByTagName('label');
    if(!labels.length) { return; }

    for(var el, i = 0; el = labels[i]; i++) {
        //geht nich, wird aber bestimmt nich 2 onselectstart-eventhandler geben
        //addEvent(labels[i], 'selectstart', function () { return false; }
        labels[i].onselectstart = _false;
    }
}

function _false() { return false; }

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ueberall, wo ein linkto als html-attribut steht, sollte der wert vom linkto
// der pfad sein, wohin der link fuehren soll
// <div linkto="/index.html">
//
// da das mit javascript gemacht ist, sollte es auch eine konventionelle
// Möglichkeit geben, dahin zu gelangen (zB mit einem <a href="..."></a>)
addEvent(document, 'click', gotoLink);

////////////////////////////////////////////////////////////////////////////////
// geht zu der seite, deren pfad im linkto-attribut des elements steht
function gotoLink(e) {
    var el = e.target;
    //alert(el.tagName);

    if (el.tagName.toUpperCase() == 'A') { return; }
    while (el) {
        if (el.getAttribute && el.getAttribute('linkto')) {
            e.preventDefault(); // <= sowas wie return false;
            self.location.href = el.getAttribute('linkto');
            return;
        }
        el = el.parentNode;
    }
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// auf den Vergleichsseiten, die Vergleichstabelle hat die Attributspalte links
// fest sitzen, so dass scrollen der Vergleichsartikel möglich ist, aber die
// Vergleichsattribute immernoch zu sehen sind. Diese Festsitzende Spalte wird
// hier als Tabelle erstellt und die Höhen der Spalten auf die richtige Größe
// angepasst (=> deswegen als JS und nicht HTML).
//
// benötigt getOffsetCoords aus global.js
addEvent(window, 'load', initComparisonTable);
//addEvent(window, 'resize', initComparisonTable);
var mouseStillPressed       = false;
var scrollIntervalActive    = false;
var scrollPoints            = [];

////////////////////////////////////////////////////////////////////////////////
// erstellen der Pfeile + Extratabelle, die dann die feste Attributspalte ist
function initComparisonTable() {
    var comparisonTable = document.getElementById('scrollingTable');
    var attributeTable  = document.getElementById('attributeTable');
    var scrollDiv       = document.getElementById('scrollDiv');
    var bigCart         = document.getElementById('bigCart');
    if(!comparisonTable || !attributeTable || !scrollDiv || !bigCart)  { return; }
    //var divHasScrollbar = scrollDiv.scrollWidth > document.body.scrollWidth;
    if(isMozilla()) { bigCart.style.width = (window.innerWidth - 60) + 'px'; }
    var divHasScrollbar = scrollDiv.scrollWidth - 1 > scrollDiv.clientWidth;
    if( !divHasScrollbar) { return; }

    equaliseRowHeight(comparisonTable.tBodies[0].rows, attributeTable.tBodies[0].rows);
    equaliseRowHeight(comparisonTable.tHead.rows, attributeTable.tHead.rows);
    equaliseRowHeight(comparisonTable.tFoot.rows, attributeTable.tFoot.rows);

    // Pfeile zum blättern
    var pfeilVor = document.getElementById('pfeilVor');
    pfeilVor.direction = 1;
    addEvent(pfeilVor, 'mousedown', keepScrolling);
    addEvent(pfeilVor, 'mouseout',  stopScrolling);
    addEvent(pfeilVor, 'mouseup',   stopScrolling);

    var pfeilRueckw = document.getElementById('pfeilRueckw');
    pfeilRueckw.direction = -1;
    addEvent(pfeilRueckw, 'mousedown',  keepScrolling);
    addEvent(pfeilRueckw, 'mouseout',   stopScrolling);
    addEvent(pfeilRueckw, 'mouseup',    stopScrolling);

    attributeTable.style.display = isIE() ? 'block' : 'table';
    scrollDiv._pfeilVor     = pfeilVor;
    scrollDiv._pfeilRueckw  = pfeilRueckw;

    // scrollpunkte, damit von spalte zu spalte gescrollt wird
    var scrollposition  = 0;
    var maxScrollLeft   = scrollDiv.scrollWidth - scrollDiv.offsetWidth ;
    for(var i = 0; i < comparisonTable.rows[0].cells.length - 2; i++)
    {
        scrollPoints.push(scrollposition);
        if(scrollposition > maxScrollLeft) { break; }
        scrollposition += comparisonTable.rows[0].cells[i+1].offsetWidth;
    }

    scrollPoints.push(maxScrollLeft);
}

////////////////////////////////////////////////////////////////////////////////
// bringt die Zellen der Attributtabelle auf die Größe der Zeile
function equaliseRowHeight(pivotRows, adjustRows)
{
    var attributeCell;
    var correspondingCell;

    for(var i = 0; i < pivotRows.length; i++)
    {
        attributeCell       = adjustRows[i].cells[0];
        correspondingCell   = pivotRows[i].cells[0];

        if(isIE() || isWebkit()) {

            var padTop      = 0;
            var padBottom   = 0;
            if(correspondingCell.parentNode.parentNode.tagName == 'TBODY') {
                padTop      = parseInt(getComputedStyle(correspondingCell, null).paddingTop, 10);
                padBottom   = parseInt(getComputedStyle(correspondingCell, null).paddingBottom, 10);
            }

            attributeCell.style.height  = (correspondingCell.offsetHeight - padTop - padBottom) + 'px';
        } else {
            attributeCell.style.height  = correspondingCell.clientHeight + 'px';
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// bei gedrueckter Maustaste wird die Vergleichstabelle die ganze Zeit gescrollt
function keepScrolling(e)
{
    mouseStillPressed = true;
    scrollInto(this.direction); // this ist das el, wo der eventhandler dranklebt
}

////////////////////////////////////////////////////////////////////////////////
// beim Loslassen oder Raushovern aus dem Pfeil, wird nicht mehr gescrollt
function stopScrolling(e) {
    mouseStillPressed = false;
}

////////////////////////////////////////////////////////////////////////////////
// scrollt die Vergleichstabelle auf den Vergleichsseiten nach links
// direction ist vorwärts => 1 und rückwärts => -1
function scrollInto(direction)
{
    if(!direction) { return; }
    var scrollDiv       = document.getElementById('scrollDiv');
    var currentPosition = scrollDiv.scrollLeft;

    if(direction < 0)           // rückwärts
    {
        var i = scrollPoints.length - 1;
        while(scrollPoints[i] >= currentPosition) { i--; }
    } else {                    // vorwärts
        var i = 0;
        while(scrollPoints[i] <= currentPosition) { i++; }
    }

    scrollElementTo(scrollDiv, scrollPoints[i], 150);
}

////////////////////////////////////////////////////////////////////////////////
// scrollt die Vergleichstabelle grafisch nach rechts oder links
// time in Millisekunden, falls keine zeit angebeben ist, wird 1000ms angenommen
function scrollElementTo(el, endPosition, time)
{
    if(!el || endPosition == null || scrollIntervalActive) { return; }
    time = time || 1000;

    var startPosition       = el.scrollLeft;
    var fps                 = 25;
    var intervalTime        = 1000/fps;
    var stepWidth           = (endPosition - startPosition) / ((time * fps)/1000);
    var direction           = stepWidth > 0 ? 1 : -1;
    scrollIntervalActive    = true;

    var scrollInterval = setInterval(function () {
            startPosition += stepWidth;
            if (startPosition * direction >= endPosition * direction) {
                el.scrollLeft = endPosition;
                clearInterval(scrollInterval);
                scrollIntervalActive = false;

                if (el.scrollLeft == scrollPoints[0]) {
                    el._pfeilRueckw.style.visibility = 'hidden';
                } else if(el.scrollLeft == scrollPoints[scrollPoints.length - 1]) {
                    el._pfeilVor.style.visibility = 'hidden';
                } else {
                    el._pfeilRueckw.style.visibility = 'visible';
                    el._pfeilVor.style.visibility = 'visible';
                }
                if (mouseStillPressed) { scrollInto(direction); }

            } else {
                el.scrollLeft = startPosition;
            }
        },
        intervalTime
    );
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Testeoboxauf der Artikeldetails-Seite
addEvent(window, 'load', initTesteoBox);

////////////////////////////////////////////////////////////////////////////////
// lädt die testeobox auf der Artikeldetailseite
function initTesteoBox() {
    var testeo_target = document.getElementById('testeoContainer');
    if (!window.testeo_object || !testeo_target ) { return; }
    if (!window.testeo_object.SCRIPT_WITHOUT_SCRIPTTAG) { return; }

    testeo_target.innerHTML = testeo_object.SCRIPT_WITHOUT_SCRIPTTAG;
    var testeo_script = getDOMBuilder().SCRIPT({ type : 'text/javascript' });
    document.getElementsByTagName('head')[0].appendChild(testeo_script);

    document._ugly_old_write = document.write;
    document.write = TesteoDocumentWrite;
    testeo_script.src = testeo_object.SCRIPT_SRC;
    // nach 3 sekunden document.write wiederherstellen
    //setTimeout(restoreDocumentWrite, 3000);
}

////////////////////////////////////////////////////////////////////////////////
// blendet die Testeobox dann auch ein, wenn sie fertig geladen ist
// falls es probleme mit der testeoseite gibt, bleibt eben alles ausgeblendet
function showTesteoBox() {
    var testeo_target = document.getElementById('testeoContainer');
    if (!testeo_target) { return; }
    testeo_target.className = '';
}

////////////////////////////////////////////////////////////////////////////////
// document.write wiederherstellen
function restoreDocumentWrite () {
    if( !document._ugly_old_write ) { return; }
    document.write = document._ugly_old_write;
    document._ugly_old_write = null;
}

////////////////////////////////////////////////////////////////////////////////
// Testeo benutzt document.write in ihrem Javascript, deswegen würde es nicht im
// <head> funktionieren, im <body> würde es funktionieren, aber da wird der code
// im script nicht mehr ausgeführt, was im <head> wiederum geht
// WARUM NEHMEN DIE NICH EINFACH DOM-FUNKTIONEN STATT document.write???
function TesteoDocumentWrite(htmlString) {
    var testeo_target = document.getElementById('testeoContainer');
    if( !testeo_target ) { return; }
    testeo_target.innerHTML = htmlString + testeo_target.innerHTML;
    showTesteoBox();
    //restoreDocumentWrite();
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// bindet die "Suchfunktion dem Browser hinzufügen"-Funktion ein
addEvent(window, 'load', initAddSearchEngine);

////////////////////////////////////////////////////////////////////////////////
// Fügt dem Browser, wenn ers kann, Computerhandlung als Searchengine hinzu
function initAddSearchEngine() {
    var addSearchEnginebutton = document.getElementById('addSearchEngineButton');
    if(!addSearchEnginebutton) { return; }

    addEvent(addSearchEnginebutton, 'click', function (e) {
        try {
            var url = '';
            if( location.href.match('^(https?:\/\/[^\/]*)') ) {
                url = RegExp.$1;
            }
            external.AddSearchProvider(url + '/add_searchengine.xml');
        } catch (err) {
            alert('Leider unterstützen nur Firefox und Internet Explorer ab der Version 7 dieses Feature.');
        }

        e.preventDefault();
    });
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// beim Klick auf ein Lieferbarkeitsbild wird die Lieferbarkeitentabelle eingeblendet
addEvent(window, 'load', initLieferbarkeitsPopup);

////////////////////////////////////////////////////////////////////////////////
function initLieferbarkeitsPopup() {
    addEvent(document.body, 'click', function (e) {
        if( e.target.parentNode.getAttribute('myType') != 'statusImage' ) { return; }
        var popup = getLieferbarkeitenPopup(e.target.parentNode);
        if( !popup ) { return; }
        popup.show();
    });
}

////////////////////////////////////////////////////////////////////////////////
// getLieferbarkeitenPopup
function getLieferbarkeitenPopup(target) {
    if( !window._cachedLieferbarkeitsPopup ) {
        var lieferbarkeiten = document.getElementById('lieferbarkeitsTabelle');
        if( !lieferbarkeiten ) { return; }

        var $ = getDOMBuilder();

        //######################################################################
        var popup, popup_content, closebutton, lieferbarkt_neu;

        popup           =   $.DIV( {'id' : 'lieferbarkeitenpopup', 'class' : 'dropShadow'},
        popup_content   =       $.DIV(
        closebutton     =           $.A({ 'class' : 'close', href : '#' }, 'schließen'),
        lieferbarkt_neu =           lieferbarkeiten.cloneNode(true)
                                )
                            );

        popup.style.width   = lieferbarkeiten.clientWidth + 'px';
        popup_content.popup = popup;

        addEvent(popup_content, 'click', function (e) { this.popup.close(); e.preventDefault(); } );

        //######################################################################
        popup.show = function () {
            this.style.display = 'block';
        }

        //######################################################################
        popup.close = function () {
            this.style.display = 'none';
        }

        window._cachedLieferbarkeitsPopup = popup;
    }
    target.appendChild(window._cachedLieferbarkeitsPopup);
    return window._cachedLieferbarkeitsPopup;
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// beim Klick auf ein Lieferbarkeitsbild wird die Lieferbarkeitentabelle eingeblendet
addEvent(window, 'load', initAddArtikelPopup);
var articleAddedPopup;

////////////////////////////////////////////////////////////////////////////////
function initAddArtikelPopup() {
    // wir befinden uns auf der Warenkorbseite (cart.htm), da müsste man
    // nahezu den gesamten content nachladen, deswegen der Reload
    // statt den veränderten Warenkorb, Zubehör und Einbauartikel ranzuholen
    if (gid('bigCart')) { return; }
    if (window.location.hostname.toLowerCase().indexOf('computerhandlung') == -1) { return; } // nur ch

    addEvent(document.body, 'click', showAddArtikelPopup);
}

////////////////////////////////////////////////////////////////////////////////
function showAddArtikelPopup(e) {
    var el = e.target;
    var artikelnummer;

    while(el && !artikelnummer) {
	if( el.tagName                      &&
            el.tagName.toUpperCase() == 'A' &&
	    el.href 			    &&
	    el.href.match(/addToBasket=(\d+)(?:\D|$)/i) )
	{
	    artikelnummer = RegExp.$1;
	} else {
	    el = el.parentNode;
	}
    }
    if(!artikelnummer) { return; }
    var initialArticles = getInitialArticles() || [artikelnummer];

    // ersma alle vorher schon geöffnetes Popup wieder weg machen
    if( articleAddedPopup ) { articleAddedPopup.close(); }

    articleAddedPopup = new ServerPopup(
        'base::Shop::HTML::Cart->addArtikel',
        {
            articlesForAccesories   : initialArticles,
            articlesToAdd           : [artikelnummer]
        },
        {
            onopen  : function () { updateCart(); initAddMultipleArticlesLink(); },
            onclose : function () { articleAddedPopup = null; },
            onerror : function () { window.location.replace(el.href); },
            e       : e
        }
    );
    e.preventDefault(); // wie return false;
}

////////////////////////////////////////////////////////////////////////////////
// Markierte Artikel in den Warenkorb legen - Link
// funktioniert nur mit JS, da ja nur aus dem Serverpopup aufgerufen
// und da muss JS an sein, sonst sieht man das garni
function initAddMultipleArticlesLink () {
    addEvent(articleAddedPopup, 'click', function (e) {
        if (!e.target.href || !e.target.href.match(/#addMultipleArticles$/) ) { return; }
        sendMultipleArticlesToCart(e);
    });
}

////////////////////////////////////////////////////////////////////////////////
//
function sendMultipleArticlesToCart(e) {
    var chosenArticles = getChosenAccessories(articleAddedPopup);

    if( !chosenArticles.length ) {
        alert('Es sind keine Artikel markiert.');
        return;
    }
    var initialArticles = getInitialArticles() || chosenArticles;

    // ersma alle vorher schon geöffnetes Popup wieder weg machen
    if( articleAddedPopup ) { articleAddedPopup.close(); }

    articleAddedPopup = new ServerPopup(
        'base::Shop::HTML::Cart->addArtikel',
        {
            articlesForAccesories   : initialArticles,
            articlesToAdd           : chosenArticles
        },
        {
            onopen  : function () { updateCart(); initAddMultipleArticlesLink(); },
            onclose : function () { articleAddedPopup = null; },
            onerror : function () { articleAddedPopup.close(); alert('Es ist ein Fehler aufgetreten. Die ausgewählten Artikel konnten dem Warenkorb nicht hinzugefügt werden.'); },
            e       : e
        }
    );

    e.preventDefault();
}

////////////////////////////////////////////////////////////////////////////////
// die angehakten Artikel ranholen
function getChosenAccessories(el) {
    var inputs = el.getElementsByTagName('input');
    var chosenArticles = [];
    // foreach
    for(var input, i = 0; input = inputs[i]; i++) {
        if(input.type && input.type == 'checkbox' && input.checked) {
            chosenArticles.push(input.value);
        }
    }
    return chosenArticles;
}

////////////////////////////////////////////////////////////////////////////////
// das Zubehoer sollte ja immer fuer den zuerst gewaehlten artikel angezeigt werden
function getInitialArticles() {
    if (!articleAddedPopup) { return; }
    var boldtags = articleAddedPopup.getElementsByTagName('b');
    // foreach
    for(var b, i = 0; b = boldtags[i]; i++) {
        if (b.getAttribute('data-initial_articles')) {
            return new ServerObject().fromJSON(b.getAttribute('data-initial_articles'));
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// fügt den Artikel noch visuell in den Warenkorb ein
function updateCart() {
    var cart, template;
    if      ( cart = gid('warenkorb_mainpage') ) { template = 'boxes_warenkorb.tpl' }
    else if ( cart = gid('warenkorb') )          { template = 'bestellung/boxes_bestellung_warenkorb.tpl' }
    //else if ( cart = gid('bigCart') )            { template = 'boxes_cart.tpl'; }
    else    { return; }

    new ServerObject({
        async   : true,
        ondata  : function (data) {
            var frag = document.createDocumentFragment();
            var placeholder = document.createElement('div');
            placeholder.innerHTML = data; //render innerHTML data
            var el;
            while( el = placeholder.firstChild ) { frag.appendChild(el); }
            cart.parentNode.insertBefore( frag.cloneNode(true), cart );
            cart.parentNode.removeChild(cart);
            initResizeCart();
        },
        // Eiskalt ma garnix machen, da stimmt eben die Anzeige einen Request
        // lang nich, beim klick auf den nächsten Link stimmts dann wieder
        onerror : function () {}
    }).Method('base::Shop::HTML::Cart->getCart', template);
}

////////////////////////////////////////////////////////////////////////////////
// schließt das popup oder geht zur URL
// für die 3 Knöpfe unten
function closeOrGotoUrl(url, button) {
    if (!url.match(/^http/) && !url.match(/^\//) ) { url = '/' + url; }
    if (window.location.pathname != url || !button) {
        window.location.href = url;
        return;
    }

    var popup;
    if(popup = getContainingPopup(button)) { popup.close(); }
}


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// bindet einen pager ein, der in der Zubehörbox mehr Zubehör anzeigt
addEvent(window, 'load', initAccessoryPager);
var pager_cache     = [];
var current_page    = 0;
var query_pending   = 0;
var pager, back, next, accessories; // DOM nodes
var current_article;

function initAccessoryPager() {
    pager       = gid('accessory_pager');
    back        = gid('accessory_back');
    next        = gid('accessory_next');
    accessories = gid('accessories');
    if( !pager || !back || !next || !accessories ) { return; }

    var has_other_accessories = parseInt(pager.getAttribute('data-has_other_accessories'), 10) ;
    if( !has_other_accessories ) { return; }

    pager.style.display     = 'block';
    back.style.visibility   = 'hidden';
    current_article         = pager.getAttribute('data-artikelnummer');
    if( !isIE() ) { accessories.style.minHeight = accessories.offsetHeight + 'px'; }

    addEvent(back, 'click', function (e) {
        if( query_pending ) { return; }
        current_page--;
        fetchPage();
        e.preventDefault();
    });

    addEvent( next, 'click', function (e) {
        if( query_pending ) { return; }
        current_page++;
        fetchPage();
        e.preventDefault();
    });
}

////////////////////////////////////////////////////////////////////////////////
// holt sich weiteres Zubehör vom Server oder aus dem JS-Cache
function fetchPage() {
    if( current_page < 0 ) { current_page = 0; }

    if( pager_cache[current_page] ) {
        showPage( current_page );
        return;
    }

    query_pending = 1;
    new ServerObject({
        async   : true,
        ondata  : cachePage
    }).Method('base::Shop::HTML::Artikeldetails->pageAccessories', current_article, current_page);

}

////////////////////////////////////////////////////////////////////////////////
// konvertiert das erhaltene HTML in documentFragment und schmeißts in den Cache
function cachePage(data) {
    query_pending = 0;
    var frag = document.createDocumentFragment();
    var placeholder = document.createElement('div');
    placeholder.innerHTML = data.box_html; //render innerHTML data
    var el;
    while( el = placeholder.firstChild ) { frag.appendChild(el); }
    pager_cache[current_page] = {
        dom_fragment    : frag,
        has_next_page   : data.has_next_page
    };

    showPage( current_page );
}

////////////////////////////////////////////////////////////////////////////////
// zeigt das abgeholte Zubehör an
function showPage(pageNumber) {
    var el;
    while( el = accessories.firstChild ) { accessories.removeChild(el) };
    accessories.appendChild( pager_cache[pageNumber].dom_fragment.cloneNode( true ) );

    if( current_page == 0 ) {
        back.style.visibility = 'hidden';
    } else {
        if( back.style.visibility == 'hidden' ) { back.style.visibility = 'visible'; }
    }

    if( !pager_cache[pageNumber].has_next_page ) {
        next.style.visibility = 'hidden';
    } else {
        if( next.style.visibility == 'hidden' ) { next.style.visibility = 'visible'; }
    }
}


////////////////////////////////////////////////////////////////////////////////
// Fügt der URL eine sessionID an
// macht den Trenner (?& ) automatisch richtig
// ersetzt schon vorhandene Sessionid mit neuer sessionid
// falls keine session_id angegeben, nimmts die globale variable sessionid(=> wrapper_html_head.tpl)
function addSessionID(url, session_id) {
    try {
        session_id = session_id || window.sessionid;
    }
    catch (e) {}

    // sessionid schon vorhanden
    if (url.match(/session-id=([0-9A-F])/)) {
        if (!RegExp.$1)             { throw new Exception('URL contains SessionID, but the SessionID is invalid.'); }
        if (RegExp.$1.length != 32) { throw new Exception('URL contains SessionID, but the SessionID has wrong length. (' + RegExp.$1.length + ' != 32)' ); }
        if (RegExp.$1 == sessionid) { return; }
        url.replace(RegExp.$1, session_id);
        return;
    }

    var divider = '?';
    if      (url.match(/[&?]$/))    { divider = ''; } // ? oder & schon am ende der url
    else if (url.indexOf('?') > -1) { divider = '&';} // url enthaelt schon ?

    return url + divider + 'session-id=' + session_id;
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
addEvent(window, 'load', initAllFilters);

////////////////////////////////////////////////////////////////////////////////
// auf Rubrikseiten, wo Filter angezeigt werden, kann es vorkommen, dass zuviele
// Filterwerte angezeigt werden. Da wird ein "Alle Anzeigen" link erstellt und
// das Filterwerte umgebende Element auf overflow hidden gestellt. Klickt man
// auf den Link, werden alle Filterwerte angezeigt.
function initAllFilters() {
    var filterbox = document.getElementById('filterbox');
    if (!filterbox) { return; }
    var filter_value_boxes = document.getElementsByClassName('filtervalues_js', filterbox)
    if (!filter_value_boxes.length) { return; }

    // foreach
    for (var filter_value_box, i = 0; filter_value_box = filter_value_boxes[i]; i++) {
        var filters = filter_value_box.getElementsByTagName('input'); // sind alle checkboxes
        if (filters.length < 7) { continue; }

        var show_all_link       = document.createElement('a');
        show_all_link.href      = 'javascript:void(0);';
        show_all_link.className = 'show_all_link';
        show_all_link.appendChild(document.createTextNode('Filterwerte verstecken'));
        show_all_link.div_to_toggle = filter_value_box;
        addEvent(show_all_link, 'click', toggle_filter_values);

        //filter_value_box.parentNode.appendChild(document.createElement('br'));
        filter_value_box.parentNode.appendChild(show_all_link);
        filter_value_box.initial_height = filter_value_box.offsetHeight;
        filter_value_box.is_extended    = 1;

        // foreach
        var dont_collapse = 0;
        for(var filter, j = 0; filter = filters[j]; j++) {
            if (!filter.checked) { continue; }
            dont_collapse = 1;
            break;
        }
        if (dont_collapse) { continue; }

        show_all_link.close = toggle_filter_values;
        show_all_link.close();
    }
}

////////////////////////////////////////////////////////////////////////////////
// blendet alle Filterwerte ein (aus)
function toggle_filter_values() {
    var div_to_toggle = this.div_to_toggle;
    var link = this;
    var transition = {};
    var min_height = isIE() ? 32 : 28;
    if (div_to_toggle.is_extended) {
        transition.now          = div_to_toggle.initial_height;
        transition.end          = min_height;
        transition.next_step    = function () { this.now -= 15; };
        transition.done         = function () { return this.now <= this.end; };
        transition.set_link_caption = function () {
            link.removeChild(link.firstChild);
            link.appendChild(document.createTextNode('Alle anzeigen'));
        };
    } else {
        transition.now          = min_height;
        transition.end          = div_to_toggle.initial_height;
        transition.next_step    = function () { this.now += 15; };
        transition.done         = function () { return this.now >= this.end; };
        transition.set_link_caption = function () {
            link.removeChild(link.firstChild);
            link.appendChild(document.createTextNode('Filterwerte verstecken'));
        };
    }

    div_to_toggle.is_extended = !div_to_toggle.is_extended;

    var filter_interval = setInterval(function () {
        transition.next_step();
        if (transition.done()) {
            clearInterval(filter_interval);
            transition.set_link_caption();
            transition.now = transition.end;
        }
        div_to_toggle.style.height = transition.now + 'px';
    }, 25);

    return false;
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// scrolls the similar-articles-box (=> Artikeldetails) more smoothly
addEvent(window, 'load', initSmoothArticleScroll)

////////////////////////////////////////////////////////////////////////////////
function initSmoothArticleScroll() {
    var scrollerboxes = document.getElementsByClassName('scrollerbox');
    if (!scrollerboxes.length) { return; }

    // foreach
    for(var scrollbox, i = 0; scrollbox = scrollerboxes[i]; i++) {
        addEvent(scrollbox, 'click', scrollArticleSmoothly);
        // den ausschnitt mit dem artikel und dem scrollbalken finden + merken
        var scrollbarboxes = document.getElementsByClassName('right_column_content', scrollbox);
        if (!scrollbarboxes.length) { return; }
        scrollbox.scrollbarbox = scrollbarboxes[0];
        // erste zeile markieren
        var lis = scrollbox.getElementsByTagName('li');
        addCSSclass(lis[0], 'show_indicator');
        scrollbox.scrollbarbox._previously_selected = lis[0];
        scrollbox.scrollTop = 0;
    }
}

////////////////////////////////////////////////////////////////////////////////
function scrollArticleSmoothly(e) {
    if (e.target.getAttribute('myType') != 'scroller') { return; }

    e.preventDefault();
    e.stopPropagation();

    var scrollbox       = this.scrollbarbox;
    var endPosition     = getDestinationScrollTop(e.target);
    var startPosition   = scrollbox.scrollTop;
    var direction       = startPosition > endPosition ? -1 : 1 ;
    var stepWidth       = 20;
    var line            = e.target.parentNode;
    removeCSSclass(scrollbox._previously_selected, 'show_indicator');
    scrollbox._previously_selected = line;
    addCSSclass(line, 'show_indicator');

    var cnt = 1;
    clearInterval(scrollbox.scrollInterval);
    scrollbox.scrollInterval = setInterval(function () {
            startPosition += stepWidth * direction;
            if (startPosition < 0) {
                scrollbox.scrollTop = 0;
                clearInterval(scrollbox.scrollInterval);
            } else if (startPosition >= scrollbox.scrollHeight + scrollbox.offsetHeight) {
                scrollbox.scrollTop = scrollbox.offsetHeight - scrollbox.scrollHeight;
                clearInterval(scrollbox.scrollInterval);
            } else if (startPosition * direction >= endPosition * direction) {
                scrollbox.scrollTop = endPosition;
                clearInterval(scrollbox.scrollInterval);
            } else {
                scrollbox.scrollTop = startPosition;
            }
        },
        25
    );
}

////////////////////////////////////////////////////////////////////////////////
function getDestinationScrollTop(el) {
    var scrollToAnchor = el.href;
    if (!scrollToAnchor) { return 0; }
    if (!scrollToAnchor.match(/#([\w_]+)$/)) { return; }
    scrollToAnchor = RegExp.$1;
    var anchors = document.getElementsByName(scrollToAnchor);
    if (!anchors.length) { return 0; }
    if (!isOpera()) { return anchors[0].offsetTop; }

    // opera has no offsetTop on the anchor, but on the next div
    var foundEl = anchors[0];
    while(foundEl && foundEl.tagName != 'DIV') {
        foundEl = foundEl.nextSibling;
    }
    return foundEl.offsetTop;
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// toggles the last-seen-articles-box small/big
addEvent(window, 'load', initToggleLastSeenArticles)

////////////////////////////////////////////////////////////////////////////////
function initToggleLastSeenArticles() {
    var last_seen_articles = document.getElementById('last_articles');
    if (!last_seen_articles) { return; }
    addEvent(last_seen_articles, 'click', toggleLastSeenArticles);
    if (!getValueFromCookie('last_seen_article_state')) { return; }

    gid('last_articles_big').className = '';
    gid('last_articles_small').className = '';
    gid(getValueFromCookie('last_seen_article_state')).className = 'hidden';
}

////////////////////////////////////////////////////////////////////////////////
function toggleLastSeenArticles(e) {
    if (!e.target.getAttribute) { return; }
    if (e.target.getAttribute('alt') != 'verkleinern' && e.target.getAttribute('alt') != 'vergrößern' ) { return; }

    var hide, show;
    if (e.target.getAttribute('alt') == 'verkleinern') {
        hide = 'last_articles_big';
        show = 'last_articles_small';
    } else {
        hide = 'last_articles_small';
        show = 'last_articles_big';
    }

    document.cookie     = 'last_seen_article_state=' + hide;
    gid(hide).className = 'hidden';
    gid(show).className = '';
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// TinteToner.pm (choose_manufacturer.htm/matching_supply.htm)
addEvent(window, 'load', function () {
    var druckerhersteller_container = gid('druckerhersteller_js');
    if (!druckerhersteller_container) { return; }
    var druckermodelle_container    = gid('druckermodelle_js');
    if (!druckermodelle_container) { return; }

    var el;
    if (el = gid('js_hide')) { el.style.display = 'none'; }
    if (el = gid('js_show')) { el.style.display = 'block'; }

    addCSSclass(druckerhersteller_container, 'waiting');
    addCSSclass(druckermodelle_container,    'waiting');

    modellFilterbox     = new Filterbox({caption: 'Bitte geben Sie hier ihr Druckermodell ein'});
    herstellerFilterbox = new Filterbox({caption: 'Bitte geben Sie hier den Hersteller ein'});

    addPrinterButton    = document.createElement('button');
    addPrinterButton.appendChild(document.createTextNode('den ausgewählten Drucker meinen Druckern hinzufügen'));
    addEvent(addPrinterButton, 'click', sendPrinter);
    addEvent(modellFilterbox.filtervaluebox, 'dblclick', sendPrinter);
    addEvent(modellFilterbox.filtervaluebox, 'keypress', function (e) {
        if (e.keyCode == vbKeyReturn) { sendPrinter(); }
    });

    window._printer_cache = {};
    addEvent(herstellerFilterbox.filtervaluebox, 'change', function (e) {
        modellFilterbox.showBusy();
        var selectfield = e.target;
        var selectedId = selectfield.value;

        if (window._printer_cache[selectedId]) {
            setTimeout(function () { updateModels(window._printer_cache[selectedId]) }, 1);
            return;
        }

        new ServerObject({
            async   : true,
            onerror : function () {
                updateModels();
            },
            ondata  : function (models) {
                window._printer_cache[selectedId] = models;
                updateModels(models);
            }
        }).Method('base::Shop::HTML::TinteToner->get_models_by_id',selectedId);
    });

    // die Druckerhersteller aus der HTML-Seite in die Liste einhängen
    setTimeout(function () {
        var hersteller = gid('druckerhersteller').getElementsByTagName('a');

        var options = [];
        for(var a, i = 0; a = hersteller[i]; i++) {
            if (!a.getAttribute('herstellerid')) { continue; }
            options.push({
                caption:    a.innerText || a.textContent,
                value:      a.getAttribute('herstellerid')
            });
        }
        herstellerFilterbox.addOptions(options);

        herstellerFilterbox.appendTo(druckerhersteller_container);
        removeCSSclass(druckerhersteller_container, 'waiting');

        modellFilterbox.appendTo(druckermodelle_container);
        removeCSSclass(druckermodelle_container, 'waiting');

        druckermodelle_container.appendChild(addPrinterButton);
    }, 10);
});

////////////////////////////////////////////////////////////////////////////////
function updateModels(models) {
    modellFilterbox.deleteAllOptions();
    if (models && models.length) { modellFilterbox.addOptions(models); }
    modellFilterbox.hideBusy();
}

////////////////////////////////////////////////////////////////////////////////
function sendPrinter() {
    var selectedmodelid = modellFilterbox.filtervaluebox.value;
    if (!selectedmodelid) {
        alert('Sie haben noch keinen Drucker markiert. Bitte wählen Sie ihren Drucker aus der Druckermodellliste.');
        return;
    }

    new ServerObject({
        async   : true,
        onerror : function () {},
        ondata  : function (data) {
            if (data.popup) {
                // Popup machen mit form drin, submit von der form unterdrücken
                // und per Serverobject submitten
                var popup = new ServerPopup(null, null, {data: data.popup});
                var edit_form = popup.getElementsByTagName('form')[0];
                addEvent(edit_form, 'submit', function (e) {
                    e.preventDefault();
                    e.stopPropagation();
                    var params = {};
                    // foreach
                    for(var form_field, i = 0; form_field = edit_form.elements[i]; i++) {
                        params[form_field.name] = form_field.value;
                    }
                    new ServerObject({
                        async       : true,
                        flat_params : true,
                        onerror     : function () {},
                        ondata      : function (data) {
                            if (!data) { return; }
                            var my_printers_box = gid('js_my_printers');
                            my_printers_box.innerHTML = data;
                            var tab_interfaces = document.getElementsByClassName('index_list', my_printers_box);
                            if (!tab_interfaces.length) { return; }
                            // foreach
                            for(var tab_i, i = 0; tab_i = tab_interfaces[i]; i++) {
                                new TabsInterface(tab_i);
                            }
                        }
                    }).Method('base::Shop::HTML::TinteToner->handle_edit_printer_and_get_my_printers', params);
                    popup.close();
                });
            }
            if (data.my_printers) {
                // "Meine Drucker" - Box aktualisieren + neu initialisieren
                var my_printers_box = gid('js_my_printers');
                my_printers_box.innerHTML = data.my_printers;
                var tab_interfaces = document.getElementsByClassName('index_list', my_printers_box);
                if (!tab_interfaces.length) { return; }
                // foreach
                for(var tab_i, i = 0; tab_i = tab_interfaces[i]; i++) {
                    new TabsInterface(tab_i);
                }
            }
        }
    }).Method('base::Shop::HTML::TinteToner->add_model_by_id', selectedmodelid);
}

////////////////////////////////////////////////////////////////////////////////
// Tintetoner.pm - passendes Druckerzubehör bestellen
//addEvent(window, 'load', function () {
//    var toggleQuickOrderform = gid('toggleQuickOrderform');
//    if (!toggleQuickOrderform) { return; }
//
//    var toggles = document.getElementsByClassName('sectionheading', toggleQuickOrderform);
//    if (!toggles.length) { return; }
//    for(var toggleMaster, i = 0; toggleMaster = toggles[i]; i++) {
//        var toggleSlave = toggleMaster;
//        while (toggleSlave) {
//            if (!toggleSlave.tagName) { return; }
//            if (toggleSlave.tagName.toUpperCase() == 'DIV') { break; }
//            toggleSlave = toggleSlave.nextSibling;
//        }
//        if (!toggleSlave) { continue; }
//        new Toggle(toggleMaster, toggleSlave, { hideOnStart: toggleMaster.getAttribute('myType') > 1 });
//    }
//});

////////////////////////////////////////////////////////////////////////////////
// TinteToner.pm /edit_stock.htm Bestandzubehör hinzufügen
addEvent(window, 'load', function () {
    var hersteller_container = gid('artikelhersteller_js');
    if (!hersteller_container) { return; }
    var artikel_container = gid('artikelmodelle_js');
    if (!artikel_container) { return; }

    var jsless_hersteller = gid('js_hide');
    jsless_hersteller.style.display = 'none';
    gid('js_show').style.display = 'block';

    herstellerFilterbox = new Filterbox({caption: 'Bitte geben Sie hier den Hersteller ein.', precaption: 'Hersteller:'});
    artikelFilterbox    = new Filterbox({caption: 'Bitte geben Sie hier die Artikelbezeichnung ein.', precaption: 'Bezeichnung:'});

    var links = jsless_hersteller.getElementsByTagName('a');
    var options = [];
    for(var a, i = 0; a = links[i]; i++) {
        if (!a.getAttribute('herstellerid')) { continue; }
        options.push({
            caption:    a.innerText || a.textContent,
            value:      a.getAttribute('herstellerid')
        });
    }
    herstellerFilterbox.addOptions(options);

    window._supply_cache = [];
    var send_hersteller,
        display                     = {
            tinte_und_papier:   gid('tinte_toner_beides'),
            papier:             gid('tinte_toner_papier'),
            tinte:              gid('tinte_toner_tinte')
        },
        tinte_toner_display_option  = getValueFromCookie('tinte_toner_display_option');

    addEvent(herstellerFilterbox.filtervaluebox, 'change', send_hersteller = function () {
        var selectfield = herstellerFilterbox.filtervaluebox,
            selectedId  = selectfield.value,
            modellId    = hersteller_container.getAttribute('specific_model'),
            constraint;

        if (!selectedId) { return; }
        artikelFilterbox.showBusy();

        if      (display.tinte_und_papier.checked)  { constraint = display.tinte_und_papier.value; }
        else if (display.papier.checked)            { constraint = display.papier.value;    }
        else if (display.tinte.checked)             { constraint = display.tinte.value;     }

        window._supply_cache[selectedId] = window._supply_cache[selectedId] || [];

        if (window._supply_cache[selectedId][constraint]) {
            setTimeout(function () { updateSupply(window._supply_cache[selectedId][constraint]) }, 1);
            return;
        }

        new ServerObject({
            async   : true,
            onerror : function () {
                updateModels();
            },
            ondata  : function (models) {
                window._supply_cache[selectedId][constraint] = models;
                updateSupply(models);
            }
        }).Method('base::Shop::HTML::TinteToner->get_supply_by_manufacturerid', selectedId, modellId, constraint);
    });

    // foreach
    for(key in display) {
        addEvent(display[key], 'click', (function () {
            send_hersteller();
            document.cookie = "tinte_toner_display_option=" + this;
        }).bind(key));
    }
    if (tinte_toner_display_option) {
        display[tinte_toner_display_option].checked = 'checked';
    } else {
        display.tinte_und_papier.checked = 'checked';
    }

    addSupplyButton = document.createElement('button');
    addSupplyButton.appendChild(document.createTextNode('den ausgewählten Artikel meinem Bestand hinzufügen'));
    addEvent(addSupplyButton, 'click', sendSupply);
    addEvent(artikelFilterbox.filtervaluebox, 'dblclick', sendSupply);
    addEvent(artikelFilterbox.filtervaluebox, 'keypress', function (e) {
        if (e.keyCode == vbKeyReturn) { sendSupply(); }
    });

    herstellerFilterbox.appendTo(hersteller_container);
    artikelFilterbox.appendTo(artikel_container);
    artikel_container.appendChild(addSupplyButton);
})

////////////////////////////////////////////////////////////////////////////////
function sendSupply() {
    var selectedsupplyid = artikelFilterbox.filtervaluebox.value;
    if (!selectedsupplyid) {
        alert('Sie haben noch keinen Artikel markiert. Bitte wählen Sie ihren Artikel aus der Artikelliste.');
        return;
    }
    var href = window.location.href.replace(/[?&]add_to_stock=\d+/, '');
    var divider = href.indexOf('?') > -1 ? '&' : '?';
    window.location.href = href + divider + 'add_to_stock=' + selectedsupplyid;
}

////////////////////////////////////////////////////////////////////////////////
function updateSupply(supply) {
    artikelFilterbox.deleteAllOptions();
    if (supply && supply.length) { artikelFilterbox.addOptions(supply); }
    artikelFilterbox.hideBusy();
}

////////////////////////////////////////////////////////////////////////////////
// Drucker löschen Knopf
addEvent(window, 'load', function () {
    var printer_container = document.getElementById('my_printers_js');
    if (printer_container) {
        addEvent(printer_container, 'click', function (e) {
            if (!e.target) { return; }
            if (!e.target.href) { return; }
            if (e.target.href.indexOf('deletePrinter') == -1) { return; }
            if (e.target.href.indexOf('#') > -1) { return; } // Anker auf der Seite

            if (!confirm('Wollen Sie den Drucker wirklich löschen?')) {
                e.preventDefault();
            }
        });
    }

    var storage = document.getElementById('edit_storage');
    if (!storage) { return; }
    addEvent(storage, 'click', function (e) {
        if (!e.target) { return; }
        if (!e.target.name) { return; }
        if (e.target.name.indexOf('delete') == -1) { return; }

        if (!confirm('Wollen Sie den Lagerort wirklich löschen?')) {
            e.preventDefault();
        }
    });
});

////////////////////////////////////////////////////////////////////////////////
// Livesuche
addEvent(window, 'load', function () {
    if (window.location.href.toLowerCase().indexOf('tempel') > -1) { return; }
    var searchField = gid('searchField');
    if (searchField) {
        new SearchSuggestFieldCH(searchField, {
            method: 'base::Shop::HTML::artikelsuche->getSuggestions',
            onSelect: function (e, row) {
                e.preventDefault();
                e.stopPropagation();
                window.location.href = row.getAttribute('link');
            }
        });
        return;
    }
    searchField = gid('normal_search');
    if (!searchField) { return; }
    new SearchSuggestFieldPE(searchField, {
        method: 'base::Shop::HTML::artikelsuche->getSuggestions',
        onSelect: function (e, row) {
            e.preventDefault();
            e.stopPropagation();
            window.location.href = row.getAttribute('link');
        }
    })
});

////////////////////////////////////////////////////////////////////////////////
// IE8 kann kein wbr, per CSS kommt man auch nicht ran, also per JS
if (isIE8()) {
    addEvent(window, 'load', function () {
        var els = document.getElementsByTagName('wbr');
        var zwsp = document.createElement('span');
        zwsp.innerHTML = "&zwsp;";
        // foreach
        for(var el, i = 0; el = els[i]; i++) {
            el.parentNode.insertBefore(zwsp.cloneNode(true), el);
        }
    })
}