﻿function init()
{
    valignButtonsInTeaser.set();
    if(document.getElementById('transparentLayer')) { 
        transparentLayer.open();
    }
    if(document.getElementById('popupLayer') || document.getElementById('formWerbenNewsletter24')) {
        popupLayerShadowForIE6.set();
        popupLayer.open();
    }
    if(document.getElementById('ibeHome')) { 
        ibeHomeShadowForIE6.set();    
    }
    //initIBE ();
}

var windowOpen = {
    open: function (url, name, width, height) {
        f = window.open(url, name, 'width='+width+',height='+height+',scrollbars=yes,status=yes,toolbar=no,location=no,directories=no,resizable=yes,menubar=yes');
        setTimeout('f.focus()', 200);
    }
}


/**********************************************************
Ist ein trasparenter Layer, der sich über die Seite legt.
**********************************************************/
var transparentLayer = {
    
    pageWidth: false,
    pageheight: false,
    
    init: function () {    
        scrollWidth = document.getElementsByTagName('body')[0].offsetWidth;
        scrollHeight = document.getElementsByTagName('body')[0].offsetHeight;
        documentWidth = document.getElementsByTagName('body')[0].scrollLeft;
        documentHeight = document.getElementsByTagName('body')[0].scrollTop;
        if(window.innerWidth) {
            windowWidth =  window.innerWidth;
            windowHeight = window.innerHeight;
        }
        else {
            windowWidth =  document.body.clientWidth;
            windowHeight = document.body.clientHeight;
        }
        if((documentWidth - scrollWidth) > windowWidth) {
            this.pageWidth = documentWidth - scrollWidth;
        }
        else {
            this.pageWidth = windowWidth;
        }
        if((documentHeight - scrollHeight) > windowHeight) {
            this.pageHeight = documentHeight - scrollHeight;
        }
        else {
            this.pageHeight = windowHeight;
        }        
        //this.pageWidth = '100%'; //document.getElementsByTagName('body')[0].offsetWidth - sL;
        //this.pageHeight = document.getElementsByTagName('body')[0].offsetHeight - sT;
    },
    
    open: function () {
        if(document.getElementById('transparentLayer')) {
            this.init();
            //this.debug();
            document.getElementById('transparentLayer').style.width = '100%'; //this.pageWidth + 'px'; 
            document.getElementById('transparentLayer').style.height = this.pageHeight + 'px';
            document.getElementById('transparentLayer').style.zIndex = '19999';
            document.getElementById('transparentLayer').style.visibility = 'visible';
        }
    },
    
    close: function () {
        if(document.getElementById('transparentLayer')) {
            document.getElementById('transparentLayer').style.visibility = 'hidden';
        }
    },
    
    debug: function () {
        alert(this.pageWidth + " x " + this.pageHeight);
    }
};
/**********************************************************
Popuplayer
**********************************************************/
var popupLayer = {
    close: function () {
        if(document.getElementById('popupLayer')) {
            document.getElementById('popupLayer').style.visibility = 'hidden';
        }
        else if(document.getElementById('formWerbenNewsletter24')) {
            document.getElementById('formWerbenNewsletter24').style.visibility = 'hidden';
        }
        transparentLayer.close();
    },
    open: function () {
        if(document.getElementById('popupLayer')) {
            document.getElementById('popupLayer').style.zIndex = '20000';
            document.getElementById('popupLayer').style.visibility = 'visible';
        }
        else if(document.getElementById('formWerbenNewsletter24')) {
            document.getElementById('formWerbenNewsletter24').style.zIndex = '20000';
            document.getElementById('formWerbenNewsletter24').style.visibility = 'visible';
        }
    }    
    
}
/*******************************************************
Popuplayer Spezialanpassung für den IE6
Schatten werden für den IE6 ausgetauscht bzw. Filter gesetzt.
********************************************************/
var popupLayerShadowForIE6 = {
    set: function () {    
        if (document.all && !window.opera) {        
            preffix = '';
            if(document.getElementById('formWerbenNewsletter24')) {
                preffix = 'werben_';    
            }
            var popUpLayer = 
            {    
                'top' : { 'obj' : document.getElementById('PopupLayerTop') , 'src' : 'images/structure/background/bg_' + preffix + 'popupLayer_top.png' },
                'content' : { 'obj' : document.getElementById('PopupLayerVertical') , 'src' : 'images/structure/background/bg_' + preffix + 'popupLayer_vertical.png' },
                'bottom' : { 'obj' : document.getElementById('PopupLayerBottom') , 'src' : 'images/structure/background/bg_' + preffix + 'popupLayer_bottom.png' }
            };
            
            popUpLayer['top']['obj'].style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' + popUpLayer['top']['src'] + ', sizingMethod="image")';
            popUpLayer['top']['obj'].style.backgroundColor = 'transparent';
            
            popUpLayer['content']['obj'].style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' + popUpLayer['content']['src'] + ', sizingMethod="scale")';
            popUpLayer['content']['obj'].style.backgroundColor = 'transparent';
            
            popUpLayer['bottom']['obj'].style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' + popUpLayer['bottom']['src'] + ', sizingMethod="image")';
            popUpLayer['bottom']['obj'].style.backgroundColor = 'transparent';
        }
    }
}
var ibeHomeShadowForIE6 = {
    set: function () {    
        if(!document.getElementById('ibeHome')) {
            return false;
        }        
        if (document.all && !window.opera) {        
            var ibeHome = 
            {    
                'top' : { 'obj' : document.getElementById('shadowTop') , 'src' : '/de/Images/bg_shadow_1_4_top.png' },
                'content' : { 'obj' : document.getElementById('shadowContent') , 'src' : '/de/Images/bg_shadow_1_4_content.png' },
                'bottom' : { 'obj' : document.getElementById('shadowBottom') , 'src' : '/de/Images/bg_shadow_1_4_bottom.png' }
            };
            ibeHome['top']['obj'].style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' + ibeHome['top']['src'] + ', sizingMethod="image")';
            ibeHome['top']['obj'].style.backgroundColor = 'transparent';
            
            ibeHome['content']['obj'].style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' + ibeHome['content']['src'] + ', sizingMethod="scale")';
            ibeHome['content']['obj'].style.backgroundColor = 'transparent';
            
            ibeHome['bottom']['obj'].style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' + ibeHome['bottom']['src'] + ', sizingMethod="image")';
            ibeHome['bottom']['obj'].style.backgroundColor = 'transparent';
        }
    }
}
/*******************************************************
Setzt Links und Buttons bei allen Teasern in einer Reihe
auf eine Linie.
********************************************************/
/*
Prototype ab Version 1.5
var valignButtonsInTeaser = {
    check: function (groupAlignButton) {
        return false;
    },
    
    set: function () {   
        $$('div.alignButton').each(function(obj) {
            // CSS-Eigenschaft für Link "position" aufheben
            $(obj).getElementsBySelector('.link').each(function(link) {
                $(link).setStyle({position: 'static'});
            });
            var dimensions = $(obj).getDimensions();
            $(obj).childElements().each(function(child) {
                $(child).setStyle({height: (dimensions.height + 15) + 'px'});
                // CSS-Eigenschaft für Link "position" setzen
                c = $(child).down('.link');
                if(c) {
                    c.setStyle({position: 'absolute'});
                }
            });
        });
    }   
}
*/

 var valignButtonsInTeaser = {
     /*
    check: function (groupAlignButton) {
        var divs = groupAlignButton.getElementsByTagName('div');
        for(var i= 0; i < divs.length; i++) {
            if(divs[i].className.indexOf('link')>-1 ) {
                return true;
            }
        }
        return false;
    },
    // Workaround
    setCSSPositionLink: function (groupAlignButton, cssPosition) {
        var divs = groupAlignButton.getElementsByTagName('div');
        for(var i= 0; i < divs.length; i++) {
            if(divs[i].className.indexOf('link')>-1 ) {
                divs[i].style.position = cssPosition;
            }
        }
    },
        */
    set: function () {
            
                $j('.alignButton').each(function (i) {
                        var minHt = 0;
                        $j(this).children('DIV').each(function (j) {
                                if( $j(this).height() > minHt ) {
                                    minHt = $j(this).height();
                                }                                                                        
                        });    
                        $j(this).children('DIV').not('.teaser14FlagTable').each(function (j) {
                                $j(this).height( minHt + 33 );                                                                
                        });    
                });
                
        /*
        myDivs = document.getElementsByTagName('div');
        myAlignGroups = new Array();
        for(var i=0; i < myDivs.length; i++) {
            if(myDivs[i].className.indexOf('alignButton')>-1 ) {
                if(this.check(myDivs[i])) {
                    this.setCSSPositionLink(myDivs[i], 'static');
                    var innerDivs = myDivs[i].getElementsByTagName('DIV'), useStructHeight = true, heights = new Array(), y;
                    for(y=0;y<innerDivs.length;++y){
                        if(innerDivs[y].className == 'teaser14FlagTable'){
                            useStructHeight = false;
                        }else{
                            heights[heights.length] = innerDivs[y].offsetHeight;
                        }
                    }
                    if(useStructHeight === true){
                        x = myDivs[i].offsetHeight;
                    }else{
                        x = heights.sort(function(a,b){
                                return a - b
                            })[heights.length-1];
                    }
                    this.setCSSPositionLink(myDivs[i], 'absolute');
                    var myAlignButtons = myDivs[i].getElementsByTagName('DIV');
                    for(j=0; j<myAlignButtons.length; j++) {
                        myAlignButtons[j].parentNode.style.height = x + 15 + 'px';
                    }
                }
            }
        }*/
    }
}
/**************************************************
Dynamisch aufklappbare Bereiche
**************************************************/
//var motion = false; 
//var decrease = .9;

var slideContainer = {
    init: function() {
        $j( '.slideContainer' ).each(function() {
            if( !parseInt( $j( this ).css('height') ) ) {
                $j( this ).css('height', 'auto').hide();
            }
        });
    }
} 
$j( slideContainer.init ); 

function slideInit (toggle, noBorder, hideLink, imageOpen, imageClose) {
        myImg = $j( toggle ).find( 'IMG' ).eq(0);
        if ( $j( toggle ).hasClass('open') ){
            $j( toggle ).parent().next('.slideContainer').slideUp('normal', function() {
                $j( toggle ).removeClass('open');
                if( myImg && myImg.attr('src') ) {
                    myImg.attr('src', myImg.attr('src').replace(/_minus/, "_plus") );    
                }
            });
        } else {
            $j( toggle ).parent().next('.slideContainer').slideDown('normal', function() {
                $j( toggle ).addClass('open');
                if( myImg && myImg.attr('src') ) {
                    myImg.attr('src', myImg.attr('src').replace(/_plus/, "_minus") );
                }
            });
        }
}

// findet alle sliderelemente (siehe "slideInit")
function preExecOpened () {    
    $j('.switchBar[rel="open"]').each(function (idx, element) {
        $j(element).find("h4")
                       .addClass("open")
                   .end()
                   .next()
                   .show();
    });   
} 


/*Funktion um in der Auswahlliste den ausgewaehlten fett zu machen */
function changeOption(auswahl) {
    for(var i=0;i<auswahl.length;i++) {
        if (auswahl[i].selected)
            auswahl[i].style.fontWeight = "bold";
        else
            auswahl[i].style.fontWeight = "normal";
    }
}
/************ Funktion fuer den Newsletter - vorbelegung des E-Mail Feldes ********/
function newsletter_email(auswahl,text) {
    if(auswahl.value == "") {
        auswahl.style.color ="#c1c1c1";
        auswahl.value = text;
    }
}    
function newsletter_email_clear(auswahl,text) {
    if(auswahl.value == text) {
        auswahl.style.color = "#000000";
        auswahl.value = "";
    }
}
/********* Funktion fuer das Pressekontakt Nachrichtenfeld *******/
function zaehlen() {
 var max = 501;
 anz = document.pressekontakt_form.Pressekontakt_Anliegen.value.length+1;
 document.pressekontakt_form.anzeige.value = max - anz;
 uebrig = max - anz;
 if(anz >= max){
  alert("Maximum erreicht !!!");
  }
  return uebrig;
 }
 
var px = 10;//mehr=schneller
var timer;
var merker;
function scrollDiv(val){
    clearTimeout(timer);
    d=document.getElementById('ScrollArea')
    y=d.scrollTop;
    if(val==1)y-=px;
    if(val==2)y+=px;
    if(y<=d.scrollHeight-d.offsetHeight+px&&y>=0-px){
        d.scrollTop=y;
        timer=setTimeout('scrollDiv('+val+')',50);
    }
    if(y<0||y>d.scrollHeight-d.offsetHeight){
        clearTimeout(timer);
    }
} 
 
 
/* FAQ Seite - Maximale Zeichen fuer Textfeld */
function zaehlenFAQ() {
  var max = 501;
  anz = document.faq.faq_ihre_anfrage.value.length+1;
  document.faq.anzeige.value = max - anz;
  uebrig = max - anz;
  if(anz >= max) {
    alert("Maximum erreicht !!!");
  }
  return uebrig;
}
 
/* Sprachumschaltung Header */
$j(document).ready(function(){
        $j("#language").change(function(event){
            if ($j(document).getUrl != ("flugundhotel.germanwings.com")){ 
                window.location = $j("#language").val();
            }
            else{
                window.location = ("http://www.germanwings.com/") + $j("#language").val();
            }
        });
    }); 

/*** MaxLengthTextArea *** Germanwings Edition ***/
function gw_maxLengthTextArea( textarea, keyEvent, maxLength )
{
  // still allow some special keys
  if ( ( keyEvent.keyCode >= 37 && keyEvent.keyCode <= 40 ) || // arrow keys
         keyEvent.keyCode == 8 || // backspace
         keyEvent.keyCode == 13 || // return key
         keyEvent.keyCode == 35 || // end key
         keyEvent.keyCode == 36 || // pos1 key
         keyEvent.keyCode == 46 ) // del key
  {
    return true;
  }
  //if ( textarea.value.length + 1 > maxLength )
    if ( $j( textarea ).attr( 'value' ).length + 1 > maxLength )
  {
    return false;
  }
  else
  {
    return true;
  }
}
function gw_updateCounter( textarea, counter, maxLength )
{
  //counter.update( maxLength - textarea.value.length ); 
    counter.text( maxLength - $j( textarea ).attr( 'value' ).length ) 
}

function popupSized(theURL, wname, width, height) {
  positionx = (screen.width/2)-(width/2)
  positiony = (screen.height/2)-(height/2)
  window.open(theURL, wname,"width="+ width +",height="+ height +",resizable=yes,status=no,scrollbars=yes,toolbar=no,menubar=no,left=" + positionx + ",top=" + positiony + ",screenX=" + positionx + ",screenY=" + positiony);
}

/* Slide fuer Unternehmensseite */
function slideInitUnternehmen(toggle, slider) {
    merker = toggle;
    if(!motion) {
        window['slideObj'] = document.getElementById(slider);
        slideObj.toggle = toggle;
        if(!slideObj.direc) slideObj.direc = 1;
        slideObj.speed = parseInt(slideObj.getElementsByTagName('DIV')[0].offsetHeight/4);
        slideUnternehmen();
    }
    return false;
}
function slideUnternehmen() {
    window.clearTimeout(motion);
    slideObj.speed *= decrease;
    ht = parseInt(slideObj.style.height);
    if (slideObj.direc > 0) {
        if(ht < (slideObj.getElementsByTagName('DIV')[0].offsetHeight)) {
            slideObj.style.height = ht + Math.ceil(slideObj.speed) + 'px';
        } else {
            slideObj.style.height = slideObj.getElementsByTagName('DIV')[0].offsetHeight + 'px';
            slideObj.toggle.className = 'open';
            merker.style.visibility = "hidden";
            slideObj.direc *= -1;
            motion = false; 
            return;
        }
    } else {
        if(ht > 0) {
            var myHt = ht - Math.ceil(slideObj.speed);
            if (myHt < 0) myHt = 0; 
            slideObj.style.height = myHt + 'px';
        } else {
            slideObj.style.height = "0px";
            slideObj.toggle.className = '';
            merker.style.visibility = "visible";            
            slideObj.direc *= -1;
            motion = false; 
            return;
        }     
    }
    motion = window.setTimeout('slideUnternehmen()', 40);
}
 

/** 
* functions to display images in page container on the fly
* added by Jörg Gutsche 2008-02-05 
* used by image_text_button_mouseover
*
*/
function mouseX(evt) {
    if (evt.pageX) return evt.pageX;
    else if (evt.clientX)
       return evt.clientX + (document.documentElement.scrollLeft ?
       document.documentElement.scrollLeft :
       document.body.scrollLeft);
    else return null;
}

function mouseY(evt) {
    if (evt.pageY) return evt.pageY;
    else if (evt.clientY)
       return evt.clientY + (document.documentElement.scrollTop ?
       document.documentElement.scrollTop :
       document.body.scrollTop);
    else return null;
}
/**
* @param e event
* @param id String image src
*/
function displayImage(e,id){
            var container = document.getElementById("Container");
             try {
                var list = container.getElementsByTagName("IMG")[0];
                container.removeChild(list);
            } catch (exception) {
            }
            var newChild = document.createElement("IMG");
            newChild.src = id;
    
            container.appendChild(newChild);
            container.style.top = mouseY(e) + "px";    
            container.style.left = mouseX(e) + "px"; 
            container.style.display = "block";
        }
// removes image nodes from Container 
function emptyContainer(){
            var theContainer = document.getElementById("Container");
            var list = theContainer.getElementsByTagName("IMG")[0];
            theContainer.removeChild(list);
            theContainer.style.display = "none";
            
 }
 
//--------------------------------------------------------------------------------
// Öffnet Fenster (popup) und plaziert dieses in der Bildschirmmitte
//--------------------------------------------------------------------------------
function openContentPopup(url, winName, w, h){
var parameter = 'width='+w+',height='+h+',left='+eval((screen.width-w)/2)+',top=50,scrollbars=yes,resizable=yes,location=no,menubar=no,toolbar=no';
    a = window.open(url,winName,parameter);
    a.focus();
    return false;
}

function openRatesTable(){
  
    var documentUrl = location.href;
    urlArray = new Array();
    urlArray = documentUrl.split("/");
    var langName;
    if (urlArray[3].length != 2)
    { langName = "en"; }
    else 
    { langName = urlArray[3]; }
    var inUrl = "/" + langName + "/faq_rates.htm";
  
    var winName = "ratestable";
    var width = 700;
    var height = 800;
  
    openContentPopup(inUrl,winName,width, height);
}


// ===================================================================
// Author: Matt Kruse <matt@mattkruse.com>
// WWW: http://www.mattkruse.com/
//
// NOTICE: You may use this code for any purpose, commercial or
// private, without any further permission from the author. You may
// remove this notice from your final code if you wish, however it is
// appreciated by the author if at least my web site address is kept.
//
// You may *NOT* re-distribute this code in any way except through its
// use. That means, you can include it in your product, or your web
// site, or any other form where the code is actually being used. You
// may not put the plain javascript up on your site for download or
// include it in your javascript libraries for download. 
// If you wish to share this code with others, please just point them
// to the URL instead.
// Please DO NOT link directly to my .js files from your site. Copy
// the files to your server and use them there. Thank you.
// ===================================================================
var MONTH_NAMES=new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');var DAY_NAMES=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat');
function LZ(x){return(x<0||x>9?"":"0")+x}
function isDate(val,format){var date=getDateFromFormat(val,format);if(date==0){return false;}return true;}
function compareDates(date1,dateformat1,date2,dateformat2){var d1=getDateFromFormat(date1,dateformat1);var d2=getDateFromFormat(date2,dateformat2);if(d1==0 || d2==0){return -1;}else if(d1 > d2){return 1;}return 0;}
function formatDate(date,format){format=format+"";var result="";var i_format=0;var c="";var token="";var y=date.getYear()+"";var M=date.getMonth()+1;var d=date.getDate();var E=date.getDay();var H=date.getHours();var m=date.getMinutes();var s=date.getSeconds();var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k;var value=new Object();if(y.length < 4){y=""+(y-0+1900);}value["y"]=""+y;value["yyyy"]=y;value["yy"]=y.substring(2,4);value["M"]=M;value["MM"]=LZ(M);value["MMM"]=MONTH_NAMES[M-1];value["NNN"]=MONTH_NAMES[M+11];value["d"]=d;value["dd"]=LZ(d);value["E"]=DAY_NAMES[E+7];value["EE"]=DAY_NAMES[E];value["H"]=H;value["HH"]=LZ(H);if(H==0){value["h"]=12;}else if(H>12){value["h"]=H-12;}else{value["h"]=H;}value["hh"]=LZ(value["h"]);if(H>11){value["K"]=H-12;}else{value["K"]=H;}value["k"]=H+1;value["KK"]=LZ(value["K"]);value["kk"]=LZ(value["k"]);if(H > 11){value["a"]="PM";}else{value["a"]="AM";}value["m"]=m;value["mm"]=LZ(m);value["s"]=s;value["ss"]=LZ(s);while(i_format < format.length){c=format.charAt(i_format);token="";while((format.charAt(i_format)==c) &&(i_format < format.length)){token += format.charAt(i_format++);}if(value[token] != null){result=result + value[token];}else{result=result + token;}}return result;}
function _isInteger(val){var digits="1234567890";for(var i=0;i < val.length;i++){if(digits.indexOf(val.charAt(i))==-1){return false;}}return true;}
function _getInt(str,i,minlength,maxlength){for(var x=maxlength;x>=minlength;x--){var token=str.substring(i,i+x);if(token.length < minlength){return null;}if(_isInteger(token)){return token;}}return null;}
function getDateFromFormat(val,format){val=val+"";format=format+"";var i_val=0;var i_format=0;var c="";var token="";var token2="";var x,y;var now=new Date();var year=now.getYear();var month=now.getMonth()+1;var date=1;var hh=now.getHours();var mm=now.getMinutes();var ss=now.getSeconds();var ampm="";while(i_format < format.length){c=format.charAt(i_format);token="";while((format.charAt(i_format)==c) &&(i_format < format.length)){token += format.charAt(i_format++);}if(token=="yyyy" || token=="yy" || token=="y"){if(token=="yyyy"){x=4;y=4;}if(token=="yy"){x=2;y=2;}if(token=="y"){x=2;y=4;}year=_getInt(val,i_val,x,y);if(year==null){return 0;}i_val += year.length;if(year.length==2){if(year > 70){year=1900+(year-0);}else{year=2000+(year-0);}}}else if(token=="MMM"||token=="NNN"){month=0;for(var i=0;i<MONTH_NAMES.length;i++){var month_name=MONTH_NAMES[i];if(val.substring(i_val,i_val+month_name.length).toLowerCase()==month_name.toLowerCase()){if(token=="MMM"||(token=="NNN"&&i>11)){month=i+1;if(month>12){month -= 12;}i_val += month_name.length;break;}}}if((month < 1)||(month>12)){return 0;}}else if(token=="EE"||token=="E"){for(var i=0;i<DAY_NAMES.length;i++){var day_name=DAY_NAMES[i];if(val.substring(i_val,i_val+day_name.length).toLowerCase()==day_name.toLowerCase()){i_val += day_name.length;break;}}}else if(token=="MM"||token=="M"){month=_getInt(val,i_val,token.length,2);if(month==null||(month<1)||(month>12)){return 0;}i_val+=month.length;}else if(token=="dd"||token=="d"){date=_getInt(val,i_val,token.length,2);if(date==null||(date<1)||(date>31)){return 0;}i_val+=date.length;}else if(token=="hh"||token=="h"){hh=_getInt(val,i_val,token.length,2);if(hh==null||(hh<1)||(hh>12)){return 0;}i_val+=hh.length;}else if(token=="HH"||token=="H"){hh=_getInt(val,i_val,token.length,2);if(hh==null||(hh<0)||(hh>23)){return 0;}i_val+=hh.length;}else if(token=="KK"||token=="K"){hh=_getInt(val,i_val,token.length,2);if(hh==null||(hh<0)||(hh>11)){return 0;}i_val+=hh.length;}else if(token=="kk"||token=="k"){hh=_getInt(val,i_val,token.length,2);if(hh==null||(hh<1)||(hh>24)){return 0;}i_val+=hh.length;hh--;}else if(token=="mm"||token=="m"){mm=_getInt(val,i_val,token.length,2);if(mm==null||(mm<0)||(mm>59)){return 0;}i_val+=mm.length;}else if(token=="ss"||token=="s"){ss=_getInt(val,i_val,token.length,2);if(ss==null||(ss<0)||(ss>59)){return 0;}i_val+=ss.length;}else if(token=="a"){if(val.substring(i_val,i_val+2).toLowerCase()=="am"){ampm="AM";}else if(val.substring(i_val,i_val+2).toLowerCase()=="pm"){ampm="PM";}else{return 0;}i_val+=2;}else{if(val.substring(i_val,i_val+token.length)!=token){return 0;}else{i_val+=token.length;}}}if(i_val != val.length){return 0;}if(month==2){if( ((year%4==0)&&(year%100 != 0) ) ||(year%400==0) ){if(date > 29){return 0;}}else{if(date > 28){return 0;}}}if((month==4)||(month==6)||(month==9)||(month==11)){if(date > 30){return 0;}}if(hh<12 && ampm=="PM"){hh=hh-0+12;}else if(hh>11 && ampm=="AM"){hh-=12;}var newdate=new Date(year,month-1,date,hh,mm,ss);return newdate.getTime();}
function parseDate(val){var preferEuro=(arguments.length==2)?arguments[1]:false;generalFormats=new Array('y-M-d','MMM d, y','MMM d,y','y-MMM-d','d-MMM-y','MMM d');monthFirst=new Array('M/d/y','M-d-y','M.d.y','MMM-d','M/d','M-d');dateFirst =new Array('d/M/y','d-M-y','d.M.y','d-MMM','d/M','d-M');var checkList=new Array('generalFormats',preferEuro?'dateFirst':'monthFirst',preferEuro?'monthFirst':'dateFirst');var d=null;for(var i=0;i<checkList.length;i++){var l=window[checkList[i]];for(var j=0;j<l.length;j++){d=getDateFromFormat(val,l[j]);if(d!=0){return new Date(d);}}}return null;}
 
/**
 * Funktionen fuer Destination Table Umbau 14092009
 * @author Sebastian Golasch
 */
  
function initDestinations() {
  var classes = ['grey','white','last'];
  toggleDestinationClass('destinationsThree',3,classes);
  toggleDestinationClass('destinationsFour',4,classes);
}
function toggleDestinationClass (classname, modulo, classes){
                $j( '.' + classname ).each(function(){
        var elements = $j(this).find('li'), lmlngth = elements.length, color = classes[0], kids = new Array(), i, j;
        for(i=0;i<lmlngth;++i){
                        kids[i] = $j( elements[i] ).children().eq(0);
            if(kids[i] && !$j( kids[i] ).hasClass( 'destHeadline' )) {
                $j( elements[i] ).addClass( color );
            }
            switch (true){
                case (i+1)%modulo == 0:
                    if(kids[i] && !$j( kids[i] ).hasClass( 'destHeadline' )) {
                        color = color == classes[0] ? classes[1] : classes[0];
                    }
                    if(!kids[i]) {
                        var is_not_undefined = false;
                        for(j=((i+1)-modulo);j<=i;j++){
                            if(kids[j] && !$j( kids[j] ).hasClass( 'destHeadline' )) {
                                is_not_undefined = true;
                                break;
                            }
                        }
                    if(is_not_undefined === true){
                        color = color == classes[0] ? classes[1] : classes[0];
                    }                        }
                case (i+1)%modulo == 0 || lmlngth == (i+1):
                    $j( elements[i] ).addClass( classes[2] );
            }
        }
    });
} 

// JS fuer Searchfeld
function checkFormInput(obj,text) {
    var temp = document.search.SearchQueryText.value;
    if(temp == '') {
       document.search.SearchQueryText.value = text;
    } else if(temp == text) {
        document.search.SearchQueryText.value = '';
    } 
}

$j(document).ready(function () {
    $j(".main-header-nav").delegate("li:not(.nav-item-second)", "click", $j.noop);

    $j("form[name='search'] button").bind("click", function () {
        $j("form[name='search']").trigger("submit");
    });
});

/********* Funktion fuer 2- oder 4- spaltige Teaserbox  struct_4_4_shadow_variable*******/
function alignBoxHights() {
    var myDivs = document.getElementsByTagName('DIV');
    var myAlignRows = new Array();
    for( j=0; j<myDivs.length; j++ ) {
        if( myDivs[j].className.indexOf('alignHeight') > 0 ) {
            myAlignRows.push( myDivs[j] );
        }
    }    
    for( j=0; j<myAlignRows.length; j++ ) {     
        var maxBoxHeight = 0;
        var myRowDivs = myAlignRows[j].getElementsByTagName('DIV');
        var myAlignBoxes = new Array();
        for( i=0; i<myRowDivs.length; i++ ) {
            if( myRowDivs[i].className.indexOf('alignBox') > 0 ) {
                myAlignBoxes.push( myRowDivs[i] );
            }
        }        
        for( i=0; i<myAlignBoxes.length; i++ ) {
            var myBox =  myAlignBoxes[i];
            //myBox.style.height = '';                                                                
            if( myBox.offsetHeight > maxBoxHeight ) {
                maxBoxHeight = myBox.offsetHeight;
            } 
        }
        for( i=0; i<myAlignBoxes.length; i++ ) {
            var myBox =  myAlignBoxes[i];    
            myBox.style.height = maxBoxHeight + 'px';        
        }                                                                             
    }
}

$j(document).ready(function(){
    var ac_url = document.URL.split("/");

    preExecOpened();
    
    // korrektur box hoehe
    if(ac_url[ac_url.length -1] != "Allgemeine-Befoerderungsbedingungen-ABB.htm" && 
       ac_url[ac_url.length -1] != "Unternehmen-Pressearchiv.htm" &&
       ac_url[ac_url.length -1] != "Sparkalender.html" && 
       ac_url[ac_url.length -1] != "Last-Minute-Fluege-ab-Hannover.shtml" &&
       ac_url[ac_url.length -1] != "Last-Minute-Fluege-ab-Berlin.shtml" &&
       ac_url[ac_url.length -1] != "Last-Minute-Fluege-ab-Koeln.shtml" &&
       ac_url[ac_url.length -1] != "Last-Minute-Fluege-ab-Stuttgart.shtml" &&
       !document.URL.match("Angebote/Flugangebote")) {   
            alignBoxHights();
        }
    

    //Teaser headline korrektur
    var ac_url = document.URL.split("/");
    if(ac_url[ac_url.length -1] != "Allgemeine-Befoerderungsbedingungen-ABB.htm" && 
       ac_url[ac_url.length -1] != "Unternehmen-Pressearchiv.htm" &&
       ac_url[ac_url.length -1] != "Last-Minute-Fluege-ab-Hannover.shtml" &&
       ac_url[ac_url.length -1] != "Last-Minute-Fluege-ab-Berlin.shtml" &&
       ac_url[ac_url.length -1] != "Last-Minute-Fluege-ab-Koeln.shtml" &&
       ac_url[ac_url.length -1] != "Last-Minute-Fluege-ab-Stuttgart.shtml" &&
       !document.URL.match("Angebote/Flugangebote")) {   
            correctTeaserHeadlines();
    }
});

function correctTeaserHeadlines(){
    var classes = ['.contentTeaserBgIcon', '.contentTeaserBgImageLarge', '.contentTeaserImage', '.teaserOnlyHeadline', '.picText'];
    $j.each(classes, function (idx, elm){
        var $elmnts = $j(elm),
            margin_top = '18.2px',
            headline = 'h5',
            rp = false,
            pp = false;
        if(typeof $elmnts.get(0) !== "undefined"){
            $elmnts.each(function (idx, element) {
                $j(element).find(headline).each(function (idx2, headline) {
                    var headline_parant_classname = headline.parentNode.className,
                        $headline = $j(headline),
                        padding_top = 0,
                        headline_height = 0;
                    $headline.css("display", "inline");
                    padding_top = parseInt($headline.css("paddingTop"));
                    headline_height = $headline.height();
                    if(headline_parant_classname === 'contentTeaserBgIcon'){
                       padding_top = 0;
                    }
                    if((headline_height - padding_top) >= 60 && headline_parant_classname !== "contentTeaserBgImageLarge"){
                        rp = true;
                    }
                    if(headline_height >= 34 && headline_parant_classname === "picText"){
                        pp = true;
                        rp = true;
                    }
                    if(headline_parant_classname ==="contentTeaserBgImageLarge"){
                        if(headline_height - padding_top >= 34){
                            rp = true;
                        }
                    }
                    $headline.css("display", "block");
                });
            });
        }
        if (rp === true) {
            $elmnts.each(function (idx, element) {
                $j(element).find(headline).each(function (idx2, headline) {
                    var $headline = $j(headline);
                    $j($headline.find("div").get(0)).css("marginTop", margin_top);
                    if(pp === true){
                        $j($j($headline.get(0).parentNode).find("p").get(0)).css("marginTop", margin_top);
                    }
                });
            });
        }
    });
}

function correctStructBackground(){
    (function ($) {
        var teaserbg = {3: "/de/Images/Buchung/bg_struct_teasergroup_3_3.gif", 2: "/de/Images/Buchung/bg_struct_teasergroup_3_3_2teaser.gif", 1: "/de/Images/Buchung/bg_struct_teasergroup_3_3_1teaser.gif"};
        $(".strucTeasergroup33").each(function (idx, struct) {
            var $struct = $(struct),
                $struct_group = $struct.find("div.group"),
                struct_group_size = $struct_group.length,
                structContentLength = $struct.find("div.group.alignButton").find("div.contentTeaserImage").length || 0;
            if(struct_group_size - 1 >= 0){
                if (structContentLength % 3 === 0) {
                    $($struct_group.get(struct_group_size - 1)).css("backgroundImage", "url(" + teaserbg[3] + ")");
                }else{
                    $($struct_group.get(struct_group_size - 1)).css("backgroundImage", "url(" + teaserbg[structContentLength % 3] + ")");
                }
            }
        });
    }(jQuery));
}

/************************ scrollToElement build the Dropdownitems ***************************/
// scrolling in den last minute seiten
$j(document).ready(function () {
            var data = $j(".dropDownIndex"), i, currentValue, selectElmnt = $j("#destination");
            data.each(function (idx, item) {
                currentValue = item.innerHTML;
                                
                var elOptNew = document.createElement('option');
                elOptNew.text = currentValue;
                elOptNew.value = currentValue;
                var elSel = selectElmnt[0];
                try {
                 elSel.add(elOptNew, null); // standards compliant; doesn't work in IE
                }
                catch(ex) {
                 elSel.add(elOptNew); // IE only
                }
            });
            
        });    
        function go (select) {
            scrollToElement(document.getElementById("lm_" + select.selectedIndex)); 
        };
        function scrollToElement(theElement){
            var selectedPosX = 0;
            var selectedPosY = 0;
              
            while(theElement != null){
                selectedPosX += theElement.offsetLeft;
                selectedPosY += theElement.offsetTop;
                theElement = theElement.offsetParent;
            }                                 
            window.scrollTo(selectedPosX,selectedPosY);
        };
 
// Ticker init script
$j(document).ready( function () {
    if(typeof run_ticker == "function"){
        run_ticker();
    }   
});

$j(document).ready( function () {
    
    if ($j("body").hasClass("ie")) {
                $j('.main-header-nav li').hover(
                    function () {
                        if(!$j(this).hasClass('nav-item-second-active')){
                            $j(this).addClass('hover');
                            $j(this).next('li').addClass('next-li');
                        }else{
                            //do nothing
                        }
                    },
                    function () {
                        $j(this).removeClass('hover');
                        $j(this).next('li').removeClass('next-li');
                    }
                );
            }
});


/**** Tracking ****/
(function (window, document, $, undef) {
    /**
     * Private helper functions
     *
     */
    var is_string = function (obj) {
        return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
    },
    /**
     * Finds click trackable structs
     * Trackable structs are defined through two css class statements
     * placed in the sorrounding element:
     * *tracking-flag which activates the tracking for this element
     * *trackng-expr() which holds the tracking metadate (brackets used here, separator is free to choose)
     *
     * <code>
     *     <div class="aClass some-other-class %trackng-flag% %trackng-expr%(%tracking_type%_%tracking_id%) anotherClass">
     *         // Some code
     *     </div>
     * </code>
     *
     * <code>
     *     // Simple
     *     var simpleTrackingFinder = new TrackingStructFinder();
     *     var trackableElements = simpleTrackingFinder.find();
     *     // Expert
     *     var expertTrackingFinder = new TrackingStructFinder("trckng-flag", "trckng-expr",  ["(",")"], "_");
     *     var trackableElements = expertTrackingFinder.find();
     *     // Output meta data
     *     console.log($.data(trackableElements[0], "trackingType");
     * </code>
     *
     * @package Tracking
     * @subPackage Click-Tracking
     * @author Sebastian Golasch <sebastian.golasch@denkwerk.com>
     * @version 2.0.0
     * @since Class exists since version 2.0.0
     * @requires jClassify
     * @requires Prototype
     */
        TrackingStructFinder = Class.extend({
        
        /**
         * Sets and checks the initial object values
         * to find the trackable elements
         *
         * @constructor
         * @param tracking_class_flag string The css class that should be used as an indicator for tracking
         * @param tracking_expression string The css class/expression tha holds the tracking meta information
         * @param tracking_type_separation_characters array The chracters used for enclosing the the meta information
         * @param tracking_id_separation_character string The character thats used to separate the tracking type from the tracking id
         */
        init: function (tracking_class_flag, tracking_expression, tracking_type_separation_characters, tracking_id_separation_character) {
            this.trackingClassFlag = is_string(tracking_class_flag) ? tracking_class_flag : "trckng";
            this.trackingExpression = is_string(tracking_expression) ? tracking_expression : "trckng-expr";
            this.trackingContentSeparationCharacters = $.isPlainObject(tracking_type_separation_characters) && is_string(tracking_type_separation_characters[0]) && is_string(tracking_type_separation_characters[1]) ? tracking_type_separation_characters : ["(", ")"];
            this.trackingTypeSeparationChar = is_string(tracking_id_separation_character) ? tracking_id_separation_character : "_";
            this.elements = [];
        },
        /**
         * Finds all trackable elements in the DOM tree
         * Attaches two funtions to everey trackable element,
         * *getTrackingType - Returns the tracking type string representation
         * *getTrackingId - Returns the elements tracking id
         *
         * @return elements array An array with all trackable elements
         */
        find: function () {
            var $elements = $("." + this.trackingClassFlag);
            // loop over trackable elements and add the getter and setter methods
            this.elements = $.map($elements, $.proxy(function (element, idx) {
                // add tracking type data
                $.data(element, "trackingType", this.extractMetaData(element).type);
                return element;
            }, this));
            return this.elements;
        },

        /**
         * Retrieves an object with
         * the given tracking separators
         *
         * @return tracking_separators object List of applied tracking separators
         */
        getTrackingSeparators: function () {
            return {
                classFlag: this.trackingClassFlag,
                expression: this.trackingExpression,
                contentSeparationCharacters: this.trackingContentSeparationCharacters,
                typeSeparationChar: this.trackingTypeSeparationchar
            };
        },
        /**
         * Extracts the tracking meta data out of
         * the css class expression
         *
         * @param element object The element the meta data should extracted for
         * @return metaData object The elements meta data, containing an type and an id
         */
        extractMetaData: function (element) {
            var class_name = typeof element.get === "function" ? element.get(0).className : element.className,
                expression = class_name.substr(class_name.indexOf(this.trackingExpression + this.trackingContentSeparationCharacters[0]) + (this.trackingExpression + this.trackingContentSeparationCharacters[0]).length).split(this.trackingContentSeparationCharacters[1])[0],
                type_id_separation_char = expression.indexOf(this.trackingTypeSeparationChar);
            return {
                type: expression.substr(0, type_id_separation_char),
                id: expression.substr(type_id_separation_char + 1)
            };
        }
    }),
    /**
     * Abstract emitter filter plugin object,
     * filters tracking strings, before they will
     * be submitted to omniture
     * All child classes must overwrite the filter method
     *
     * <code>
     *     // Create new concrete plugin implementation
     *     var concretePlugin = Class.create();
     *
     *     // Extend the concrete plugin with the abstract plugin functionality
     *     concretePlugin.prototype = Object.extend(new AbstractEmitterPlugin(), {
     *         filter: function(tracking_data){
     *             // Do something with the tracking_data
     *             return tracking_data;
     *         }
     *   });
     * </code>
     *
     * @package Tracking
     * @subPackage Click-Tracking
     * @author Sebastian Golasch <sebastian.golasch@denkwerk.com>
     * @version 2.0.0
     * @since Class exists since version 2.0.0
     * @requires jClassify
     * @requires Object
     * @abstract
     */
    AbstractEmitterPlugin = Class.extend({
        /**
         * Empty constructor
         *
         * @constructor
         */
        init: function () {},
        /**
         * Filters the tracking data, before it will be submittet
         * Must be implemented by its child objects
         *
         * @param tracking_data string
         * @throws No concrete filter emitter handler implementation available, if method is not implemented in child objects
         */
        filter: function (tracking_data) {
            throw "No concrete filter emitter handler implementation available";
        }
    }),
    /**
     * Abstract teaser plugin object,
     * all tracking plugins need to inherit this
     * object and override the two given methods:
     * "getPluginName" and "trackingHandler"
     *
     * <code>
     *     // Create new concrete plugin implementation
     *     var concretePlugin = Class.create();
     *
     *     // Extend the concrete plugin with the abstract plugin functionality
     *     concretePlugin.prototype = Object.extend(new AbstractTrackingPlugin(), {
     *         getPluginName: function(){
     *             return "Concrete plugin name";
     *         },
     *         trackingHandler: function(event){
     *             // do something on click
     *         }
     *   });
     * </code>
     *
     * @package Tracking
     * @subPackage Click-Tracking
     * @author Sebastian Golasch <sebastian.golasch@denkwerk.com>
     * @version 2.0.0
     * @since Class exists since version 2.0.0
     * @requires jClassify
     * @requires Event
     * @requires Object
     * @abstract
     */
    AbstractTrackingPlugin = Class.extend({
        /**
         * Prepares the default tracking separator
         *
         * @constructor
         */
        init: function () {
            this.trackingSeparator = "|";
            this.filters = [];
            this.beforeFilters = [];
        },
        /**
         * Should return the plugin name when concretly implemented,
         * throws an error when not correctly implemented
         *
         * @return plugin_name string The plugin name
         * @throws No concrete plugin handler implementation available, if method will not be overriden in the inherited implementation
         */
        getPluginName: function () {
            if (is_string(this.name) && this.name !== "") {
                return this.name;
            }
            throw "No concrete plugin handler implementation available";
        },
        /**
         * Will be called to handle the click event,
         * throws an error when not correctly implemented
         *
         * @param event object Event properties
         * @throws No concrete tracking handler implementation available, if method will not be overriden in the inherited implementation
         */
        trackingHandler: function (event) {
            throw "No concrete tracking handler implementation available";
        },
        /**
         * Sets the tracking separator string,
         * omniture is used to, to split the incoming tracking values
         *
         * @param tracking_separator string The trakcing separator character
         * @return this AbstractTrackingPlugin AbstractTrackingPlugin instance
         */
        setTrackingSeparator: function (tracking_separator) {
            this.trackingSeparator = is_string(tracking_separator) ? tracking_separator : "|";
            return this;
        },
        /**
         * Adds an local return value filter
         * to the tracking strings that afterwards,
         * will be send to omniture
         *
         * @param filter AbstractEmitterPlugin
         * @return this AbstractTrackingPlugin
         */
        addFilter: function (filter) {
            if (filter instanceof AbstractEmitterPlugin) {
                this.filters.push(filter);
            }
            return this;
        },
        /**
         * Adds an local return value filter
         * to the tracking strings that afterwards,
         * will be send to omniture
         *
         * @param filter AbstractEmitterPlugin
         * @return this AbstractTrackingPlugin
         */
        addBeforeFilter: function (filter) {
            if (filter instanceof AbstractEmitterPlugin) {
                this.beforeFilters.push(filter);
            }
            return this;
        },
        /**
         * Emits the tracking value data to omniture
         *
         * @param signature string The tracking link signature
         * @param element object The corresponding object
         * @return this AbstractTrackingPlugin AbstractTrackingPlugin instance
         */
        sendTrackingValues: function (signature, element) {
            var s = s_gi('germanwingscomprod');
            s.linkTrackVars = 'eVar9';
            s.linkTrackEvents = 'None';
            s.eVar9 = signature;
            s.tl(element, 'e', 'Link Name');
            return this;
        },
        /**
         * Generates the tracking link signature
         *
         * @param id string The tracking id
         * @param content string The tracked content
         * @param position string|integer The elements position (tracking position not coordinates or stuff)
         * @return signature string Teaser tracking link
         */
        renderLinkSignature: function (id, content, position) {
            var pos = (!is_string(position) && typeof position !== 'number' ? 1 : position),
                signature;
            // apply filter to the content
            $.each(this.filters, $.proxy(function (idx) {
                id = this.beforeFilters[idx].filter(id);
                position = this.beforeFilters[idx].filter(pos);
                content = this.beforeFilters[idx].filter(content);
            }, this));
            // Build signature
            signature = id + this.trackingSeparator + pos + this.trackingSeparator + content;
            // apply filter to the content
            $.each(this.filters, $.proxy(function (idx) {
                signature = this.filters[idx].filter(signature);
            }, this));
            return signature;
        },
        /**
         * Finds the parent tracking container
         * from an given element
         *
         * @param element object DOM element to look up for its parent tracking container
         * @return tracking_container object DOM element representation of the parent tracking container
         */
        findParentTrackingContainer: function (element) {
            return element.className.search('\\b' + this.separators.classFlag + '\\b') !== -1 ? element : this.findParentTrackingContainer(element.parentNode);
        },
        /**
         * Sets the tracking separator flags
         *
         * @param separators object The tracking separator flags
         * @return this AbstractTrackingPlugin
         */
        setTrackingSeparators: function (separators) {
            this.separators = separators;
            return this;
        },
        /**
         * Finds and returns the parent element if its
         * an anchor or the document element
         *
         * @param element object DOM element to look up for its parent anchor
         * @return tracking_container object DOM element representation of the parent anchor or the document element
         */
        getParentElement: function (element) {
            return element === document || element.tagName.toLowerCase() === 'a' ? element : this.getParentElement(element.parentNode);
        }
    }),
    /**
     * Manages the plugins for the click tracking application
     * Stores, validates and returns plugins
     *
     * <code>
     *     // instanciate the plugin manager
     *     var pluginManager = new TrackingPluginManager();
     *
     *     // Attach plugins to the manager
     *     pluginManager
     *         .attach(plugin_1)
     *         .attach(plugin_2)
     *
     *     // Check if a plugin exists
     *     pluginManager.hasPlugin("plugin_1_name");  // Returns true
     *     pluginManager.hasPlugin("not_existing_plugin_3_name"); // Returns false
     *
     *     // Grab a plugin out of the collection
     *     if(pluginManager.hasPlugin("plugin_1_name")){
     *         var instance_of_plugin_1 = pluginManager.getPlugin("plugin_1_name");
     *     }
     * </code>
     *
     * @package Tracking
     * @subPackage Click-Tracking
     * @author Sebastian Golasch <sebastian.golasch@denkwerk.com>
     * @version 2.0.0
     * @since Class exists since version 2.0.0
     * @requires jClassify
     */
    TrackingPluginManager = Class.extend({
        /**
         * Prepares the plugin collection
         *
         * @constructor
         */
        init: function (separators) {
            this.separators = separators;
            this.plugins = {};
        },
        /**
         * Attaches an plugin to the collection
         *
         * @param plugin AbstractTrackingPlugin Tracking plugin object
         * @return this TrackingPluginManager Instance of TrackingPluginManager
         */
        attach: function (plugin) {
            if (plugin instanceof AbstractTrackingPlugin) {
                this.plugins[plugin.getPluginName()] = plugin.setTrackingSeparators(this.separators);
            }
            return this;
        },
        /**
         * Detaches an plugin by its name
         *
         * @param plugin_name string The name of the plugin that should be detached
         * @return this TrackingPluginManager Instance of TrackingPluginManager
         */
        detach: function (plugin_name) {
            // Check if the questioned plugin exists
            if (!this.hasPlugin(plugin_name)) {
                return this;
            }
            // Iterate over attached plugins and reassign non detached
            this.plugins = $.map(this.plugins, function (item, idx) {
                // Check for plugins, who wont be detached
                if (idx !== plugin_name) {
                    // Add non detached plugins
                    return item;
                }
            });
            
            return this;
        },
        /**
         * Checks if an plugin, corresponding to the given name, exists
         *
         * @param plugin_name string The name of the plugin to look for
         * @return plugin_exists bool Plugin exists
         */
        hasPlugin: function (plugin_name) {
            return this.plugins[plugin_name] instanceof AbstractTrackingPlugin ? true : false;
        },
        /**
         * Returns an tracking plugin, corresponding to the given name
         *
         * @param plugin_name string The name of the plugin
         * @return object|null tracking_plugin The tracking plugin instance or null
         */
        getPlugin: function (plugin_name) {
            return this.hasPlugin(plugin_name) ? this.plugins[plugin_name] : null;
        }
    }),
    /**
     * Decorates trackable elements with an "onclick" event,
     * the event comes out of the plugin, based on the teaser type
     *
     * <code>
     *    // instanciate the event decorator
     *    var trackingEvents = new TrackingEventDecorator(pluginManager, '|');
     *
     *    // If you need to be filter the strings send to omniture, you can apply filters as follows
     *    trackingEvents
     *      .addFilter(filter1)
     *      .addFilter(filter2);
     *
     *    // attach an onclick event, to an trackable element
     *    try{
     *        trackingEvents.attachEventHandler(an_trackable_element);
     *    }catch(ex){
     *        alert(ex);
     *    }
     * </code>
     *
     * @package Tracking
     * @subPackage Click-Tracking
     * @author Sebastian Golasch <sebastian.golasch@denkwerk.com>
     * @version 2.0.0
     * @since Class exists since version 2.0.0
     * @requires jClassify
     * @requires Event
     */
    TrackingEventDecorator = Class.extend({
        /**
         * Sets the plugin manager and the tracking separator
         * used by omniture to split the incoming tracking values
         * Prepares the filter collection
         *
         * @param plugin_manager TrackingPluginManager Plugin manager instance
         * @param tracking_separator string Character used by omniture to split the incominf tracking values
         */
        init: function (plugin_manager, tracking_separator) {
            this.pluginManager = plugin_manager;
            this.trackingSeparator = is_string(tracking_separator) ? tracking_separator : "|";
            this.filters = [];
            this.beforeFilters = [];
        },
        /**
         * Adds an filter to the all plugins
         *
         * @param filter AbstractEmitterPlugin The filter to be applied
         * @return this TrackingEventDecorator TrackingEventDecorator instance
         */
        addFilter: function (filter) {
            if (filter instanceof AbstractEmitterPlugin) {
                this.filters.push(filter);
            }
            return this;
        },
        /**
         * Change behaviour of the last applied filter
         * to filter the incoming data, before the tracking
         * string will be build
         *
         * @return this TrackingEventDecorator TrackingEventDecorator instance
         */
        before: function () {
            this.beforeFilters.push(this.filters.pop());
            return this;
        },
        /**
         * Attaches an event handler to the tracking
         * Checks if the tracking plugin exists
         * Return value of tracking plugins "getPluginName" function
         * must match the tracking type string
         *
         * @param element object Trackable dom element
         * @return this TrackingEventDecorator Instance of TrackingEventDecorator
         * @throws Element %element_name% is not trackable, if the element is not decorated with the "getTeaserType" function
         * @throws Tracking plugin %plugin_name% does not exist, if the plugin based on the teaser type is not assigned
         */
        attachEventHandler: function (element) {
            var tracking_type = $.data(element, "trackingType") !== undef && $.data(element, "trackingType") !== null ? $.data(element, "trackingType") : null,
                plugin;
            // check if tracking type is available
            if (tracking_type === null) {
                throw "Element is not trackable";
            }
            // check if tracking plugin exists (based on tracking type)
            if (!this.pluginManager.hasPlugin(tracking_type)) {
                throw "Tracking plugin '" + tracking_type + "' does not exist";
            }
            // retrieve plugin and configure
            plugin = this.pluginManager
                         .getPlugin(tracking_type)
                         .setTrackingSeparator(this.trackingSeparator);
            // set global applied (after) filters
            $.each(this.filters, $.proxy(function (idx) {
                plugin.addFilter(this.filters[idx]);
            }, this));
            // set global applied (before) filters
            $.each(this.beforeFilters, $.proxy(function (idx) {
                plugin.addBeforeFilter(this.beforeFilters[idx]);
            }, this));
            // attach the plugin event handler
            $(element).delegate("a", "click", $.proxy(plugin.trackingHandler, plugin));
            return this;
        }
    }),
    /**
     * Filter plugin for replacing special characters
     * that should not be send to omniture
     *
     * @package Tracking
     * @subPackage Click-Tracking
     * @author Sebastian Golasch <sebastian.golasch@denkwerk.com>
     * @version 2.0.0
     * @since Class exists since version 2.0.0
     * @requires jClassify
     * @requires Object
     */
    SpecialCharacterReplacer = AbstractEmitterPlugin.extend({
        /**
         * Filters characters that should not been
         * send to omniture
         *
         * @param tracking_data string
         * @return filtered_tracking_data string
         */
        filter: function (tracking_data) {
            return this.replaceChars(['ü', 'Ü', 'ä', 'Ä', 'ö', 'Ö', 'ß', '&uuml;', '&Uuml;', '&auml;', '&Auml;', '&ouml;', '&Ouml;', '&szlig;', '&euro;', '\u20ac', '&amp;', '&', '|'], ['ue', 'Ue', 'ae', 'Ae', 'oe', 'Oe', 'ss', 'ue', 'Ue', 'ae', 'Ae', 'oe', 'Oe', 'ss', 'EUR', 'EUR', 'und', 'und', ''], tracking_data);
        },
        /**
         * Local helper function for replacing
         * large character sets
         *
         * @param search array
         * @param replace array
         * @param subject string
         * @return replaced_chars string
         */
        replaceChars: function (search, replace, subject) {
            var ret_val = subject + "";
            $.each(search, function (idx, item) {
                if (is_string(replace[idx])) {
                    ret_val = ret_val.replace(new RegExp(search[idx], 'g'), replace[idx]);
                }
            });
            return ret_val;
        }
    }),
    /**
     * Teasergroup 44 tracking plugin
     *
     * @package Tracking
     * @subPackage Click-Tracking
     * @author Sebastian Golasch <sebastian.golasch@denkwerk.com>
     * @version 2.0.0
     * @since Class exists since version 2.0.0
     * @requires jClassify
     * @requires Event
     * @requires AbstractTrackingPlugin
     */
    TrackerTeasergroup44 = AbstractTrackingPlugin.extend({
        /**
         * Name of the plugin
         *
         * @type string
         */
        name: "Teasergroup44",
        /**
         * Enable logging
         *
         * @var bool
         */
        enableLogging: false,
        /**
         * Takes and sets an array of class names
         * which declare the different tracking teasers
         * inherited by the container
         *
         * @param class_names array Array of css class names
         */
        init: function (class_names, enableLogging) {
            this._super();
            this.classNames = class_names;
            this.enableLogging = enableLogging;
        },

        /**
         * The handling function,
         * called as an event handler
         *
         * @param event Event Instance of prototypes event handling object
         */
        trackingHandler: function (event) {
            var element = event.currentTarget,
                metadataExtractor = new TrackingStructFinder();
            // check if an link has been clicked
            if (this.getParentElement(element) !== document) {
                // compile and send the tracking data
                if(this.enableLogging === true) {
                    console.log(this.renderLinkSignature(metadataExtractor.extractMetaData(this.findParentTrackingContainer(element)).id, this.getTeaserContent(element), this.getTeaserPosition(element), this.getExtraContent(element)));
                    event.preventDefault();
                }else{
                    this.sendTrackingValues(this.renderLinkSignature(metadataExtractor.extractMetaData(this.findParentTrackingContainer(element)).id, this.getTeaserContent(element), this.getTeaserPosition(element), this.getExtraContent(element)));
                }
            }
        },
        /**
         * Retrieves the teaser position
         * within the container
         *
         * @param teaser object
         * @return position integer
         */
        getTeaserPosition: function (teaser) {
            var teaser_container = this.traceTeaserContainer(teaser, this.classNames),
                parentStruct = this.findParentTrackingContainer(teaser),
                getAllStructs = function (node, class_names) {
                    var els = node.getElementsByTagName("*"),
                        a = [],
                        re;
                    $.each(els, function (idx, item) {
                        $.each(class_names, function (idxs, name) {
                            re = new RegExp('\\b' + name + '\\b');
                            if (re.test(els[idx].className)) {
                                a.push(els[idx]);
                            }
                        });
                    });
                    return a;
                },
                all_structs = getAllStructs(parentStruct, this.classNames),
                polyfill = null;
            $.each(all_structs, function (idx, struct) {
                if (struct === teaser_container) {
                    polyfill = (idx + 1);
                }
            });

            if(polyfill !== null) {
                return polyfill;
            }
            return 1;
        },
        /**
         * Retrieves the teaser content (headline or image alt attribute)
         *
         * @param teaser object Teaser element
         * @return teaser_content string The parsed out teaser contents
         */
        getTeaserContent: function (teaser) {
            var traceHeadline = function (teaserContainer) {
                var $teaser_container = $(teaserContainer);
                if (teaserContainer === document) {
                    return teaserContainer;
                }
                return $teaser_container.find('h5')[0] || $teaser_container.find('h4')[0] || $teaser_container.find('h3')[0] || $teaser_container.find('h2')[0] || document;
            },
                headline = traceHeadline(this.traceTeaserContainer(teaser, this.classNames)),
                node = headline.childNodes[0];
            
            if(typeof node === "undefined"){
                return $.trim($(teaser).find("img").attr("alt"));
            }

            if (node.nodeName.toLowerCase() === 'img') {
                return $.trim(node.alt);
            } else {
                return headline === document ? 'No trackable content available' : $.trim($(headline).text());
            }
        },
        /**
         * Traces the teaser container
         *
         * @param element object Teaser element
         * @param class_names array List of with possible
         */
        traceTeaserContainer: function (element, class_names) {
            var $element = $(element),
                polyfill = null;
            if (element === document) {
                return element;
            } else {
                $.each(class_names, function (idx, name) {
                    if ($element.hasClass(name)) {
                        polyfill = element;
                    }
                });
                if(polyfill !== null){
                    return polyfill;
                }

                return this.traceTeaserContainer(element.parentNode, class_names);
            }
        },
        /**
         * Retrieves the teaser content (headline or image alt attribute)
         *
         * @param element object Teaser element
         * @return extra string The parsed out extra contents
         */
        getExtraContent: function (element) {
            var parent = element.parentNode,
                url_data = [],
                url_data_length = 0,
                html_data = [],
                html_data_length = 0,
                extra = "";
            if (element.tagName.toLowerCase() !== "a" || parent.tagName.toLowerCase() !== "li" || parent.className.search("hplpt") === -1) {
                return;
            }
            url_data = element.href.replace(".htm", "").split("/");
            url_data_length = url_data.length;
            $.each(url_data, function (idx, item) {
                if (idx + 2 === url_data_length || idx + 1 === url_data_length) {
                    extra += url_data[idx] + (idx + 2 === url_data_length ? " -> " : " ");
                }                
            });
            html_data = element.innerHTML.split(" ");
            html_data_length = html_data.length;
            $.each(url_data, function (idx, item) {
                if (idx + 2 === html_data_length) {
                    extra += html_data[idx] + " EUR";
                }
            });
            return extra;
        },
        /**
         * Generates the tracking link signature
         *
         * @param id string The tracking id
         * @param content string The tracked content
         * @param position string|integer The elements position (tracking position not coordinates or stuff)
         * @param extra string|mixed Extra content special links are able to track
         * @return signature string Teaser tracking link
         */
        renderLinkSignature: function (id, content, position, extra) {
            var signature,
                pos = (!is_string(position) && typeof position !== 'number' ? 1 : position),
                special_content = is_string(extra) ? extra : false;
            // apply filter to the content
            $.each(this.beforeFilters, $.proxy(function (idx, item) {
                id = item.filter(id);
                position = item.filter(pos);
                content = item.filter(content);
                special_content = special_content !== false ? item.filter(special_content) : false;
            }, this));
            // Build signature
            signature = id + this.trackingSeparator + pos + this.trackingSeparator + content + (special_content !== false ? (this.trackingSeparator + special_content) : "");
            // apply filter to the content
            $.each(this.filters, $.proxy(function (idx) {
                signature = this.filters[idx].filter(signature);
            }, this));
            return signature;
        }
    }),
    /**
     * QuadrupelSquare tracking plugin (used at offers doorpage)
     *
     * @package Tracking
     * @subPackage Click-Tracking
     * @author Sebastian Golasch <sebastian.golasch@denkwerk.com>
     * @version 2.0.0
     * @since Class exists since version 2.0.0
     * @requires jClassify
     * @requires Event
     * @requires AbstractTrackingPlugin
     */
    TrackerQuadrupelSquare = AbstractTrackingPlugin.extend({
        /**
         * Name of the plugin
         *
         * @type string
         */
        name: "QuadrupelSquare",
        /**
         * Enable logging
         *
         * @var bool
         */
        enableLogging: false,
        /**
         *  Constructor
         *
         *
         */
        init: function (enableLogging) {
            this._super();
            this.enableLogging = enableLogging;
        },
        /**
         * The handling function,
         * called as an event handler
         *
         * @param event Event Instance of prototypes event handling object
         */
        trackingHandler: function (event) {
            var element = event.currentTarget,
                parent = this.getParentElement(element),
                metadataExtractor = new TrackingStructFinder(),
                metadata;

            // check if an link has been clicked
            if (parent !== document) {
                // grab parent element and extract its metadata
                metadata = metadataExtractor.extractMetaData(this.findParentTrackingContainer(element));
                // compile and send the tracking data
                if(this.enableLogging === true) {
                    console.log(this.renderLinkSignature(metadata.id, !is_string(parent.className) || parent.className !== "offer-teaser" ? this.getTeaserContentByLink(parent) : this.getTeaserContentByMarkup(parent), this.getTeaserPosition(element)));
                    event.preventDefault();
                }else{
                    this.sendTrackingValues(this.renderLinkSignature(metadata.id, !is_string(parent.className) || parent.className !== "offer-teaser" ? this.getTeaserContentByLink(parent) : this.getTeaserContentByMarkup(parent), this.getTeaserPosition(element)));
                }
            }
        },
        /**
         * Returns the price teaser tracking content
         * when images are used as teasers
         *
         * @param anchor object
         * @return sidebar_content string
         */
        getTeaserContentByLink: function (anchor) {
            var link = anchor.href,
                data, departure, arrival, date, data_length;
            // check if we have an low fare calnder url or seo pages related url
            if (link.split('?')[1] !== undef) {
                data = link.split('?')[1].split('&');
                departure = data[0].split('=')[1];
                arrival = data[1].split('=')[1];
                date = data[2].split('=')[1];
            } else {
                data = link.replace(".htm", "").replace(".shtm", "").replace(".aspx", "").split("/");
                data_length = data.length;
                departure = data[data.length - 2];
                arrival = data[data.length - 1];
                date = null;
            }
            return departure + ' -> ' + arrival + (date !== null ? ' @ ' + date : "");
        },
        /**
         * Returns the price teaser tracking content
         * when html markup is used for the teasers
         *
         * @param anchor object
         * @return sidebar_content string
         */
        getTeaserContentByMarkup: function (anchor) {
            var $info_elements = $(anchor).find("span"),
                $anchor =  $(anchor),
                data = {
                    currency: $($anchor.find(".currency").get(0)).text(),
                    decimal: $($anchor.find(".decimal").get(0)).text(),
                    destination: $($anchor.find(".destination").get(0)).text(),
                    intr: $($anchor.find(".int").get(0)).text(),
                    origin: $($anchor.find(".origin").get(0)).text(),
                    sep: $($anchor.find(".sep").get(0)).text()
                };

                $.each(this.beforeFilters, $.proxy(function (idx, item) {
                    data.currency = item.filter(data.currency);
                    data.decimal = item.filter(data.decimal);
                    data.destination = item.filter(data.destination);
                    data.intr = item.filter(data.intr);
                    data.origin = item.filter(data.origin);
                    data.sep = item.filter(data.sep);
                }, this));

            return data.origin + ' -> ' + data.destination + ' @ ' + data.intr + data.sep + data.decimal + ' ' + data.currency;
        },
        /**
         * Retrieves the price teaser position
         * within the price teaser struct
         *
         * @param teaser object DOM representation of the teaser element
         * @return position integer The
         */
        getTeaserPosition: function (teaser) {
            var link = this.getParentElement(teaser),
                parentStruct = this.findParentTrackingContainer(teaser),
                anchors = parentStruct.getElementsByTagName('a'),
                polyfill = null;
            $.each(anchors, function (idx, anchor) {
                if (anchor === link) {
                    polyfill = idx + 1;
                }
            });
            return polyfill || 1;
        }
    }),
    /**
     * Calendar teaser tracking plugin
     *
     * @package Tracking
     * @subPackage Click-Tracking
     * @author Sebastian Golasch <sebastian.golasch@denkwerk.com>
     * @version 2.0.0
     * @since Class exists since version 2.0.0
     * @requires jClassify
     * @requires Event
     * @requires AbstractTrackingPlugin
     */
    TrackerCalendarTeaser = AbstractTrackingPlugin.extend({
        /**
         * Name of the plugin
         *
         * @type string
         */
        name: "CalendarTeaser",
        /**
         * Enable logging
         *
         * @var bool
         */
        enableLogging: false,
        /**
         *  Constructor
         *
         *
         */
        init: function (enableLogging) {
            this._super();
            this.enableLogging = enableLogging;
        },
        /**
         * The handling function,
         * called as an event handler
         *
         * @param event Event Instance of prototypes event handling object
         */
        trackingHandler: function (event) {
            var element = event.currentTarget,
                metadataExtractor = new TrackingStructFinder();
            // compile and send the tracking data
            if(this.enableLogging === true) {
                console.log((this.renderLinkSignature(metadataExtractor.extractMetaData(this.findParentTrackingContainer(element)).id, $(element).find("img").get(0).alt)));
                event.preventDefault();
            }else{
                this.sendTrackingValues(this.renderLinkSignature(metadataExtractor.extractMetaData(this.findParentTrackingContainer(element)).id, $(element).find("img").get(0).alt));
            }
        }
    }),
    /**
     * Sidebar tracking plugin
     *
     * @package Tracking
     * @subPackage Click-Tracking
     * @author Sebastian Golasch <sebastian.golasch@denkwerk.com>
     * @version 2.0.0
     * @since Class exists since version 2.0.0
     * @requires jClassify
     * @requires Event
     * @requires AbstractTrackingPlugin
     */
    TrackerSidebarDefault = AbstractTrackingPlugin.extend({
        /**
         * Name of the plugin
         *
         * @type string
         */
        name: "SidebarDefault",
        /**
         * Enable logging
         *
         * @var bool
         */
        enableLogging: false,
        /**
         *  Constructor
         *
         *
         */
        init: function (enableLogging) {
            this._super();
            this.enableLogging = enableLogging;
        },
        /**
         * The handling function,
         * called as an event handler
         *
         * @param event Event Instance of prototypes event handling object
         */
        trackingHandler: function (event) {
            var element = event.currentTarget,
                metadataExtractor = new TrackingStructFinder(),
                metadata;
            // check if an link has been clicked
            if (this.getParentElement(element) !== document) {
                // grab parent element and extract its metadata
                metadata = metadataExtractor.extractMetaData(this.findParentTrackingContainer(element));
                if(this.enableLogging === true) {
                    console.log(this.renderLinkSignature(metadata.id, this.getSidebarContent(element), this.getSidebarPosition(element)));
                    event.preventDefault();
                }else{
                    this.sendTrackingValues(this.renderLinkSignature(metadata.id, this.getSidebarContent(element), this.getSidebarPosition(element)));
                }
            }
        },
        /**
         * Returns the sidebar tracking content
         *
         * @param element object
         * @return sidebar_content string
         */
        getSidebarContent: function (element) {
            var
            anchor = this.getParentElement(element),
                // finds the headline element for the clicked sidebar element, if one is present
                findHeadline = function (element) {
                    return element.getElementsByTagName('h5')[0] || element.getElementsByTagName('h4')[0] || element.getElementsByTagName('h3')[0] || element.getElementsByTagName('h2')[0] || null;
                },
                box = this.findBox(anchor),
                headline = typeof box === 'object' ? findHeadline(box.parentNode) : document,
                node = headline.childNodes[0];
            // check if we found an proper headline tag
            if (headline !== document) {
                if (node.nodeName.toLowerCase() === "img" && typeof node.alt === "string" && $.trim(element.alt) !== "") {
                    return node.alt;
                } else {
                    return $.trim(headline.innerHTML);
                }
            }
            // check if the element is an image, ans has a proper alt attribute
            if (element.tagName.toLowerCase() === "img" && typeof element.alt === "string" && $.trim(element.alt) !== "") {
                return element.alt;
            }
            return 'No trackable content available';
        },
        /**
         * Returns the position of the requested
         * sidebar element
         *
         * @param element object DOM element the position is requested
         * @return sidebar_position integer The position of the clicked sidebar element
         */
        getSidebarPosition: function (element) {
            var container = this.findParentTrackingContainer(element),
                anchor = this.getParentElement(element),
                box = this.findBox(anchor),
                // gets all elements annotated with the box class
                getAllBoxes = function (container) {
                    var elements = $(container).find("*"),
                        class_name = "box";
                    return $(elements).map(function (idx, element) {
                            if ($(element).hasClass(class_name)) {
                                return element;
                            }
                        });
                },
                boxes = getAllBoxes(container),
                polyfill = null;
            $.each(boxes, function (idx, item) {
                if (box === item) {
                    polyfill = (idx + 1);
                }
            });
            return polyfill || 1;
        },
        /**
         * Finds the sidebar elements parent element thats been annotated with the box class
         *
         * @param element object The element you want to look upward for the annotated element
         * @return box_element The annotated element
         */
        findBox: function (element) {
            return $(element).hasClass('box') === true ? element : this.findBox(element.parentNode);
        }
    }),
    /**
     * Ticker tracking plugin
     *
     * @package Tracking
     * @subPackage Click-Tracking
     * @author Sebastian Golasch <sebastian.golasch@denkwerk.com>
     * @version 2.0.0
     * @since Class exists since version 2.0.0
     * @requires jClassify
     * @requires Event
     * @requires AbstractTrackingPlugin
     */
    TrackerTicker = AbstractTrackingPlugin.extend({
        /**
         * Name of the plugin
         *
         * @type string
         */
        name: "Ticker",
        /**
         * Trackable elements
         *
         * @type string
         */
        elements: [],
        /**
         * Trackable elements
         *
         * @type string
         */
        elementsData: [],
        /**
         * Enable logging
         *
         * @var bool
         */
        enableLogging: false,
        /**
         *  Constructor
         *
         *
         */
        init: function (enableLogging) {
            this.enableLogging = enableLogging;
            this._super();
            window.setTimeout($.proxy(function () {
                var metadataExtractor = new TrackingStructFinder(),
                    data_puffer = [],
                    data = metadataExtractor.find(),
                    elements = [];
                $.each(data, $.proxy(function (idx, item) {
                    if (item.className.search(this.getPluginName() + "_") > -1) {
                        elements = $(item).find("a");
                    }
                }, this));
                $.each(elements, $.proxy(function (idx, item) {
                    if (typeof data_puffer[elements[idx].innerHTML] !== "object") {
                        this.elements.push(elements[idx]);
                    }
                }, this));
            }, this), 350);
        },
        /**
         * The handling function,
         * called as an event handler
         *
         * @param event Event Instance of prototypes event handling object
         */
        trackingHandler: function (event) {
            var element = event.currentTarget,
                metadataExtractor = new TrackingStructFinder(),
                metadata;
            // check if an link has been clicked
            if (this.getParentElement(element) !== document) {
                // grab parent element and extract its metadata
                metadata = metadataExtractor.extractMetaData(this.findParentTrackingContainer(element));
                if(this.enableLogging === true) {
                    console.log(this.renderLinkSignature(metadata.id, this.getTickerContent(element), this.getTickerPosition(element)));
                    event.preventDefault();
                }else{
                    this.sendTrackingValues(this.renderLinkSignature(metadata.id, this.getTickerContent(element), this.getTickerPosition(element)));
                }
            }
        },
        /**
         * Returns the content of the clicked element
         *
         * @param element object Dom element to grab the contents from
         * @return ticker_content string The contents of the given element
         */
        getTickerContent: function (element) {
            return typeof element.title === 'string' && element.title.length > 0 ? element.title : element.innerHTML;
        },
        /**
         * Returns the position of the
         * clicked anchor
         *
         * @param element object Dom element to check the position for
         * @return ticker_position integer The position of the clicked link
         */
        getTickerPosition: function (element) {
            var polyfill = null;
            $.each(this.elements, $.proxy(function (idx, item) {
                if (element.innerHTML === item.innerHTML) {
                    polyfill = (idx + 1);
                }
            }, this));
            return polyfill || 1;
        }
    });
    // Initiate tracking if window element is ready
    $(function () {
        var simpleTrackingFinder = new TrackingStructFinder(),
            trackableElements = simpleTrackingFinder.find(),
            pluginManager = new TrackingPluginManager(simpleTrackingFinder.getTrackingSeparators()),
            enableLogging = false,
            trackingEvents;
        // attach plugins to the manager
        pluginManager.attach(new TrackerTeasergroup44(['contentTeaserBgImage', 'contentTeaserImage', 'teaser14FlagTable', 'contentTeaserBgIcon', 'structShadow44', 'struct_4_4', 'text44', 'folderText44', 'teaserOnlyHeadline'], enableLogging))
                     .attach(new TrackerQuadrupelSquare(enableLogging))
                     .attach(new TrackerCalendarTeaser(enableLogging))
                     .attach(new TrackerSidebarDefault(enableLogging))
                     .attach(new TrackerTicker(enableLogging));
        // instanciate the event decorator
        trackingEvents = new TrackingEventDecorator(pluginManager);
        // Add global return value filter at an before compile step
        trackingEvents.addFilter(new SpecialCharacterReplacer()).before();
        // attach an event handler, to all trackable elements
        $.each(trackableElements, function (idx, item) {
            trackingEvents.attachEventHandler(item);
        });
    });
}(window, document, jQuery));
