/* version: 8.60.p02.00 */
/* 
 * DB Bahn JavaScript
 * Copyright (c) 2008, namics (deutschland) gmbh. All rights reserved.
 * Code licensed under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 */

/* Typ-Strings fuer Type-ahead-History-Cookie der Suggest-Lib.
   Muss hier ausserhalb des Namespaces stehen! */
var historyCookieTypeString = "";
function qfSetHistCookieTypeStr() {
    var ts = jQuery('input#qf-bhf-typeahead-historycookie-typestring').val();
    if (ts) {
        historyCookieTypeString = ts.split(",");
    }
}

/* Konfigurationsfunktion fuer alle Kalender.
   Muss hier ausserhalb des Namespaces stehen! */
function qfInitCalendars() {
    var ms = jQuery('input#qf-months-texts').val();
    var ma = "";
    if (ms) {
        ma = ms.split(",");
    }

    var ws = jQuery('input#qf-weekday-texts-short').val();
    var wa = "";
    if (ws) {
        wa = ws.split(",");
    }

    var cs = jQuery('input#qf-cal-close-text').val();

    calman.config = {
        "today"           : new Date(),
        "viewPeriodS"     : parseUserDateInput("01.01.1900"),
        "viewPeriodE"     : parseUserDateInput("31.12.2099"),
        "dataPeriodS"     : parseUserDateInput("01.01.1900"),
        "dataPeriodE"     : parseUserDateInput("31.12.2099"),
        "monthsTexts"     : ma,
        "weekdaysTexts"   : wa,
        "closeText"       : cs,
        "showShortYear"   : true,
        "styleClass"      : "calendardiv"
    }
}

/* Konfigurationsfunktion je Kalender.
   Muss hier ausserhalb des Namespaces stehen!
 * calNummer: eindeutige Nummer des Kalenders auf der Seite
 * textfeldId: ID des Textfeldes, in dem das Datum angezeigt/eingegeben wird
 * textfeldName: Name des Textfeldes, in dem das Datum angezeigt/eingegeben wird
 * returnDateCalNummer: eindeutige Nummer des zugeordneten Rueckfahrt-Kalenders auf der Seite.
 *      Falls dies gesetzt ist (true), dann wird fuer das jeweils
 *      Rueckfahrt-Feld ein Verknuepfung hergestellt, d.h. von Hinfahrt zu Rueckfahrt
 * returnDateOffset: Offset, um den das Rueckfahrtdatum oben weiter gestellt wird als die Hinfahrt; standardmaessig 0
 */
function qfInitCalendar(calNummer, textfeldId, textfeldName,  returnDateCalNummer, returnDateOffset) {
    var calcon_config = {
        "formName"        : "document.".concat(document.getElementById(textfeldId).form.name),
        "fieldName"       : textfeldName,
        "referenceObject" : "callink".concat(calNummer),
        "returnCalId"     : returnDateCalNummer ? "callink".concat(returnDateCalNummer) : null, /* Verknuepfung zum Rueckfahrtdatumsfeld */
        "returnCalShift"  : returnDateOffset
    }
    calman.createCalendar(calcon_config);
}

/* Quickfinder-Namespace */
var BAHN_QF = {
    TRIPLE_ID_EXT: "-tripleid",
    
    QF_MAX_REISENDE: 5,             // max. Anzahl Reisende fuer Quickfinder

    QF_REISENDER_TYP_ERW: "E",      // Reisendertyp Erwachsener
    QF_REISENDER_TYP_FKIND: "F",    // Reisendertyp Familienkind (Kind reist zus. mit mind. 1 Erwachsenem)
    QF_REISENDER_TYP_AKIND: "K",    // Reisendertyp alleinreisendes Kind
    QF_REISENDER_TYP_KKIND: "B",    // Reisendertyp Kleinkind

    QF_REISEPROFIL_CHANGED_EVENT: 99,

    // Konstanten fuer QfReiseprofilUpdater
    QF_REISEPROFIL_SELECTBOX_ID: 1,
    QF_REISEPROFIL_FAST_BOOK_MODE_ID: 2,
    QF_REISEPROFIL_PREFIX_KLASSE_RADIO_ID: 3,
    QF_REISEPROFIL_FAST_BOOK_MODE_MARKER: 4,
    
    // Konstanten fuer QfReisendeUpdater:
    // Keys fuer IDs der Selectboxen
    QF_KEY_ADULTS_ID: 1,
    QF_KEY_CHILDREN_ID: 2,
    QF_KEY_INFANTS_ID: 3,
    // Keys fuer Praefixe fuer die IDs der Inputfelder in den Reisendenzeilen
    QF_KEY_PREFIX_TRAV_TYPE_ID: 4,
    QF_KEY_PREFIX_TRAV_BC_ID: 5,
    QF_KEY_PREFIX_TRAV_AGE_ID: 6,
    QF_KEY_PREFIX_TRAV_BDAY_ID: 7,
    // Key fuer ID des Containers fuer Reisendendaten im Non-Javascript-Fall
    QF_KEY_TRAVS_CONT_ID: 8,
    // Key fuer ID des Containers fuer Reisendendaten im Javascript-Fall
    QF_KEY_TRAVS_JS_CONT_ID: 9,
    // Key fuer Praefix fuer die IDs der Reisendenzeilen
    QF_KEY_PREFIX_TRAV_ROWS: 10,
    // Key fuer Schalter, ob bei Kindern und Kleinkindern das Alterfeld eingeblendet werden soll
    QF_KEY_SHOW_AGE_FIELD_FOR_CHILDREN: 11,

    // gibt an, ob es sich um den Quickfinder im Webclient handelt 
    // (andernfalls handelt es sich um den Standalone-QF im www.bahn.de-Content)
    qfWebclient: false,

    // Merkliste fuer die bereits initialisierten Reiter/Tabs.
    // Die Values sind die Tabnamen, wie sie auch in der URL verwendet werden ("bahn", "hotel", ...)
    qfTabInits: [],

    // Preissuche-Abfahrtszeit-Slider
    slider: null,
    
    // Initialize quickfinder
    init: function() {
        var qf = document.getElementById( 'quickfinder' );
        if (qf) {
            // feststellen, um welchen QF es sich handelt (Webclient oder Standalone/Content)
            var qfWec = jQuery('#qf-wec').val();
            if (qfWec && qfWec.length > 0) {
                BAHN_QF.qfWebclient = true;
            }
    
            // allgemeine Kalenderkonfigurationen
            qfInitCalendars();
            
            // Datums- und Uhrzeitfelder mit Default-Werten befuellen 
            // (VOR Registrierung der Datepickers, da diese offenbar Initialwerte einfuellen)
            // (wg. gemeinsamem Code alle Felder zusammen in einer Methode)
            BAHN_QF.qfInitDateAndTime();
          
            // Type-ahead-Funktionalitaet fuer alle Start-/Ziel-Felder
            // (wg. gemeinsamem Code alle Felder zusammen in einer Methode)
            BAHN_QF.qfInitTypeAhead();

            // 1. Tab oeffnen, falls noetig und diesen initialisieren
            BAHN_QF.qfTabSetFocus();
            // wenn QF offen sein soll, dann geoeffneten Tab noch initialisieren 
            // (falls dieser bereits ueber den HTML-Code geoeffnet wurde und nicht ueber qfTabSetFocus())
            var openTab = jQuery('#quickfinder ul.tablist li.active a').attr('rel');
            if (openTab && openTab.length > 0) {
                BAHN_QF.qfInitActiveTab(openTab);
            }
                
            // Reiternavigation per JS ermoeglichen
            jQuery('#quickfinder ul.tablist a').click(BAHN_QF.qfTabSetFocus);
            
            // Keyboard Events im QF handeln
            jQuery(qf).keydown( BAHN_QF.qfKeydown ).bind( 'focusin', BAHN_QF.qfKeydown ).bind( 'focusout', BAHN_QF.qfKeydown );
            // fuer die versch. Brwoser auch die "old school"-Varianten fuer Event-Handling
            if (qf.addEventListener) {
                qf.addEventListener('focus', BAHN_QF.qfKeydown, true); // true => handler fuer ev-capture-phase (false => fuer ev-bubbling-phase)
                qf.addEventListener('blur', BAHN_QF.qfKeydown, true);
            }
            // MS IE
            if (qf.attachEvent) {
                qf.attachEvent('focus', BAHN_QF.qfKeydown);
                qf.attachEvent('blur', BAHN_QF.qfKeydown);
                qf.attachEvent('keydown', BAHN_QF.qfKeydown);
            }
            
            // Schliessen-Icons
            jQuery('#quickfinder a.closeButton').click(BAHN_QF.qfClose);
        }

        // Fix z-index bug in IE6
        if (jQuery(qf).bgiframe) {
            jQuery(qf).bgiframe();
            jQuery('div.qf-number-desc').bgiframe();
        }
    },
    
    // Liefert eine gleichverteilte Zufallszahl aus dem Intervall [min;max] (inkl. beider Randwerte).
    // Quelle: http://aktuell.de.selfhtml.org/artikel/javascript/zufallszahlen/
    qfRandomNumber: function(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    },

    // Diese Funktion entscheidet, ob bei Aufruf der Auskunft zwecks Verbindungssuche
    // der Parameter mitgesendet werden soll, der die Verfuegbarkeitspruefung anstoesst.
    qfCheckSendInitialAvail: function() {
        // konfigurierter Prozentsatz von Anfragen, bei denen die Verfuegbarkeitspruefung durchgefuehrt werden soll
        var likelihood = jQuery('#qf-auskunft-initialavail-likelihood').val();
        // konfigurierten Wert anpassen, falls noetig
        if (!likelihood || likelihood < 0) {
            likelihood = 0;
        } 
        else if (likelihood > 100) {
            likelihood = 100;
        }

        // Zufallszahl aus [1,100] wuerfeln (simuliert randNum-te Anfrage)
        var randNum = BAHN_QF.qfRandomNumber(1, 100);
    
        if (likelihood > 0 && randNum <= likelihood) {
            // Hidden Field "initialAvail" im Tab Bahn enablen/senden
            jQuery('#qf-bahn-initialavail').removeAttr('disabled');
        }
        else {
            // Hidden Field "initialAvail" im Tab Bahn disablen/nicht senden
            jQuery('#qf-bahn-initialavail').attr('disabled', 'disabled');
        }
        
        //alert(" likelihood = " + likelihood + "\n randNum = " + randNum + "\n send = " + (randNum <= likelihood));        

        return true;
    },
    
    qfOnSubmitTabBahn: function() {
        BAHN_QF.qfCheckSendInitialAvail();
        // kein Verhindern des Submit
        return true; 
    },
    
    // initialisiert den anzuzeigenden Tab, falls noch nicht geschehen
    qfInitActiveTab: function(sActiveTab) {
        // Tab wurde bereits initialisiert
        if (BAHN_QF.qfIsTabInitialized(sActiveTab))
            return;

        // Tab initialisieren
        if ("bahn" === sActiveTab) {
            BAHN_QF.qfInitTabBahn();
        }
        else if ("hotel" === sActiveTab) {
            BAHN_QF.qfInitTabHotel();
        }
        else if ("mietwagen" === sActiveTab
                || "mwagent" === sActiveTab
                || "mweuropcar" === sActiveTab) {
            BAHN_QF.qfInitTabMietwagen();
        }
        else if ("mobil" === sActiveTab
                || "vtv" === sActiveTab
                || "vtvmwagent" === sActiveTab
                || "vtvmweuropcar" === sActiveTab) {
            BAHN_QF.qfInitTabMobil();
        } 
        else if ("preissuche" == sActiveTab) {
            BAHN_QF.qfInitTabPreissuche();
        }
        // else if ("reisende" === sActiveTab) {} // fuer diesen Tab ist nichts zu tun
        
        // Tab als initialisiert markieren
        BAHN_QF.qfTabInits.push(sActiveTab);
    },

    qfInitTabBahn: function() {
        // Kalender
        BAHN_QF.qfInitDatePicker('0', 'qf-departure-date', 'date', 1);
        BAHN_QF.qfInitDatePicker('1', 'qf-return-date', 'returnDate');
        
        // Uhrzeit
        BAHN_QF.qfInitTimeField('qf-time');
        BAHN_QF.qfInitTimeField('qf-return-time');
        
        // Radiobuttons "einfache/Hin-+Rueckfahrt" initialisieren
        var tripTypeBahn = new BAHN_QF.QfTripType('qf_form_bahn',      'qf-departure-date',            'qf-return-date',            'qf-return-time',            'qf-trip-type-single',            'qf-trip-type-return');
        jQuery('#quickfinder #qf_form_bahn p.trip-type input').change(tripTypeBahn.handleTripTypeChanged).click(tripTypeBahn.handleTripTypeChanged);
        
        var params = {};

        // Reiseprofil-Selectbox befuellen und anzeigen
        params[BAHN_QF.QF_REISEPROFIL_SELECTBOX_ID] = 'qf-rprofil-select';
        params[BAHN_QF.QF_REISEPROFIL_FAST_BOOK_MODE_ID] = 'qf-rprofil-fastbm';
        params[BAHN_QF.QF_REISEPROFIL_PREFIX_KLASSE_RADIO_ID] = 'qf-class-';
        params[BAHN_QF.QF_REISEPROFIL_CHANGED_EVENT] = 'qfBahnReiseprofilChangedEvent';
        params[BAHN_QF.QF_REISEPROFIL_FAST_BOOK_MODE_MARKER] = 'qf-rp-marker-fastbooking';
        new BAHN_QF.QfReiseprofilUpdater(params);
        
        // Strecken-Auswahl-Layer initialisieren
        new BAHN_QF.QfStreckePicker('qf-strecken-bahn',    'qf-departure-point',         'qf-via1-point',         'qf-via2-point',         'qf-destination-point');
        
        // Automatismen fuer Reisenden-Felder
        params = {};
        params[BAHN_QF.QF_REISEPROFIL_CHANGED_EVENT] = 'qfBahnReiseprofilChangedEvent';
        // IDs der Reisende-Anzahl-Selectboxen
        params[BAHN_QF.QF_KEY_ADULTS_ID] = 'qf-adult-number';
        params[BAHN_QF.QF_KEY_CHILDREN_ID] = 'qf-children-number';
        params[BAHN_QF.QF_KEY_INFANTS_ID] = 'qf-infant-number';
        // Praefixe fuer die IDs der Inputfelder in den Reisendenzeilen
        params[BAHN_QF.QF_KEY_PREFIX_TRAV_TYPE_ID] = 'qf-trav-type-';
        params[BAHN_QF.QF_KEY_PREFIX_TRAV_BC_ID] = 'qf-trav-bc-';
        params[BAHN_QF.QF_KEY_PREFIX_TRAV_AGE_ID] = 'qf-trav-age-';
        params[BAHN_QF.QF_KEY_PREFIX_TRAV_BDAY_ID] = 'qf-trav-bday-';
        // ID des Containers fuer Reisendendaten im Non-Javascript-Fall
        params[BAHN_QF.QF_KEY_TRAVS_CONT_ID] = 'qf-travs';
        // ID des Containers fuer Reisendendaten im Javascript-Fall
        params[BAHN_QF.QF_KEY_TRAVS_JS_CONT_ID] = 'qf-travs-js';
        // Praefix fuer die IDs der Reisendenzeilen
        params[BAHN_QF.QF_KEY_PREFIX_TRAV_ROWS] = 'qf-travrow-';
        params[BAHN_QF.QF_KEY_SHOW_AGE_FIELD_FOR_CHILDREN] = false;
        new BAHN_QF.QfReisendeUpdater(params);
		new BAHN_QF.QfBahnCardSelectionUpdater(params);
    },

    qfInitTabHotel: function() {
        // wenn Tab-Inhalt das <form> fuer hotel.de ist (und nicht der Link zu HRS (bei Fiku (KMU)))
        if (!jQuery('div.qf-hotel-hrs').get(0)) {
            // Kalender
            if (BAHN_QF.qfWebclient === true) {
                // im Webclient-QF andere Feldnamen ...
                BAHN_QF.qfInitDatePicker('6', 'qf-hotel-arrival-date', 'REQ0JourneyDate', '7', 1);
                BAHN_QF.qfInitDatePicker('7', 'qf-hotel-departure-date', 'REQ1JourneyDate');
            }
            else {
                // ... als im Standalone-QF
                BAHN_QF.qfInitDatePicker('6', 'qf-hotel-arrival-date', 'hotel_anreise', '7', 1);
                BAHN_QF.qfInitDatePicker('7', 'qf-hotel-departure-date', 'hotel_abreise');
            }
        }
    },
    
    qfInitTabPreissuche: function() {
        // das Eingabeformular wird nur unter bestimmten Bedingungen angezeigt,
        // andernfalls eine Fehlermeldung
        BAHN_QF.checkPreissuchePreconditions();
        
        // Kalender
        if (BAHN_QF.qfWebclient === true) {
            // im Webclient-QF andere Feldnamen ...
            BAHN_QF.qfInitDatePicker('8', 'qf-preissuche-departure-date', 'ps.date', '9', 1);
            BAHN_QF.qfInitDatePicker('9', 'qf-preissuche-return-date', 'ps.returnDate');
        } else {  
            // ... als im Standalone-QF
            // Kalender
            BAHN_QF.qfInitDatePicker('8', 'qf-preissuche-departure-date', 'date', '9', 1);
            BAHN_QF.qfInitDatePicker('9', 'qf-preissuche-return-date', 'returnDate');
        }

        // Uhrzeit-Slider
        slider = new de.bahn.webgets.Slider();
        slider.createTimeSlider("sucheSliderHinfahrt");
		slider.createTimeSlider("sucheSliderRueckfahrt");

        // Radiobuttons einf./Hin+Rueckfahrt        
        var tripTypePreissuche = new BAHN_QF.QfTripType('qf_form_preissuche','qf-preissuche-departure-date', 'qf-preissuche-return-date', 'qf-preissuche-return-time', 'qf-preissuche-trip-type-single', 'qf-preissuche-trip-type-return');                                                                                                
        jQuery('#qf_form_preissuche p.trip-type input').change(tripTypePreissuche.handleTripTypeChanged).click(tripTypePreissuche.handleTripTypeChanged);
        // Hin-+Rueckfahrt vorselektieren
        jQuery('#qf-preissuche-trip-type-return').click();
        
        // Reiseprofil-Selectbox befuellen und anzeigen
        var params = {};
        params[BAHN_QF.QF_REISEPROFIL_SELECTBOX_ID] = 'qf-preissuche-rprofil-select';
        params[BAHN_QF.QF_REISEPROFIL_FAST_BOOK_MODE_ID] = 'qf-preissuche-rprofil-fastbm';
        params[BAHN_QF.QF_REISEPROFIL_PREFIX_KLASSE_RADIO_ID] = 'qf-preissuche-class-';
        params[BAHN_QF.QF_REISEPROFIL_CHANGED_EVENT] = 'qfPsReiseprofilChangedEvent';
        params[BAHN_QF.QF_REISEPROFIL_FAST_BOOK_MODE_MARKER] = 'qf-preissuche-rp-marker-fastbooking';
        new BAHN_QF.QfReiseprofilUpdater(params);

        // Automatismen fuer Reisenden-Felder im Preissuche-Reiter
        params = {};
        params[BAHN_QF.QF_REISEPROFIL_CHANGED_EVENT] = 'qfPsReiseprofilChangedEvent';
        // IDs der Reisende-Anzahl-Selectboxen
        params[BAHN_QF.QF_KEY_ADULTS_ID] = 'preissuche-qf-adult-number';
        params[BAHN_QF.QF_KEY_CHILDREN_ID] = 'preissuche-qf-children-number';
        params[BAHN_QF.QF_KEY_INFANTS_ID] = 'preissuche-qf-infant-number';
        // Praefixe fuer die IDs der Inputfelder in den Reisendenzeilen
        params[BAHN_QF.QF_KEY_PREFIX_TRAV_TYPE_ID] = 'preissuche-qf-trav-type-';
        params[BAHN_QF.QF_KEY_PREFIX_TRAV_BC_ID] = 'preissuche-qf-trav-bc-';
        // kein Non-JS-Fall beim Preissuche-Reiter
        // ID des Containers fuer Reisendendaten im Javascript-Fall
        params[BAHN_QF.QF_KEY_TRAVS_JS_CONT_ID] = 'preissuche-qf-travs-js';
        // Praefix fuer die IDs der Reisendenzeilen
        params[BAHN_QF.QF_KEY_PREFIX_TRAV_ROWS] = 'preissuche-qf-travrow-';
        params[BAHN_QF.QF_KEY_SHOW_AGE_FIELD_FOR_CHILDREN] = false;
        new BAHN_QF.QfReisendeUpdater(params);

        // Captcha-Abschnitt erst einblenden, wenn Kunde in ein Feld klickt
        jQuery('#qf-preissucheContainer :input.loadpscaptcha')
                .bind('focus', BAHN_QF.qfInitPreissucheCaptcha)
                .bind('click', BAHN_QF.qfInitPreissucheCaptcha);
    },
    
    qfInitTabMietwagen: function() {
        if (jQuery("#qf-mietwagen-rental-date").length > 0) {
        	// Kalender fuer Mietwagen-Agent
        	BAHN_QF.qfInitDatePicker('4', 'qf-mietwagen-rental-date', 'REQ0JourneyDate', '5', 1);
        	BAHN_QF.qfInitDatePicker('5', 'qf-mietwagen-return-date', 'REQ1JourneyDate');
        
        	// Uhrzeit
        	BAHN_QF.qfInitTimeField('qf-mietwagen-rental-time');
        	BAHN_QF.qfInitTimeField('qf-mietwagen-return-time');
        } else {
			// Kalender fuer Mietwagen Europcar
        	BAHN_QF.qfInitDatePicker('4', 'qf-mietwagen-anmietdatum', 'qf-mietwagen-anmietdatum', '5', 1);
        	BAHN_QF.qfInitDatePicker('5', 'qf-mietwagen-rueckgabedatum', 'qf-mietwagen-rueckgabedatum');
        	
        	BAHN_QF.qfInitTimeField('qf-mietwagen-anmietzeit');
        	BAHN_QF.qfInitTimeField('qf-mietwagen-rueckgabezeit');
			
            // bei Auswahl Anmietstation diese als Rueckgabestation uebernehmen
			jQuery("#qf-mietwagen-anmietstation").bind("change", BAHN_QF.handleMietwagenAnmietstationChanged);
        }        
    },
	
	handleMietwagenAnmietstationChanged: function() {
		// Anpassung der Rueckgabestation an Anmietstation
		jQuery("#qf-mietwagen-rueckgabestation").val(jQuery("#qf-mietwagen-anmietstation").val());
	},

    qfInitTabMobil: function() {
        // Tab Mobil (falls Tab Mobilitaet (statt VTV) und damit die folgenden Felder existieren)
        if (jQuery('#qf_form_mobil').get(0)) {
            // Kalender/Uhrzeit für Mobilcheck
            BAHN_QF.qfInitDatePicker('2', 'qf-mobil-departure-date', 'date');
            BAHN_QF.qfInitTimeField('qf-mobil-time');
            // Kalender/Uhrzeit für Umweltcheck
            BAHN_QF.qfInitDatePicker('3', 'qf-uwmobil-departure-date', 'date');
            BAHN_QF.qfInitTimeField('qf-uwmobil-time');
        } else if (jQuery('#qf_form_mobil_vtv').get(0)) {
            // Kalender            
            if (BAHN_QF.qfWebclient === true) {
                // im Webclient-QF andere Feldnamen ...            
                BAHN_QF.qfInitDatePicker('2', 'qf-mobil-vtv-departure-date', 'vtv.date', '3');
                BAHN_QF.qfInitDatePicker('3', 'qf-mobil-vtv-return-date', 'vtv.returnDate');
            } else {
                // ... als im Standalone-QF
                BAHN_QF.qfInitDatePicker('2', 'qf-mobil-vtv-departure-date', 'date', '3');
                BAHN_QF.qfInitDatePicker('3', 'qf-mobil-vtv-return-date',    'returnDate');
            }
            
            // Uhrzeit
            BAHN_QF.qfInitTimeField('qf-mobil-vtv-time');
            BAHN_QF.qfInitTimeField('qf-mobil-vtv-return-time');
            
            // Radiobuttons einf./Hin+Rueckfahrt        
            var tripTypeMobilVtv = new BAHN_QF.QfTripType('qf_form_mobil_vtv', 'qf-mobil-vtv-departure-date',  'qf-mobil-vtv-return-date',  'qf-mobil-vtv-return-time',  'qf-mobil-vtv-trip-type-single',  'qf-mobil-vtv-trip-type-return');
            jQuery('#qf_form_mobil_vtv p.trip-type input').change(tripTypeMobilVtv.handleTripTypeChanged).click(tripTypeMobilVtv.handleTripTypeChanged);
            // "einfache Fahrt" vorselektieren
            jQuery('#qf-mobil-vtv-trip-type-single').click();

            // Der Mietwagen-Reiter verschiebt sich in den VTV-Reiter (= Mobil-Reiter fuer Privatkunden), 
            // wenn der Preissuche-Reiter angezeigt wird.
            // Wenn dann der VTV-Reiter aktiviert wird, muss auch der Mietwagen-Anteil noch mitinitialisiert werden.
            if (jQuery('#tabMietwagenInTabVtv').get(0) && !BAHN_QF.qfIsTabInitialized("mietwagen")) {
                BAHN_QF.qfInitTabMietwagen();   
            }
        }
        
        // Strecken-Auswahl-Layer im Mobil-Reiter initialisieren
        new BAHN_QF.QfStreckePicker('qf-strecken-mobil',   'qf-mobil-departure-point',   'qf-mobil-via1-point',   'qf-mobil-via2-point',   'qf-mobil-destination-point');
        new BAHN_QF.QfStreckePicker('qf-strecken-uwmobil', 'qf-uwmobil-departure-point', 'qf-uwmobil-via1-point', 'qf-uwmobil-via2-point', 'qf-uwmobil-destination-point');
        
        // Automatismen fuer Reisenden-Felder im Vtv-Reiter
        var params = {};
        // keine Reiseprofilbox im VTV-Reiter
        // IDs der Reisende-Anzahl-Selectboxen
        params[BAHN_QF.QF_KEY_ADULTS_ID] = 'vtv-qf-adult-number';
        params[BAHN_QF.QF_KEY_CHILDREN_ID] = 'vtv-qf-children-number';
        params[BAHN_QF.QF_KEY_INFANTS_ID] = 'vtv-qf-infant-number';
        // Praefixe fuer die IDs der Inputfelder in den Reisendenzeilen
        params[BAHN_QF.QF_KEY_PREFIX_TRAV_TYPE_ID] = 'vtv-qf-trav-type-';
        params[BAHN_QF.QF_KEY_PREFIX_TRAV_BC_ID] = 'vtv-qf-trav-bc-';
        params[BAHN_QF.QF_KEY_PREFIX_TRAV_AGE_ID] = 'vtv-qf-trav-age-';
        params[BAHN_QF.QF_KEY_PREFIX_TRAV_BDAY_ID] = 'vtv-qf-trav-bday-';
        // ID des Containers fuer Reisendendaten im Non-Javascript-Fall
        params[BAHN_QF.QF_KEY_TRAVS_CONT_ID] = 'vtv-qf-travs';
        // ID des Containers fuer Reisendendaten im Javascript-Fall
        params[BAHN_QF.QF_KEY_TRAVS_JS_CONT_ID] = 'vtv-qf-travs-js';
        // Praefix fuer die IDs der Reisendenzeilen
        params[BAHN_QF.QF_KEY_PREFIX_TRAV_ROWS] = 'vtv-qf-travrow-';
        params[BAHN_QF.QF_KEY_SHOW_AGE_FIELD_FOR_CHILDREN] = true;
        new BAHN_QF.QfReisendeUpdater(params);		
        new BAHN_QF.QfBahnCardSelectionUpdater(params);
    },
    
    // prueft, ob der uebergebene Tab bereits initialisiert wurde
    qfIsTabInitialized: function(sActiveTab) {
        for (var i = 0; i < BAHN_QF.qfTabInits.length; i++) {        
            if (BAHN_QF.qfTabInits[i] === sActiveTab) {
                return true; 
            }
        }
        return false;
    },
    
    qfInitDatePicker: function(datefieldIdNo, datefieldId, datefieldName, returnDateCalNummer, returnDateOffset) {
        // Kalender initialisieren
        qfInitCalendar(datefieldIdNo, datefieldId, datefieldName, returnDateCalNummer, returnDateOffset);

        // Container suchen, der die Kalender-Elemente enthaelt
        var calContainer = jQuery('#' + datefieldId).closest('.qf-cal');
        var refId = "callink" + datefieldIdNo;
        
        // Actions
        if (BAHN_QF.qfWebclient === true) {
            // Im Webclient-QF anderer HTML-Code fuer die Blaetterbuttons ... 
            calContainer.find('img.cal_button_later').click(function(){calman.shiftDate(refId, 1);});
            calContainer.find('img.cal_button_earlier').click(function(){calman.shiftDate(refId, -1);});
        }
        else {
            // ... als im Standalone-QF.
            // Datum formatieren lassen (+ Wochentagskuerzel), indem im Datumsfeld vorbelegtes Datum 1x rauf- und wieder runter geblaettert wird
            calContainer.find('a.next')
                    .click(function(){calman.shiftDate(refId, 1);})
                    .click(); 
            calContainer.find('a.prev')
                    .click(function(){calman.shiftDate(refId, -1);})
                    .click();
        }
        calContainer.find('a.calendar').click(function(){return calman.toggleDisplay(refId);});
    },

    qfInitTimeField: function(timeFieldId) {
        // Container suchen, der die Zeit-Elemente enthaelt
        var timefield = document.getElementById(timeFieldId);
        var timeContainer = jQuery(timefield).closest('.qf-time');
        
        // Actions
        if (BAHN_QF.qfWebclient === true) {
            // Im Webclient-QF anderer HTML-Code fuer die Blaetterbuttons ... 
            timeContainer.find('img.time_button_later').click(function(){BAHN_QF.qfShiftTime(timefield, 1);});
            timeContainer.find('img.time_button_earlier').click(function(){BAHN_QF.qfShiftTime(timefield, -1);});
        }
        else {
            // ... als im Standalone-QF.
            timeContainer.find('a.next').click(function(){BAHN_QF.qfShiftTime(timefield, 1);}); 
            timeContainer.find('a.prev').click(function(){BAHN_QF.qfShiftTime(timefield, -1);});
        }
    },

    // Uhrzeit erhoehen/erniedrigen. timefield enthaelt das zugehoerige Textfield
    qfShiftTime: function(timefield, offset) {
        if (timefield == null)
            return false;
        var ctime = timefield.value;
        var hour, minute;
        if (ctime.match(/^([0-2]?\d):?(\d\d)?$/) == null)
            return false;
        var tmpH = RegExp.$1 * 1;
        var tmpM = RegExp.$2 * 1;
        if ((ctime.indexOf(":") < 0) && (ctime < 1000)) {
            if (ctime <= 24) {
                hour = ctime * 1;
                minute = 0;
            } else {
                hour = Math.floor(ctime / 100);
                minute = ctime % 100;
            }
        } else {
            hour = tmpH;
            minute = tmpM;
            if ((hour > 24) || (minute > 59))
                return;
        }
        if (minute != 0) {
            minute = 0;
            if (offset < 0)
                offset += 1;
        }
        hour += offset;
        hour %= 24;
        if (hour < 0)
            hour += 24;
        if (hour < 10)
            ctime = "0" + hour + ":00";
        else
            ctime = hour + ":00";
        timefield.value = ctime;
    },

    // type-ahead- (und all-type-) Funktionalitaet fuer die Von-/Nach-Felder des Quickfinders
    qfInitTypeAhead: function() {
        // Text fuer Loctype bei Historycookieanzeige
        qfSetHistCookieTypeStr();
    
        var historyCookieName = jQuery('#qf-bhf-typeahead-history-cookiename').val();
        var minChars = jQuery('#qf-bhf-typeahead-minchar').val();
        var delay = jQuery('#qf-bhf-typeahead-delay').val();
        var reqUrl = jQuery('#qf-bhf-typeahead-requrl').val();
        var reqAllTypeUrl = jQuery('#qf-bhf-typeahead-reqalltypeurl').val();
		
		// Erweiterte alltype-Suche
		var minCharAlltype = jQuery('#qf-bhf-typeahead-minchar-alltype').val();
		var reqAllTypeExtendedUrl = jQuery('#qf-bhf-typeahead-reqalltype-extended-url').val();

        // Tab Bahn (falls Tab Bahn und damit die folgenden Felder existieren)
        if (jQuery('#qf_form_bahn').get(0)) {
            if (BAHN_QF.qfWebclient === true) {
	            new FSuggest({
	                loc: "qf-departure-point", type: "S", minChar: minChars, cookiename: historyCookieName, 
					requestURL: reqUrl, stopDelay: delay, requestType: "js", alltypeMoreWord: false  });
	            new FSuggest({
	                loc: "qf-destination-point", type: "Z", minChar: minChars, cookiename: historyCookieName, 
					requestURL: reqUrl, stopDelay: delay, requestType: "js", alltypeMoreWord: false });				
            } else {
				// QF-Standalone
				new FSuggest({
				    loc: "qf-departure-point", type: "S", minChar: minChars, cookiename: historyCookieName, 
					requestURL: reqAllTypeExtendedUrl, stopDelay: delay, requestType: "js", 
					minCharAlltype: minCharAlltype, alltypeMoreWord: true });
				new FSuggest({
				    loc: "qf-destination-point", type: "Z", minChar: minChars, cookiename: historyCookieName, 
					requestURL: reqAllTypeExtendedUrl, stopDelay: delay, requestType: "js", 
					minCharAlltype: minCharAlltype, alltypeMoreWord: true });                
            }			
                
            // Waechter fuer Triple-Id-Felder
            jQuery("#qf-departure-point").blur(BAHN_QF.checkTripleId);
            jQuery("#qf-destination-point").blur(BAHN_QF.checkTripleId);
        }

        // Tab Mobil (falls Tab Mobilitaet (statt VTV) und damit die folgenden Felder existieren)
        if (jQuery('#qf_form_mobil').get(0)) {
            new FSuggest({
                loc: "qf-uwmobil-departure-point", type: "S",
                minChar: minChars, cookiename: historyCookieName, requestURL: reqUrl, 
				stopDelay: delay, requestType: "js", alltypeMoreWord: false });
            new FSuggest({
                loc: "qf-uwmobil-destination-point", type:"Z",
                minChar: minChars, cookiename: historyCookieName, requestURL: reqUrl, 
				stopDelay: delay, requestType: "js", alltypeMoreWord: false });
            new FSuggest({
                loc: "qf-mobil-departure-point", type: "S",
                minChar: minChars, cookiename: historyCookieName, requestURL: reqUrl, 
				stopDelay: delay, requestType: "js", alltypeMoreWord: false });
            new FSuggest({
                loc: "qf-mobil-destination-point", type: "Z",
                minChar: minChars, cookiename: historyCookieName, requestURL: reqUrl, 
				stopDelay: delay, requestType: "js", alltypeMoreWord: false });
                
            // Waechter fuer Triple-Id-Felder
            jQuery("#qf-mobil-departure-point").blur(BAHN_QF.checkTripleId);
            jQuery("#qf-mobil-destination-point").blur(BAHN_QF.checkTripleId);
            jQuery("#qf-uwmobil-departure-point").blur(BAHN_QF.checkTripleId);
            jQuery("#qf-uwmobil-destination-point").blur(BAHN_QF.checkTripleId);
        }
        
        // Tab Mobil VTV (falls Tab Mobil VTV und damit die folgenden Felder existieren)
        if (jQuery('#qf_form_mobil_vtv').get(0)) {
			if (BAHN_QF.qfWebclient === true) {
	            new FSuggest({
	                loc: "qf-mobil-vtv-departure-point", type: "S", minChar: minChars, cookiename: historyCookieName, 
					requestURL: reqAllTypeUrl, stopDelay: delay, requestType: "js", alltypeMoreWord: false });
	            new FSuggest({
	                loc: "qf-mobil-vtv-destination-point", type: "Z", minChar: minChars, cookiename: historyCookieName, 
					requestURL: reqAllTypeUrl, stopDelay: delay, requestType: "js", alltypeMoreWord: false });
			} else {
                new FSuggest({
                    loc: "qf-mobil-vtv-departure-point", type: "S", minChar: minChars, cookiename: historyCookieName, 
                    requestURL: reqAllTypeExtendedUrl, stopDelay: delay, requestType: "js", 
					minCharAlltype: minCharAlltype, alltypeMoreWord: true });
                new FSuggest({
                    loc: "qf-mobil-vtv-destination-point", type: "Z", minChar: minChars, cookiename: historyCookieName, 
                    requestURL: reqAllTypeExtendedUrl, stopDelay: delay, requestType: "js", 
					minCharAlltype: minCharAlltype, alltypeMoreWord: true });				
			}
			

                
            // Waechter fuer Triple-Id-Felder
            jQuery("#qf-mobil-vtv-departure-point").blur(BAHN_QF.checkTripleId);
            jQuery("#qf-mobil-vtv-destination-point").blur(BAHN_QF.checkTripleId);
        }
        
        // Tab Preissuche(falls Tab Preissuche und damit die folgenden Felder existieren)
        if (jQuery('#qf_form_preissuche').get(0)) {
            // nur deutsche Bahnhoefe, kein History-Cookie nutzen
            // "type" wird innerhalb des Namens des Triple-ID-Feldes verwendet. 
            // Dieser muss sich von dem im Reiter Bahn unterscheiden, da die FSuggest-Lib faelschlicherweise nach Element 
            // mit diesem Feldnamen im ganzen Dokument und nicht nur im aktuellen <form> sucht! 
            new FSuggest({
                loc: "qf-preissuche-departure-point", type: "S",
                minChar: minChars, requestURL: reqUrl, stopDelay: delay, requestType: "js", locType: 1, filter: "germany", type: "S1"});
            new FSuggest({
                loc: "qf-preissuche-destination-point", type: "Z",
                minChar: minChars, requestURL: reqUrl, stopDelay: delay, requestType: "js", locType: 1, filter: "germany", type: "Z1"});
                
            // Waechter fuer Triple-Id-Felder
            jQuery("#qf-preissuche-departure-point").blur(BAHN_QF.checkTripleId);
            jQuery("#qf-preissuche-destination-point").blur(BAHN_QF.checkTripleId);
        }
    },
    
    // Befuellt fuer ein Button-Tag das zugehoerige Hidden Field mit uebergebenem Namen und Value.
    // Wird benoetigt, da vor allem der IE(6) <input>-Buttons und <button>-Buttons 
    // gemeinsam in einem Formular nicht korrekt verarbeitet. 
    // Beim Senden ueber Input wird auch Name/Value des Buttons gesendet.
    // Dies fuehrt auf Tab Bahn und Hotel dazu, dass auch die "Weitere Optionen"-Buttons 
    // immer die Sofort-Suchen-Flags senden und sofort eine Suche angestossen wird,
    // was bei diesen Buttons jedoch nicht gewuenscht ist.
    // Daher das Suchen-Flag hier "onclick" in ein Hidden Field fuellen. 
    qfSetSearchFlag: function(fieldId, fieldName, fieldValue) {
        jQuery('#' + fieldId)
                .attr('name', fieldName) // auch Namen erst hier setzen, noch nicht im HTML!
                .val(fieldValue);
    },

    // ergaenzt falls noetig fuer Datumsteile (z. B. Tag oder Monat, als Zahl!) eine fuehrende Null
    // und liefert Ergebnis als String zurueck
    qfDatePartStr: function(datePart) {
        return (datePart < 10) ? ("0" + datePart) : datePart;
    },

    // Datums- und Uhrzeitfelder mit Default-Werten befuellen
    qfInitDateAndTime: function() {
        // im QF im Webclient braucht nicht vorbelegt zu werden, nur im Standalone-QF fuer Content
        if (BAHN_QF.qfWebclient === true)
            return;
    
        // aktuelles Datum und Zeit
        var now = new Date();
        var sNowDate = BAHN_QF.qfDatePartStr(now.getDate())
                + "." + BAHN_QF.qfDatePartStr(now.getMonth() + 1)
                + "." + now.getFullYear();
        var sNowTime = BAHN_QF.qfDatePartStr(now.getHours())
                + ":" + BAHN_QF.qfDatePartStr(now.getMinutes());

        // morgen
        var tomorrow = new Date();
        tomorrow.setDate(tomorrow.getDate() + 1);
        var sTomDate = BAHN_QF.qfDatePartStr(tomorrow.getDate())
                + "." + BAHN_QF.qfDatePartStr(tomorrow.getMonth() + 1)
                + "." + tomorrow.getFullYear();
        
        // uebermorgen
        var plus2days = new Date();
        plus2days.setDate(plus2days.getDate() + 2);
        var sPlus2Date = BAHN_QF.qfDatePartStr(plus2days.getDate())
                + "." + BAHN_QF.qfDatePartStr(plus2days.getMonth() + 1)
                + "." + plus2days.getFullYear();

        // heute in 3 Tagen
        var plus3days = new Date();
        plus3days.setDate(plus3days.getDate() + 3);
        var sPlus3Date = BAHN_QF.qfDatePartStr(plus3days.getDate())
                + "." + BAHN_QF.qfDatePartStr(plus3days.getMonth() + 1)
                + "." + plus3days.getFullYear();
        
        // heute in 4 Tagen
        var plus4days = new Date();
        plus4days.setDate(plus4days.getDate() + 4);
        var sPlus4Date = BAHN_QF.qfDatePartStr(plus4days.getDate())
                + "." + BAHN_QF.qfDatePartStr(plus4days.getMonth() + 1)
                + "." + plus4days.getFullYear();
               
        // Felder nur vorbelegen, wenn noch nichts drinsteht! (Fuer Standalone-Quickfinder)
        // (andernfalls wurden sie z. B. aus dem Buchungsprofil des Kunden bereits befuellt)
        var field;

        // Tab Bahn
        if (jQuery('#qf_form_bahn').length > 0) {
            field = jQuery('#qf-departure-date');
            if (field.val().length == 0) {
                field.val(sNowDate);
            }
            field = jQuery('#qf-time');
            if (field.val().length == 0) {
                field.val(sNowTime);
            }
            field = jQuery('#qf-return-date');
            if (field.val().length == 0) {
                field.val(sNowDate);
            }
            field = jQuery('#qf-return-time');
            if (field.val().length == 0) {
                field.val("12:00");
            }
        }

        // Tab Hotel
        if (jQuery('#qf_form_hotel').length > 0 && field.length > 0) { 
            field = jQuery('#qf-hotel-arrival-date');
            if (field.val().length == 0) {
                field.val(sNowDate);
            }
            field = jQuery('#qf-hotel-departure-date');
            if (field.val().length == 0) {
                field.val(sTomDate);
            }
        }

        // Tab Mietwagen
        if (jQuery('#qf_form_mietwagen').length > 0) {
            BAHN_QF.qfInitDateAndTimeTabMietwagen(sTomDate, "10:00", sPlus2Date, "10:00");
        }

        // Tab Mobilitaet
        if (jQuery('#qf_form_mobil').length > 0) {
            field = jQuery('#qf-mobil-departure-date');
            if (field.val().length == 0) {
                field.val(sNowDate);
            }
            field = jQuery('#qf-mobil-time');
            if (field.val().length == 0) {
                field.val(sNowTime);
            }
            field = jQuery('#qf-uwmobil-departure-date');
            if (field.val().length == 0) {
                field.val(sNowDate);
            }
            field = jQuery('#qf-uwmobil-time');
            if (field.val().length == 0) {
                field.val(sNowTime);
            }
        }
        
        // Tab VTV
        if (jQuery('#qf_form_mobil_vtv').length > 0) {
            field = jQuery('#qf-mobil-vtv-departure-date');
            if (field.val().length == 0) {
                field.val(sNowDate);
            }
            field = jQuery('#qf-mobil-vtv-time');
            if (field.val().length == 0) {
                field.val(sNowTime);
            }
            field = jQuery('#qf-mobil-vtv-return-date');
            if (field.val().length == 0) {
                field.val(sNowDate);
            }
            field = jQuery('#qf-mobil-vtv-return-time');
            if (field.val().length == 0) {
                field.val("12:00");
            }
            
            // Tab Mietwagen (falls Tab Mietwagen im VTV-Reiter angezeigt wird)
            if (jQuery('#tabMietwagenInTabVtv').length > 0) {
                BAHN_QF.qfInitDateAndTimeTabMietwagen(sTomDate, "10:00", sPlus2Date, "10:00");
            }
        }
        
        // Tab Preissuche
        if (jQuery('#qf_form_preissuche').length > 0) {
            field = jQuery('#qf-preissuche-departure-date');
            if (field.val().length == 0) {
                field.val(sPlus3Date);
            }
            field = jQuery('#qf-preissuche-return-date');
            if (field.val().length == 0) {
                field.val(sPlus4Date);
            }
        }
    },
    
    qfInitDateAndTimeTabMietwagen: function(rentalDate, rentalTime, returnDate, returnTime) {
        var field = jQuery('#qf-mietwagen-rental-date');
        if (field.length > 0) {
            // Tab Mietwagen-Agent
            if (field.val().length == 0) {
                field.val(rentalDate);
            }
            field = jQuery('#qf-mietwagen-rental-time');
            if (field.val().length == 0) {
                field.val(rentalTime);
            }
            field = jQuery('#qf-mietwagen-return-date');
            if (field.val().length == 0) {
                field.val(returnDate);
            }
            field = jQuery('#qf-mietwagen-return-time');
            if (field.val().length == 0) {
                field.val(returnTime);
            }        	
        } else {
        	// Tab Mietwagen Europcar
        	field = jQuery('#qf-mietwagen-anmietdatum');
            if (field.val().length == 0) {
                field.val(rentalDate);
            }
            field = jQuery('#qf-mietwagen-anmietzeit');
            if (field.val().length == 0) {
                field.val(rentalTime);
            }
            field = jQuery('#qf-mietwagen-rueckgabedatum');
            if (field.val().length == 0) {
                field.val(returnDate);
            }
            field = jQuery('#qf-mietwagen-rueckgabezeit');
            if (field.val().length == 0) {
                field.val(returnTime);
            }        	
        }
    },

    qfInitPreissucheCaptcha: function() {
        // Captcha-Abschnitt einblenden
        jQuery('#qf-ps-captcha').removeClass("hidden").show();

        // neues Captcha laden
        new BAHN_QF.QfCaptcha().create();
          
        // diese Funktion soll nur 1x ausgefuehrt werden, daher wieder abhaengen
        jQuery('#qf-preissucheContainer :input')
                .unbind('focus', BAHN_QF.qfInitPreissucheCaptcha)
                .unbind('click', BAHN_QF.qfInitPreissucheCaptcha);
    },

    /**
     * Initialisiert und behandelt Events der Reiseprofil-Selectbox
     */
    QfReiseprofilUpdater: function(params) {
        var rpBoxId = params[BAHN_QF.QF_REISEPROFIL_SELECTBOX_ID]; // ID der Reiseprofil-Selectbox
        var fastBookModeId = params[BAHN_QF.QF_REISEPROFIL_FAST_BOOK_MODE_ID]; // ID des Inputfeldes fuer Schnellbuchung
        var prefixKlasseRadioId = params[BAHN_QF.QF_REISEPROFIL_PREFIX_KLASSE_RADIO_ID]; // Praefix fuer ID der Klasse-Radiobuttons
        var reiseprofilChangedEvent = params[BAHN_QF.QF_REISEPROFIL_CHANGED_EVENT]; // Name des Events, das bei Auswahl eines anderes Profils aus der Selectbox versendet wird
        var fastBookModeMarker = params[BAHN_QF.QF_REISEPROFIL_FAST_BOOK_MODE_MARKER]; // ID des Feldes, in dem der Markierungstext fuer Schnellbuchungsprofile steht

        var reiseprofile;

        /**
         * Befuellt die Selectbox mit den RProfilnamen aus dem Cookie und macht die Box sichtbar.
         */
        var initReiseprofile = function() {
            var sCn = jQuery('#qf-cookiename-mrp').val();
            if (sCn) {
                var rpCookie = jQuery.cookie(sCn);
                var rpBox = document.getElementById(rpBoxId);
                // nur wenn Cookie und die Reiseprofil-Selectbox existiert
                // (die Box wird fuer Firmenkunden nicht angezeigt!)
                if (rpCookie && rpBox) {
                    // Reiseprofil-Selectbox einblenden
                    jQuery('#quickfinder p.reiseprofile').show();

                    // Cookie auslesen
                    var rpCookieHandler = new BAHN_QF.QfReiseprofilCookieHandler();
                    rpCookieHandler.setCookieName(sCn);
                    rpCookieHandler.parseCookie();
                    reiseprofile = rpCookieHandler.getReiseprofile();

                    // sicherheitshalber alle ausser der 1. Option (=Hinweistext) loeschen
                    rpBox.options.length = 1;

                    // Reiseprofile als Optionen hinzufuegen
                    // Text: RP-Name + Markierung fuer Schnellbuchung (Marker-Text kommt aus Hidden Field),
                    // Value: Index des RProfils (im Cookie) (der wird auch an die Auskunft uebertragen!)
                    var optionTextMarker = jQuery('#' + fastBookModeMarker).val();
                    for (var i = 0; i < reiseprofile.length; i++) {
                        var rp = reiseprofile[i];
                        if (rp) {
                            var newOption = document.createElement('option');
                            newOption.value = rp.index;
                            var optionText = rp.name;
                            if (rp.schnellbuchung && rp.schnellbuchung > 0) {
                                optionText += " " + optionTextMarker;
                            }
                            newOption.text = optionText;
                            rpBox.options.add(newOption); // nur diese Schreibweise klappt im IE6
                        }
                    }

                    // Hidden Field "Schnellbuchungsmodus" enablen
                    jQuery('#' + fastBookModeId).removeAttr('disabled');

                    BAHN.updateBuffer();
                }
            }
        }

        /**
         * ausgewaehltes Reiseprofil aendert sich => Event mit RProfildaten versenden
         */
        var reiseprofilChanged = function(event) {
            var oTarget = BAHN.getTarget(event);

            var rprofil; 
            // wenn Reiseprofile ex. und wenn ein Reiseprofil mit Index >= 0 ausgewaehlt
            if (reiseprofile && reiseprofile.length > 0 && oTarget.value >= 0) {
                // Index des RProfil-Objekts und Index des RProfils in der internen Liste
                // muessen nicht unbedingt identisch sein, daher diese Schleife
                for (var i = 0; i < reiseprofile.length; i++) {
                    rprofil = reiseprofile[i];
                    if (rprofil.index === oTarget.value) {
                        break;
                    }
                }
            }
            // keine Profile oder Profil wieder deselektiert (oTarget.value < 0)
            // (RP-Index=-1 entspricht dem Hinweistext in der Selectbox)
            else {
                rprofil = new BAHN_QF.QfReiseprofil();
                // Default-Reiseprofil mit 1 Erw., keinen Kindern und keinen sonst. Daten vorbelegen
                 rprofil.setDefaults();            
            }
            
            // RProfil zum Index gefunden
            if (rprofil) {
                // Wert fuer Schnellbuchungsmodus setzen
                jQuery('#' + fastBookModeId).val(rprofil.schnellbuchung);
                // Wert fuer Klasse setzen
                if (rprofil.klasse == 1) {
                    jQuery('#' + prefixKlasseRadioId.concat("1")).attr('checked', 'checked');
                    jQuery('#' + prefixKlasseRadioId.concat("2")).removeAttr('checked');
                }
                else {
                    jQuery('#' + prefixKlasseRadioId.concat("2")).attr('checked', 'checked');
                    jQuery('#' + prefixKlasseRadioId.concat("1")).removeAttr('checked');
                }
                // spez. Event versenden und damit zusammen auch die Daten des aktuell ausgewaehlten Reiseprofils
                jQuery('*').trigger(reiseprofilChangedEvent, [rprofil]);
            }
        }

        // Konstruktor

        // RProfilBox aus Cookie befuellen und anzeigen
        initReiseprofile();
        // auf Change-Events der RProfilBox reagieren
        jQuery('#' + rpBoxId).change(reiseprofilChanged);
    },

    /**
     * Diese Klasse behandelt die Events fuer und von den Reisenden-Anzahl-Selectboxen
     * und fuer die Reisendenzeilen (Typ + BC-Ermaessigung).
     * Reiseprofil ausgewaehlt:
     *  - Anpassen der angezeigten Anzahlen und max. Optionen der Reisenden-Anzahl-Selectboxen
     *  - Anzeigen der Daten der Reisenden in den Reisendenzeilen (z. B. Typ und Ermaessigung (=BC))
     * Reisendenanzahl geaendert:
     *  - max. auswaehlbaren Optionen der anderen Selectboxen veraendern sich, wenn die Auswahl einer Selectbox geaendert wird
     *  - entsprechend der Auswahl der Reisendenanzahl und -Typen werden Zeilen fuer die BC-Ermaessigung hinzu-/weggeblendet
     *
     * Parameter ist ein Array von HTML-Element-IDs bzw. ID-Praefixes.
     * Als Keys fuer Befuellung des Arrays muessen die BAHN_QF.QF_XYZ-Konstanten verwendet werden!
     */
    QfReisendeUpdater: function(params) {
        // Extensions fuer die IDs der Tag-/Monat-/Jahr-Einzelfelder fuer Geburtstag
        var TRAV_BDAY_DAY_EXT = "_day";
        var TRAV_BDAY_MONTH_EXT = "_month";
        var TRAV_BDAY_YEAR_EXT = "_year";

        // Selectboxen
        var adultsBox = document.getElementById(params[BAHN_QF.QF_KEY_ADULTS_ID]);
        var childrenBox = document.getElementById(params[BAHN_QF.QF_KEY_CHILDREN_ID]);
        var infantsBox = document.getElementById(params[BAHN_QF.QF_KEY_INFANTS_ID]);

        /**
         * Aktualisiert die Optionen der (Anzahl-)Selectbox, wobei die maximale Anzahl von Reisenden durch maxNumber bestimmt wird.
         */
        var updateMaxNumOptions = function(selectBox, maxNumber) {
            if (selectBox == null)
                return;

            var optionsSize = selectBox.options.length;
            var selIndex = selectBox.selectedIndex;

            var firstOptVal = parseInt((optionsSize > 0 ? selectBox.options[0].value : 0));
            var lastOptVal = parseInt((optionsSize > 0 ? selectBox.options[optionsSize - 1].value : 0));

            if (lastOptVal < maxNumber) {
                // stocke aktuelle Optionen auf die neue max. zulaessige Anzahl von Reisenden auf
                var option;
                for (var i = eval(lastOptVal + 1); i <= maxNumber; i++) {
                    option = document.createElement('option');
                    option.text = i;
                    option.value = i;
                    selectBox.options.add(option);
                }
            }
            else {
                // beschneide die Anzahl der Optionen auf die neue max. Anzahl
                selectBox.options.length = maxNumber + (firstOptVal == 0 ? 1 : 0);
            }

            // bisher selektierten Wert wieder selektieren (oder 1. Option, falls nicht moeglich)
            doSelectIndex(selectBox, selIndex);
        }
        
        /** 
         * Selektiert die Option mit dem uebergebenen Index, falls vorhanden.
         * Andernfalls wird die 1. Option selektiert.
         */
        var doSelectIndex = function(selectBox, selIndex) {
            if (selectBox == null)
                return;
        
            if (selIndex >= selectBox.options.length) {
                // falls der aktuell selektierte Index ausserhalb der Menge der Optionen liegt,
                // wird einfach die erste Option selektiert
                selectBox.selectedIndex = 0;
            }
            else {
                selectBox.selectedIndex = selIndex;
            }
        }

        /**
         * Aktualisiert die max. Anzahl von Optionen aller Anzahl-Selectboxen anhand der aktuell ausgewaehlten Werte
         * und div. Sonderregeln, so dass eine Gesamtzahl von BAHN_QF.QF_MAX_REISENDE nicht ueberschritten wird.
         */
        var updateNumberOfReisende = function(event) {
            var oTarget = BAHN.getTarget(event);

            // aktuell selektierte Werte der Selectboxen (zum spaeteren Rumrechnen unbedingt Ints draus machen!)
            var numAdults = parseInt(params[BAHN_QF.QF_KEY_ADULTS_ID].length > 0 && adultsBox != null ? adultsBox.value : 0);
            var numChildren = parseInt(params[BAHN_QF.QF_KEY_CHILDREN_ID].length > 0 && childrenBox != null ? childrenBox.value : 0);
            var numInfants = parseInt(params[BAHN_QF.QF_KEY_INFANTS_ID].length > 0 && infantsBox != null ? infantsBox.value : 0);

            // aktuell selektiert Indexe der Optionen
            // merken, da die aktuelle Auswahl aufgrund von Sonderregeln evtl. angepasst werden muss
            var idxAdults = parseInt(params[BAHN_QF.QF_KEY_ADULTS_ID].length > 0 && adultsBox != null ? adultsBox.selectedIndex : 0);
            var idxChildren = parseInt(params[BAHN_QF.QF_KEY_CHILDREN_ID].length > 0 && childrenBox != null ? childrenBox.selectedIndex : 0);
            var idxInfants = parseInt(params[BAHN_QF.QF_KEY_INFANTS_ID].length > 0 && infantsBox != null ? infantsBox.selectedIndex : 0);

            // Sonderregeln bei 0 Erwachsenen
            if (numAdults == 0) {
                // keine Kleinkinder moeglich
                numInfants = 0;
                if (infantsBox != null) {
                    idxInfants = 0; // Annahme: infantsBox beginnt immer mit Option 0 (Erw. beginnt bei Fiku mit 1!)
                }
                // hoechstens 1 alleinreisendes Kind moeglich
                if (numChildren > 1) {
                    numChildren = 1;
                    if (childrenBox != null) {
                        idxChildren = 1; // Annahme: childrenBox beginnt immer mit Option 0 (Erw. beginnt bei Fiku mit 1!)
                    }
                }
            }

            // Auswahl korrigieren, falls (jetzt) 0 Reisende ausgewaehlt sind
            var numTravs = numAdults + numChildren + numInfants;
            if (numTravs == 0) {
                // Erwachsene wurden gerade genullt
                if (oTarget.id === params[BAHN_QF.QF_KEY_ADULTS_ID]) {
                    if (childrenBox != null) {
                        // 1 Kind auswaehlen
                        idxChildren = 1;
                        numChildren = 1;
                    }
                // Kinder wurden gerade genullt
                } else if (oTarget.id === params[BAHN_QF.QF_KEY_CHILDREN_ID]) {
                    if (adultsBox != null) {
                        // 1 Erw. auswaehlen
                        idxAdults = 1;
                        numAdults = 1;
                    }
                }
            }

            // Sonderregeln bei 0 Erwachsenen
            if (numAdults == 0) {
                // moegliche Optionen der Selectboxen neu bestimmen
                updateMaxNumOptions(adultsBox, BAHN_QF.QF_MAX_REISENDE - numChildren - numInfants);
                updateMaxNumOptions(childrenBox, numChildren);
                updateMaxNumOptions(infantsBox, numInfants);
            }
            // mind. 1 Erwachsener
            else {
                // Max. Anzahl der Erwachsenen haengt von gewaehlter Anzahl Kinder und Kleinkinder ab.
                // Analog fuer die max. Anzahl Kinder und Kleinkinder.
                updateMaxNumOptions(adultsBox, BAHN_QF.QF_MAX_REISENDE - numChildren - numInfants);
                updateMaxNumOptions(childrenBox, BAHN_QF.QF_MAX_REISENDE - numAdults - numInfants);
                updateMaxNumOptions(infantsBox, BAHN_QF.QF_MAX_REISENDE - numAdults - numChildren);
            }
            
            // Richtige Option selektieren.
            // Entweder ist das die, die der Kunde aktuell ausgewaehlt hatte oder sie wurde aufgrund obiger Sonderregeln angepasst.
            // Der selectedIndex der Selectbox konnte aber oben noch nicht sofort angepasst werden,
            // da soviele Optionen evtl. (noch) nicht nur Verfuegung stehen.
            // Dies ist erst jetzt nach Anpassung der max. Optionen (updateMaxNumOptions()) der Fall.
            // Bsp: Waehle erst 5 Erw, danach 0 Erw.
            doSelectIndex(adultsBox, idxAdults);
            doSelectIndex(childrenBox, idxChildren);
            doSelectIndex(infantsBox, idxInfants);
        }

        /**
         * Liefert ein Array von QfReisender-Objekten mit den Daten der aktuell sichtbaren Reisendenzeilen
         */
        var getCurrentReisende = function() {
            var reisende = [];
            // iteriere ueber alle Reisendenrows ...
            for (var i = 1; i <= BAHN_QF.QF_MAX_REISENDE; i++) {
                // ... die sichtbar sind
                if (jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_ROWS] + i).is(':visible')) {
                    // Reisender-Objekt mit den Daten der Felder der aktuellen Zeile fuellen
                    var r = new BAHN_QF.QfReisender();
                    r.typ = jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_TYPE_ID] + i).val();
                    r.bahncard = jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_BC_ID] + i).val();
                    r.geburtsdatum = jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_BDAY_ID] + i).val();
                    r.alter = jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_AGE_ID] + i).val();
                    r.geb_tag = jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_BDAY_ID] + i + TRAV_BDAY_DAY_EXT).val();
                    r.geb_monat = jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_BDAY_ID] + i + TRAV_BDAY_MONTH_EXT).val();
                    r.geb_jahr = jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_BDAY_ID] + i + TRAV_BDAY_YEAR_EXT).val();
                    // Alter wird immer neu berechnet beim naechsten Anzeigen
                    reisende.push(r);
                }
            }
            return reisende;
        }

        /**
         * Aktualisiert anhand der Auswahl in den Anzahl-Selectboxen eine interne Liste von Reisenden (Model),
         * es werden leere neue Reisende des gewuenschten Typs hinzugefuegt oder die letzten jeden Typs entfernt.
         * Anhand dieser internen Reisendenliste wird die Oberflaeche aktualisiert.
         */
        var updateNumberOfReisendeRows = function() {
            // Daten der aktuell sichtbaren Reisendenzeilen ermitteln
            var reisende = getCurrentReisende();
            // aktuelle Reisende in typ-spez. Arrays aufteilen
            var adults = [];
            var children = [];
            var infants = [];
            for (var i = 0; i < reisende.length; i++) {
                var r = reisende[i];
                if (BAHN_QF.QF_REISENDER_TYP_ERW === r.typ) {
                    adults.push(r);
                } else if (BAHN_QF.QF_REISENDER_TYP_FKIND === r.typ || BAHN_QF.QF_REISENDER_TYP_AKIND === r.typ) {
                    children.push(r);
                } else if (BAHN_QF.QF_REISENDER_TYP_KKIND === r.typ) {
                    infants.push(r);
                }
            }

            // wg. Sonderregeln bei der Anzahl der Reisenden hat sich evtl. nicht nur die vom Kunden betaetigte Selectbox geaendert,
            // sondern auch die anderen Selectboxen - daher muss fuer alle Reisendentypen ueberprueft werden, ob Anpassungen noetig sind!
            var newReisende = [];
            var offset = 0;

            // Erwachsene
            if (adultsBox != null) {
                offset = adults.length - adultsBox.value;
                if (offset >= 0){
                    adults.length = adults.length - offset;
                } else {
                    newReisende = createNewReisende(Math.abs(offset), BAHN_QF.QF_REISENDER_TYP_ERW);
                    adults = adults.concat(newReisende);
                }
            }

            // Kinder
            if (childrenBox != null) {
                offset = children.length - childrenBox.value;
                if (offset >= 0){
                    children.length = children.length - offset;
                } else {
                    newReisende = createNewReisende(Math.abs(offset), BAHN_QF.QF_REISENDER_TYP_FKIND);
                    children = children.concat(newReisende);
                }
            }

            // Kleinkinder
            if (infantsBox != null) {
                offset = infants.length - infantsBox.value;
                if (offset >= 0){
                    infants.length = infants.length - offset;
                } else {
                    newReisende = createNewReisende(Math.abs(offset), BAHN_QF.QF_REISENDER_TYP_KKIND);
                    infants = infants.concat(newReisende);
                }
            }
            
            var resultReisende = [];
            resultReisende = resultReisende.concat(adults);
            resultReisende = resultReisende.concat(children);
            resultReisende = resultReisende.concat(infants);

            // Zeilen aktualisieren und de-/aktivieren
            updateReisendeRows(resultReisende);
        }
        

        /**
         * Erzeugt 'anzahl' Stueck neue Reisende vom uebergebenen Reisenden-Typ (eine der BAHN_QF.QF_REISENDER_TYP_XXX-Konstanten).
         */
        var createNewReisende = function(anzahl, typ) {
            var result = [];
            for (var j = 0; j < anzahl; j++){
                // neuer Reisender
                var r = new BAHN_QF.QfReisender();
                r.typ = typ;

                result.push(r);
            }
            return result;
        }

        /**
         * Fuellt die Daten der Reisenden in die ersten reisende.length Zeilen.
         * Die restlichen Zeilen werden ausgeblendet und ihre Input-Felder (inkl. Selectboxen etc.) disabled.
         *
         * Die Liste von Reisenden muss so aufgebaut sein,
         * dass jeweils alle Reisenden eines Typs direkt aufeinander folgen
         * und nicht Reisende anderen Typs dazwischenstehen.
         */
        var updateReisendeRows = function(reisende) {
            // Index fuer korrekte Nummerierung innerhalb der Reisendentypen im Label fuer die BC-Selectbox
            var labelIdx = 1;
            // Merker zum Feststellen von Typwechsel beim Iterieren
            var prevType = "";

            for (var i = 0; i < reisende.length; i++) {
                var r = reisende[i];
                // Indexes der Reisendenzeilen starten mit 1
                var j = eval(i + 1);
                // Reisendendaten in die Felder der i-ten Reisendenzeile fuellen
                jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_TYPE_ID] + j).val(r.typ);
                jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_BC_ID] + j).val(r.bahncard);
                jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_BDAY_ID] + j).val(r.geburtsdatum);
                jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_BDAY_ID] + j + TRAV_BDAY_DAY_EXT).val(r.geb_tag);
                jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_BDAY_ID] + j + TRAV_BDAY_MONTH_EXT).val(r.geb_monat);
                jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_BDAY_ID] + j + TRAV_BDAY_YEAR_EXT).val(r.geb_jahr);
                // Alter des Reisenden am Hinreisetag (immer ueber Getter abholen)
                jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_AGE_ID] + j).val(r.getAlter());

                // Nummerierung im Reisendenlabel bei neuem Typ zuruecksetzen
                if (prevType !== r.typ) {
                    labelIdx = 1;
                    prevType = r.typ;
                }
                // Labeltexte fuer die Reisendentypen kommen aus Hidden Fields "#<prefix-typ>name-<Typkuerzel>"
                var lblText = labelIdx + ". " + jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_TYPE_ID] + 'name-' + r.typ).val();
                // Label fuer die BahnCard-Selectbox dem Reisendentyp anpassen
                jQuery("label[for='" + params[BAHN_QF.QF_KEY_PREFIX_TRAV_BC_ID] + j + "']").text(lblText);

                // Wenn gewuenscht, fuer Kinder und Kleinkinder das Alterfeld einblenden
                if (params[BAHN_QF.QF_KEY_SHOW_AGE_FIELD_FOR_CHILDREN]) {
                    if (BAHN_QF.QF_REISENDER_TYP_ERW == r.typ) {
                        jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_AGE_ID] + j).hide(); 
                    } else {
                        jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_AGE_ID] + j).show().removeClass('hide')
                                // Trick: damit beim Einblenden der Default-Text befuellt wird
                                .blur();
                    }
                }
                
                labelIdx++;
            }

            // die Zeilen mit den Reisendendaten sichtbar und aktiv schalten
            // (die uebrigen ausblenden/disablen)
            setReisendeRowsEnabled(1, reisende.length);

            BAHN.updateBuffer();
        }

        /**
         * Aktiviert die Reisendenzeilen im uebergebenen Intervall,
         * d. h. die Inputfelder werden enabled und die Zeile eingeblendet.
         * Die uebrigen werden deaktiviert (Inputfelder werden deaktiviert und Zeile ausgeblendet).
         * Der Startindex muss >= 1 sein wg. der Feld-/Zeilennamen.
         */
        var setReisendeRowsEnabled = function(startIdx, endIdx)  {
            // iteriere ueber alle Reisendenrows
            for (var i = 1; i <= BAHN_QF.QF_MAX_REISENDE; i++){
                // falls im uebergebenen Intervall
                if (startIdx <= i && i <= endIdx) {
                    // Inputfelder (input, select, ...) aktivieren
                    jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_ROWS] + i + ' :input').removeAttr('disabled');
                    // Zeile einblenden
                    jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_ROWS] + i).show()
                            .removeClass('hide'); // auch diese Class (aus HTML-Code) entfernen
                } else {
                    // Inputfelder (input, select, ...) deaktivieren
                    jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_ROWS] + i + ' :input').attr('disabled', 'disabled');
                    // Zeile ausblenden
                    jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_ROWS] + i).hide();
                }
            }
        }

        /**
         * Wenn eine der Reisenden-Anzahl-Selectboxen geaendert wurde,
         * die Selectboxen anpassen und auch die Reisendenzeilen.
         */
        var anzahlReisendeChanged = function(event) {
            // max. Optionen der Selectboxen anpassen
            updateNumberOfReisende(event);
            // Reisendenzeilen ein-/ausblenden
            updateNumberOfReisendeRows();
            // Info-Layers fuer Kind/Kleinkind schliessen
            jQuery('#quickfinder div.qf-number-desc a.closeButton').click();
        }

        /**
         * Wenn in der RProfil-Selectbox ein anderes Reiseprofil ausgewaehlt wurde,
         * die Daten des Reiseprofils im QF anzeigen
         * (Reisenden-Anzahl-Selectboxen und Reisendenzeilen).
         */
        var reiseprofilChanged = function(event, rprofil) {
            // Falls Kunde erst an den Anzahl-Selectboxen geaendert hat und dann ein Reiseprofil auswaehlt,
            // koennen ueber das Reiseprofil Reisendenanzahlen kommen, die momentan nicht in der Selectbox als Option enthalten sind 
            // (wg. automatisierter Beschraenkung auf max 5 Reisende insgesamt).
            // Daher hier jede Box auf die max. moegl. Reisendenzahl aufblaehen,
            // das wird danach in updateNumberOfReisende() wieder korrigiert.
            updateMaxNumOptions(adultsBox, BAHN_QF.QF_MAX_REISENDE);
            updateMaxNumOptions(childrenBox, BAHN_QF.QF_MAX_REISENDE);
            updateMaxNumOptions(infantsBox, BAHN_QF.QF_MAX_REISENDE);
            // neue Werte auswaehlen
            BAHN_QF.qfSelectByValue(adultsBox, rprofil.adults.length);
            BAHN_QF.qfSelectByValue(childrenBox, rprofil.children.length);
            BAHN_QF.qfSelectByValue(infantsBox, rprofil.infants.length);
            // max. moegliche Optionen der Selectboxen anhand der neuen Reisendenzahlen neu festlegen
            updateNumberOfReisende(event);

            // Reihenfolge der Reisendenzeilen festlegen: Erwachsene, Kinder, Kleinkinder
            var reisende = [];
            reisende = reisende.concat(rprofil.adults);
            reisende = reisende.concat(rprofil.children);
            reisende = reisende.concat(rprofil.infants);
            // Ermaessigungszeilen mit den Daten der Reisenden aus dem RProfil fuellen
            updateReisendeRows(reisende);
        }

        // Konstruktor 
        // (fuer Standalone-QF immer ausfuehren, fuer WEC-QF nur, wenn JS-Bereich sichtbar ist (d. h. *_dyn.css wurde nicht zurueckgerollt))
        if (BAHN_QF.qfWebclient === false || BAHNCONSISTENCY.isJsLoadedSuccessful) {
            // Input-Felder des Non-JS-Bereichs deaktivieren
            jQuery('#' +  params[BAHN_QF.QF_KEY_TRAVS_CONT_ID]  + ' :input').attr('disabled', 'disabled');
            // Input-Felder des JS-Bereichs aktivieren
            jQuery('#' +  params[BAHN_QF.QF_KEY_TRAVS_JS_CONT_ID]  + ' :input').removeAttr('disabled');
    
            // Reisende-Anzahl-Selectboxen aktivieren und Aenderungen belauschen.
            jQuery('#' + params[BAHN_QF.QF_KEY_ADULTS_ID])
                    .removeAttr('disabled')
                    .change(anzahlReisendeChanged);
            jQuery('#' + params[BAHN_QF.QF_KEY_CHILDREN_ID])
                    .removeAttr('disabled')
                    .change(anzahlReisendeChanged);
            jQuery('#' + params[BAHN_QF.QF_KEY_INFANTS_ID])
                    .removeAttr('disabled')
                    .change(anzahlReisendeChanged);
    
            // Die Erwachsenen-Selectbox ist im JS-Fall immer vorhanden,
            // sie stoesst stellvertretend fuer alle Selectboxen die Behandlung des Reiseprofil-Changed-Events an,
            // sofern im Konstruktor ein Reiseprofil-Changed-Event benannt wurde.
            if (params[BAHN_QF.QF_REISEPROFIL_CHANGED_EVENT] != null) {
                // /nur fuer das Reiseprofil-Changed-Event der Reiter-eigenen Selectbox anmelden) 
                jQuery('#' + params[BAHN_QF.QF_KEY_ADULTS_ID]).bind(params[BAHN_QF.QF_REISEPROFIL_CHANGED_EVENT], reiseprofilChanged);
            }
    
            // In HTML sind Werte fuer Anzahl Erwachsene/Kinder/Kleinkinder in den Selectboxen vorselektiert.
            // Daran die max. Optionen der Selectboxen sowie die Reisendenzeilen intial anpassen.
            anzahlReisendeChanged();
        }

        BAHN.updateBuffer();
    },
	
	QfBahnCardSelectionUpdater: function(params) {	     
        // Selectboxen fuer Anzahl der Reisenden
        var adultsBox = document.getElementById(params[BAHN_QF.QF_KEY_ADULTS_ID]);
        var childrenBox = document.getElementById(params[BAHN_QF.QF_KEY_CHILDREN_ID]);
        var infantsBox = document.getElementById(params[BAHN_QF.QF_KEY_INFANTS_ID]);
		
		// Selectboxen für Reisende mit BahnCard-Auswahl	
		var bcBoxList = [];		
		for (var i = 0; i < BAHN_QF.QF_MAX_REISENDE; i++) {
          bcBoxList[i] = document.getElementById(params[BAHN_QF.QF_KEY_PREFIX_TRAV_BC_ID] + (i+1));    
        } 
		
		/** Member fuer die BahnCardMix-Matrix (2D-Array) */
		var qfBahnCardMixMatrix = [];		
		/** Member fuer die BahnCardType-Option-Values */
		var qfBahnCardValues = [];
		
        /**
         * Liest die BC-Mix Matrix, als String, aus dem Hidden-field value,
         * wandelt es in ein 2D-Array um und weist es der Variable 'qfBahnCardMixMatrix' zu.
         */		
        var initBahnCardMixMatrix = function(){
            var bcMixArray = [];            
            var stringValue = document.getElementById("qf-bc-matrix").value;
            var splittedStringArray = stringValue.split(';');
            
            // 2D-Array, muss weiter gesplittet werden
            for (var i = 0; i < splittedStringArray.length; i++) {
                bcMixArray[i] = splittedStringArray[i].split(',');
            }			
            qfBahnCardMixMatrix = bcMixArray;
        };		
				
        /**
         * Liest die BC Options, als String, aus dem Hidden-field value,
         * wandelt es in ein Array um und weist es der Variable 'qfBahnCardValues' zu.
         */
        var initBahnCardValues = function(){
            var bcValuesArray = [];            
            var stringValue = document.getElementById("qf-bc-options").value;
            var splittedStringOptions = stringValue.split('#');
            
            // 2D-Array, muss weiter gesplittet werden
            for (var i = 0; i < splittedStringOptions.length; i++) {
                bcValuesArray[i] = splittedStringOptions[i].split(';');
            }            
            qfBahnCardValues = bcValuesArray;
        };
		
		/**
		 * Liefert eine Liste der zulaessigen BC-Typen zur Auswahl.
		 * @param {Object} bcIntKey
		 */
        var getAllowedBahnCardTypes = function(bcIntKey){
            var retList = [];
            var counter = 0;			
            if (typeof(bcIntKey) != 'undefined') {
                for (var i = 0; i < qfBahnCardMixMatrix.length; i++) {
                    if (qfBahnCardMixMatrix[bcIntKey][i] == "1") {
                        retList[counter] = i;
                        counter++;
                    }
                }
            }
            return retList;
        }
		 
		/**
		 * Prueft ob die in der Liste aufgefuehrten BahnCard-Typen
		 * zum BahnCard-Typ "bcKey" erlaubt sind.
		 * @param {Object} bcKey 
		 * @param {Object} allowedBcTypList zu pruefende Liste mit BahnCardTypen.
		 */
        var isAllowed = function(bcKey, allowedBcTypList){
            for (var i = 0; i < allowedBcTypList.length; i++) {
                if (allowedBcTypList[i] == bcKey) {
                    return true;
                }
            }
            return false;
        }	 
		 
        /**
         * Fuegt der Selectbox die erlaubten BahnCard-Typen hinzu.
         * @param {Object} selectbox - die zu befuellende Selectbox
         * @param {Object} selection - selektierter Bahncard Typ
         */        
        var updateSelectboxOption = function(selectbox, selection){
            // loescht die bisherigen Optionen in der Selectbox
			selectbox.length = 0;

            // Ermitteln der erlaubten BC-Typen, unter beruecksichtigung
			// der Selektion
			var allowedBcTypes = getAllowedBahnCardTypes(selection);
            for (var i = 0; i < qfBahnCardValues.length; i++) {
                var bcKey = qfBahnCardValues[i][0];
                
                if (isAllowed(bcKey, allowedBcTypes)) {
                    var _entry = qfBahnCardValues[i];
                    
                    option = document.createElement('option');
                    option.value = _entry[0];
                    option.text = _entry[1];
                    selectbox.options.add(option);
                }
            }
        }
		
		/**
		 * Liefert die Anzahl der Reisenden (Erw. + Kind + Kleinkind)
		 */
		var getAnzahlReisende = function() {
		    var anzahlErw = parseInt(adultsBox.value);
			// FiKu hat keine Auswahl für Kinder/Kleinkinder
		    var anzahlKinder = parseInt(childrenBox != null ? childrenBox.value : 0);
			// bei VTV gibt es keine Selectbox Kleinkinder
		    var anzahlKleinkinder = parseInt(infantsBox != null ? infantsBox.value : 0);
		                
		    return (anzahlErw + anzahlKinder + anzahlKleinkinder);              
		}
		
		/**
		 * Ermittelt den selektierten Bahncard-Typ, der dann fuer alle
		 * Selectboxen gilt.
		 * @param {Object} anzahlReisende
		 */
		var getSelectedBahnCardType = function(anzahlReisende) {
			// Wenn Anzahl der Reisenden = 1 ist, dann lade alle BC-Typen
            // ansonsten muss geprueft werden ob fuer einen anderen Reisenden
            // eine Auswahl getroffen wurde   
			if (anzahlReisende == 1) {
				return 0;
			}
            
			// ueberpruefe die auswahl in den sichtbaren selectboxen
			var selectedBcType = 0;						
			for (var i = 0; i < anzahlReisende; i++) {
				var selection = parseInt(bcBoxList[i].value);
				if (selection > selectedBcType) {
				    selectedBcType = selection;	
				}
			}			
			return selectedBcType;
		}
           
        /**
         * Eventhandler für die Selectboxen:
         * Anzahl Erwachsene, Kinder und Kleinkinder
         */   
        var handleAnzahlReisendeChanged = function() {
            handleBahnCardSelectionChanged();
        }
				
        /**
         * Event-Handler fuer BahnCard Selectboxen 
         */
        var handleBahnCardSelectionChanged = function(){                     
            var anzahlReisende = getAnzahlReisende();
            var allowedBcType = getSelectedBahnCardType(anzahlReisende);
            
            // Alle Select-Boxen werden aktualisiert
            // Die Vorauswahl wird nur bei den sichtbaren gesetzt,
			// bei den anderen wird die Auswahl zurueckgesetzt.        
            for (var i = 0; i < BAHN_QF.QF_MAX_REISENDE; i++) {
                var currentSelection = 0;
                if (i < anzahlReisende) {
                    currentSelection = parseInt(bcBoxList[i].value);
                }
                updateSelectboxOption(bcBoxList[i], allowedBcType);
                bcBoxList[i].value = currentSelection + '';
            }			
        }

        // Initialisierung der Matrix-Daten und verfügbaren BahnCard-Option values 
		initBahnCardMixMatrix();
		initBahnCardValues();

		// Event-handler registrieren 
		jQuery('#' + params[BAHN_QF.QF_KEY_ADULTS_ID]).change(handleAnzahlReisendeChanged);
        jQuery('#' + params[BAHN_QF.QF_KEY_CHILDREN_ID]).change(handleAnzahlReisendeChanged);
        jQuery('#' + params[BAHN_QF.QF_KEY_INFANTS_ID]).change(handleAnzahlReisendeChanged);
							
		for (var i = 1; i <= BAHN_QF.QF_MAX_REISENDE; i++) {
		  jQuery('#' + params[BAHN_QF.QF_KEY_PREFIX_TRAV_BC_ID] + i).change(handleBahnCardSelectionChanged);	
		}        						
	},  

    /**
     *  Klasse fuer Quickfinder-Triptype-Funktionalitaet fuer Bahn- und Vtv-Reiter.
     *  Diese kontrolliert das Ein- und Ausblenden des Rueckfahrt-Blocks (Datum und Uhrzeit). 
     */
    QfTripType: function(sReiterFormId, sHinDatumId, sRueckDatumId, sRueckZeitId, sTripTypeSingleId, sTripTypeReturnId) {
        var reiterFormId = sReiterFormId;
        var hinDatumId = sHinDatumId;
        var rueckDatumId = sRueckDatumId;
        var rueckZeitId = sRueckZeitId;
        var tripTypeSingleId = sTripTypeSingleId;
        var tripTypeReturnId = sTripTypeReturnId;
        
        this.handleTripTypeChanged = function(event) {
            // Aktion bei Klick auf Radiobuttons "einfache/Hin-+Rueckfahrt"
            var oTarget = BAHN.getTarget(event);

            // einfache Fahrt aktiviert
            if (oTarget.id === tripTypeSingleId ) {
                // Rueckfahrtabschnitte ausblenden und alle Input-Controls in den Abschnitten disabled setzen
                jQuery('#quickfinder #' + reiterFormId + ' fieldset.depends-trip-type').hide();
                jQuery('#quickfinder #' + reiterFormId + ' fieldset.depends-trip-type :input').attr('disabled', 'disabled');

                jQuery('#quickfinder #' + reiterFormId + ' p.depends-trip-type').hide();
                jQuery('#quickfinder #' + reiterFormId + ' p.depends-trip-type :input').attr('disabled', 'disabled');
                
                // zusaetzliches Feld returntimesel im Hinfahrt-Abschnitt fuer einfache Fahrt enablen
                jQuery('#quickfinder #' + reiterFormId + ' input.depends-trip-type').removeAttr('disabled');
                
                // hwai-Parameter (Standalone )
                jQuery('#quickfinder #' + reiterFormId + ' #qf-mobil-vtv-hwai').val('QUERY!direction=single!');
            }
            
            // Hin- und Rueckfahrt aktiviert
            else if (oTarget.id === tripTypeReturnId) {
                // zusaetzliches Feld returntimesel im Hinfahrt-Abschnitt fuer einfache Fahrt disablen
                jQuery('#quickfinder #' + reiterFormId + ' input.depends-trip-type').attr('disabled', 'disabled');

                // alle Input-Controls in den Abschnitten enabled setzen und Rueckfahrtabschnitte einblenden
                jQuery('#quickfinder #' + reiterFormId + ' fieldset.depends-trip-type :input').removeAttr('disabled');
                jQuery('#quickfinder #' + reiterFormId + ' fieldset.depends-trip-type')
                        .show()
                        .removeClass('hide');

                jQuery('#quickfinder #' + reiterFormId + ' p.depends-trip-type :input').removeAttr('disabled');
                jQuery('#quickfinder #' + reiterFormId + ' p.depends-trip-type')
                        .show()
                        .removeClass('hide');
                
                // hwai-Parameter (Standalone )
                jQuery('#quickfinder #' + reiterFormId + ' #qf-mobil-vtv-hwai').val('QUERY!direction=both!');
                
                // reiterspezifisches 
                if (reiterFormId == "qf_form_preissuche") {
                    // Rueckfahrt-Slider wieder initialisieren
                    // todo die regler stellen sich nicht zurueck, daher auskommentiert:
                    //new BAHN_QF.QfSlider().createTimeSlider("sucheSliderRueckfahrt");
                } else {
                    // uebliche Regel: Rueckfahrdatum = Hinfahrdatum
                    var hDate = jQuery('#' + hinDatumId).val();
                    jQuery('#' + rueckDatumId).val(hDate);
                }

                // Rueckfahrt-Zeit dann auch wieder auf Default
                jQuery('#' + rueckZeitId).val('12:00');
            }
            
            BAHN.updateBuffer(); // Force screen reader buffer update
        }    
    },
       
    /**
     * Diese Klasse stellt die Funktionalitaet fuer das Ein-/Ausblenden eines Layers bereit,
     * in dem die in einem Cookie gespeicherten Strecken angezeigt und eine davon augewaehlt werden kann,
     * um andere Eingabefelder des Quickfinders (Start, Ziel, etc.) mit den Daten der ausgewaehlten Strecke zu befuellen.
     *
     * @param {Object} sImgId - ID des Elements (Icon), unter dem der Layer angezeigt werden soll
     * @param {Object} sStartId - ID des Inputfeldes, in das die Start-Location der gewaehlten Strecke gefuellt werden soll
     * @param {Object} sVia1Id - ID des Inputfeldes, in das die Via1-Location der gewaehlten Strecke gefuellt werden soll
     * @param {Object} sVia2Id - ID des Inputfeldes, in das die Via2-Location der gewaehlten Strecke gefuellt werden soll
     * @param {Object} sZielId - ID des Inputfeldes, in das die Ziel-Location der gewaehlten Strecke gefuellt werden soll
     */
    QfStreckePicker: function(sImgId, sStartId, sVia1Id, sVia2Id, sZielId) {
        var imgId = sImgId;
        var startId = sStartId;
        var via1Id = sVia1Id;
        var via2Id = sVia2Id;
        var zielId = sZielId;

        var strecken;
        var selStrecke;
        
        var initialized = false;

        var layerKeyDown = function(event) {
            var ev = event || window.event;
            var oTarget = BAHN.getTarget(ev);
            var iKey = ev.keyCode;
            var activeListItem = jQuery('#' + imgId + '-layer .active').get(0);

            if (iKey == BAHN.key_down) {
                // falls nachfolgender Link vorhanden, auf diesen den Fokus setzen
                if (jQuery(activeListItem).next().length > 0) {
                    jQuery(activeListItem).removeClass('active');
                    jQuery(activeListItem).next().focus();
                }
            }
            else if (iKey == BAHN.key_up) {
                // falls voriger Link vorhanden, auf diesen den Fokus setzen
                if (jQuery(activeListItem).prev().length > 0) {
                    jQuery(activeListItem).removeClass('active');
                    jQuery(activeListItem).prev().focus();
                }
            }
            else if (iKey == BAHN.key_tab) {
                closeLayer();
            }
            else if (iKey == BAHN.key_return) {
                //alert("LAYERKEYDOWN enter");
            }
        }
        
        var iconKeyDown = function(event) {
            var ev = event || window.event;
            var iKey = ev.keyCode;
            
            if (iKey == BAHN.key_down) {
                jQuery('#' + imgId + '-layer div:first').get(0).focus();
            }                        
        }

        /**
         * Liest das Cookie aus und befuellt mit den Strecken den im HTML bereits vorhandenen <div>-Container.
         * Falls kein Cookie existiert, wird im Layer statt Streckennamen ein Hinweistext angezeigt.
         */
        var createLayer = function() {
            // Strecken-Cookie parsen
            if (!strecken || strecken.length === 0) {
                var mstrCookieHandler = new BAHN_QF.QfStreckenCookieHandler();
                mstrCookieHandler.setCookieName(jQuery('#qf-cookiename-mstr').val());
                mstrCookieHandler.parseCookie();
                strecken = mstrCookieHandler.getStrecken();
            }

            // Layer mit Streckennamen befuellen
            if (strecken && strecken.length > 0) {
                
                /* folgende HTML-Struktur wird aufgebaut:
                    <div name="[Listen-Nr der Strecke (nicht: Index!)]"> [Name der Strecke ] </div>              
                */

                // Layer-div zuerst leeren (enthaelt per Default den Hinweistext, falls Streckencookie fehlt)
                var lyCont = jQuery('#' + imgId + '-layer');
                lyCont.empty();

                for (var i = 0; i < strecken.length; i++) {
                    var strecke = strecken[i];
                    // div-Container mit i als name-Attribut und Name der Strecke als Inhalt
                    var newDiv = document.createElement('div');
                    jQuery(newDiv)
                            .attr('name', i)
                            .text(strecke.name)
                            .focus(focusLink)
                            .click(selectStrecke);
                    lyCont.append(newDiv);
                }
            }
            
            initialized = true;
        }

        var focusLink = function() {
            jQuery(this).addClass('active');
        }

        /**
         * Blendet den Layer in den sichtbaren Bereich ein.
         * Genauer: linke obere Ecke des Layers unter die linke untere Ecke des Icons positionieren.
         * Falls der Layer noch nicht existiert, wird er zuvor erzeugt (Aufbau der Strecken-Auswahlliste aus dem Cookie).
         */
        var openLayer = function() {
            // Layer nur einmal erzeugen
            if (initialized == false) {
                createLayer(); 
            }
            // Layerpostion berechnen
            var imgPos = jQuery('#' + imgId).position();
            var lyPosTop = eval(imgPos.top + jQuery('#' + imgId).outerHeight());
            jQuery('#' + imgId + '-layer')
                    .css('left', imgPos.left)   // sichtbare Pos des Layers
                    .css('top', lyPosTop)       // sichtbare Pos des Layers
                    .keydown(layerKeyDown)      // Tastaturevents behandeln
                    //.blur(closeLayer)           // schliessen beim Verlassen
                    .bgiframe();                // Fix z-index bug in IE6
        }

        /**
         * Handler-Funktion, falls eine Strecke aus dem Layer ausgewaehlt wurde.
         */
        var selectStrecke = function(event) {
            var oTarget = BAHN.getTarget(event);

            // selektierte Strecke bestimmen
            var indexSelStrecke = parseInt(jQuery(oTarget).attr('name'));
            selStrecke = strecken[indexSelStrecke];

            // Streckenorte-Input- und -TripleID-Felder mit Daten den gewaehlten Strecke befuellen
            // bei Start u. Ziel Beobachter fuer Veraenderungen registrieren
            if (startId) {
                jQuery('#' + startId)
                        .val(selStrecke.start ? selStrecke.start.name : '')
                        .blur(observeInputField);
                jQuery('#' + startId + BAHN_QF.TRIPLE_ID_EXT)
                        .val(selStrecke.start ? selStrecke.start.getTripleID() : '');
            }
            if (zielId) {
                jQuery('#' + zielId)
                        .val(selStrecke.ziel ? selStrecke.ziel.name : '')
                        .blur(observeInputField);
                jQuery('#' + zielId + BAHN_QF.TRIPLE_ID_EXT)
                        .val(selStrecke.ziel ? selStrecke.ziel.getTripleID() : '');
            }
            if (via1Id) {
                jQuery('#' + via1Id)
                        .val(selStrecke.via1 ? selStrecke.via1.name : '')
                        .removeAttr('disabled');
                jQuery('#' + via1Id + BAHN_QF.TRIPLE_ID_EXT)
                        .val(selStrecke.via1 ? selStrecke.via1.getTripleID() : '')
                        .removeAttr('disabled');
            }
            if (via2Id) {
                jQuery('#' + via2Id)
                        .val(selStrecke.via2 ? selStrecke.via2.name : '')
                        .removeAttr('disabled');
                jQuery('#' + via2Id + BAHN_QF.TRIPLE_ID_EXT)
                        .val(selStrecke.via2 ? selStrecke.via2.getTripleID() : '')
                        .removeAttr('disabled');
            }

            // Layer ausblenden
            closeLayer();
        }

        /**
         * Handler-Funktion fueuer Verlassen der Start-/Ziel-Felder, falls zuvor eine Strecke ausgewaehlt worden war.
         */
        var observeInputField = function(event) {
            var oTarget = BAHN.getTarget(event);
            if (selStrecke && event.type === 'blur'){
                // pruefen, ob Start o. Ziel veraendert wurden
                if (oTarget.id == startId) {
                    if (selStrecke.start && selStrecke.start.name != oTarget.value) {
                        // Vias entfernen, passen nicht mehr zur geaenderten Strecke
                        deleteVias();
                        // Eingabefeld nicht mehr beobachten
                        jQuery('#' + startId).unbind('blur', observeInputField);
                        // TripleId zum Eingabefeld loeschen: macht BAHN_QF.checkTripleId()
                    }
                } else if (oTarget.id == zielId) {
                    if (selStrecke.ziel && selStrecke.ziel.name != oTarget.value) {
                        deleteVias();
                        jQuery('#' + zielId).unbind('blur', observeInputField);
                        // TripleId zum Eingabefeld loeschen: macht BAHN_QF.checkTripleId()
                    }
                }
            }
        }

        /**
         * Vias leeren und disablen, wenn Start oder Ziel der gewaehlten Strecke veraendert wurden
         */
        var deleteVias = function() {
            if (via1Id) {
                jQuery('#' + via1Id)
                        .val('')
                        .attr('disabled', 'disabled');
                jQuery('#' + via1Id + BAHN_QF.TRIPLE_ID_EXT)
                        .val('')
                        .attr('disabled', 'disabled');
            }
            if (via2Id) {
                jQuery('#' + via2Id)
                        .val('')
                        .attr('disabled', 'disabled');
                jQuery('#' + via2Id + BAHN_QF.TRIPLE_ID_EXT)
                        .val('')
                        .attr('disabled', 'disabled');
            }
        }

        /**
         * Schliesst den Layer, indem er aus dem sichtbaren Bereich herausgeschoben wird,
         * (indem man die Styleangaben, die zum Einblenden des Layers ergaenzt wurden, wieder entfernt).
         * Siehe auch openLayer()
         */
        var closeLayer = function() {
            // Schliessen
            jQuery('#' + imgId + '-layer').removeAttr('style');
            // aktiven Link zuruecksetzen
            jQuery('#' + imgId + '-layer .active').removeClass('active');
            // Fokus zurueck auf Favoriten-Image-Link setzen
            jQuery('#' + imgId).parent().get(0).focus();
        }

        // Konstruktor

        // falls es Strecken-Icon gibt
        var imgEl = jQuery('#' + imgId);
        if (imgEl.size() > 0) {
            // dem das Strecken-Icon umgebenden Link eine Click-Action zum Oeffnen des Layers zuweisen
            // und Layer automatisch schliessen, wenn Link den Fokus wieder verliert
            imgEl.parent()
                    .click(openLayer)
                    .keydown(iconKeyDown)
                    ;//.blur(closeLayer); // todo problem hierdurch bei reisendenlayern (opera)
        }
        // kein Strecken-Icon, dann sind Start/Ziel/Vias evtl. vorbelegt,
        // dann Aenderungen an dieser Vorbelegung verfolgen
        else {
            var via1 = jQuery('#' + via1Id).attr('value');
            var via2 = jQuery('#' + via2Id).attr('value');
            // nur, falls Vias vorbelegt sind
            if ((via1 && via1.length > 0) || (via2 && via2.length > 0)) {
                var start = jQuery('#' + startId).attr('value');
                var startDefault = jQuery('#' + startId + '-default').attr('value');
                var ziel = jQuery('#' + zielId).attr('value');
                var zielDefault = jQuery('#' + zielId + '-default').attr('value');
                // wenn Start o. Ziel ungleich dem Default-Text gefuellt sind, dann diese Strecke merken
                if ((start && start != startDefault) || (ziel && ziel != zielDefault)) {
                    // selektierte Strecke selbst erzeugen aus aktuellen Werten der Start-/Ziel-Felder
                    selStrecke = new BAHN_QF.QfStrecke();
                    selStrecke.start = new BAHN_QF.QfLoc();
                    selStrecke.start.name = start;
                    selStrecke.ziel = new BAHN_QF.QfLoc();
                    selStrecke.ziel.name = ziel;
                    // Eventhandler registrieren
                    jQuery('#' + startId).blur(observeInputField);
                    jQuery('#' + zielId).blur(observeInputField);
                }
            }
        }
    },

    // Rewrite quickfinder tab URL to a fragment identifier when JavaScript is active
    qfShowTab: function( sActiveTab, sTargetType ) {
        if (sActiveTab) {
            jQuery('#quickfinder div.tabpanel').removeClass( 'active' ).removeAttr( BAHN.nTabindex() );
        }
        jQuery( '#quickfinder ul.tablist a' ).each( function( i ) {
            var sRel = jQuery( this ).attr( 'rel' ),
                oTabpanel = jQuery( '#qf-tabpanel-' + ( i + 1 ) ),
                oParent = jQuery( this.parentNode.parentNode );
            if ( sRel !== sActiveTab || sTargetType === 'close' ) {
                // Inactive tab
                if ( sActiveTab || !sActiveTab && oParent.attr( 'class' ).indexOf( 'active' ) == -1 ) {
                    oParent.removeAttr( 'class' ); // Remove class="active" from parent list element
                    jQuery( this ).hide().show().attr( 'href', '#' + sRel ); // Replace current URL with anchor to the tab; force redraw
                } else {
                    jQuery( this ).removeAttr( 'href' ); // Remove href attribute from tab
                }
                if ( sTargetType === 'close' ) {
                    jQuery( '#quickfinder' ).attr( 'class', 'closed' );
                }
            } else {
                // Active tab
                jQuery( this ).removeAttr( 'href' ); // Remove href attribute from tab
                oParent.addClass( 'active' ); // Add class="active" to parent list element
                oTabpanel.addClass( 'active' ); // Show tabpanel
                // document.location.hash = '#' + sRel; // Update URL: causes Window Eyes to re-read page from top
                if (sTargetType === 'tab') {
                    jQuery('#qf-tabpanel-' + (i + 1) + '-focuspoint').focus(); // Set focus; workaround for Opera 9.5
                }
                jQuery( '#quickfinder' ).attr( 'class', 'open' );
                BAHN_QF.qfInitActiveTab(sActiveTab); // anzuzeigenden Tab initialisieren
            }
            i++;
        });
        // für Notfälle/Programmierfehler: wenn QF offen sein soll, aber noch keiner aktiv ist, den 1. Reiter aufklappen
        if ( jQuery('#quickfinder.open').length > 0 && jQuery('#quickfinder ul.tablist li.active').length === 0 ) {
            // Namen des 1. Reiters ermitteln
            var openTabName = jQuery('#quickfinder ul.tablist li').first().find('a').attr('rel');
            BAHN_QF.qfShowTab(openTabName);
        }
        BAHN.updateBuffer(); // Force screen reader buffer update
    },

    // Close button
    qfClose: function( event ) {
        var oTarget = BAHN.getTarget( event );
        // close layer with traveller-number-descriptions
        if (jQuery(oTarget).parent().attr('class') == 'qf-number-desc') {
            jQuery(oTarget).parent().parent().removeAttr('class');
        }
        // Strecken-Layer
        else if (jQuery(oTarget).parent().attr('class') == 'strecken-layer') {
            jQuery(oTarget).parent().removeAttr('style');
        }
        // close tabs (Schliessen-Button wird nur angezeigt, wenn QF auf dieser Seite geschlossen werden darf)
        else {
            BAHN_QF.qfShowTab(jQuery('#quickfinder ul.tablist li.active a').attr('rel'), 'close');
        }
        return false;
    },

    // Set focus on a quickfinder tab
    qfTabSetFocus: function( event ) {
        var oTarget = BAHN.getTarget( event );
        // function can be initiated either by a click on a tab or by loading a page URL with a fragment identifier
        var sFragmentID = ( oTarget && oTarget.href ) ? this.hash : document.location.hash;
        sFragmentID = sFragmentID.replace( '#', '' );
        // click on a tab
        if (oTarget) {
            // tab is closed: open it
            if (oTarget.href) {
                BAHN_QF.qfShowTab(sFragmentID);
            }
            // tab is open: close it (wenn QF auf dieser Seite geschlossen werden darf)
            else {
                if (!document.getElementById('quickfinder-always-open')) {
                    BAHN_QF.qfShowTab(jQuery('#quickfinder ul.tablist li.active a').attr('rel'), 'close');
                }
            }
        }
        // URL with fragment identifier
        else {
          BAHN_QF.qfShowTab( sFragmentID );
        }
    },

    // Check key input on quickfinder
    qfKeydown: function( e ) {
        var event = e || window.event;
        var iKey = event.keyCode,
            bAltKey = event.altKey,
            bShiftKey = event.shiftKey,
            oTarget = BAHN.getTarget( event ),
            sType = event.type,
            iNewTab,
            sId = jQuery( oTarget ).attr( 'id' );

        // Info-Layer zu Selectboxen fuer Anzahl Klein-/Kinder
        if (sId == 'qf-adult-number' || sId == 'qf-children-number' || sId == 'qf-infant-number' 
                || sId == 'vtv-qf-adult-number' || sId == 'vtv-qf-children-number' 
                    || sId == 'preissuche-qf-adult-number' || sId == 'preissuche-qf-children-number' || sId == 'preissuche-qf-infant-number' ) {
            
            if ( sType === 'focus' || sType === 'focusin' ) {
                // den aktuellen Layer einblenden (ueber das uebergeordnete li-Element - siehe CSS-Defs)
                jQuery( oTarget ).parent().addClass( 'qf-number-active' );
                
                // die "anderen" Reisendenanzahl-Info-Layer immer ausblenden 
                var otherNumberDescIds = null;
                if (sId == 'qf-infant-number') {
                    otherNumberDescIds = ['#qf-children-number', '#qf-adult-number'];    
                }
                else if (sId == 'qf-children-number'){
                    otherNumberDescIds = ['#qf-infant-number', '#qf-adult-number'];    
                }
                else if (sId == 'qf-adult-number'){
                    otherNumberDescIds = ['#qf-infant-number', '#qf-children-number'];    
                }
                else if (sId == 'vtv-qf-children-number') {
                    otherNumberDescIds = ['#vtv-qf-adult-number'];
                }
                else if (sId == 'vtv-qf-adult-number') {
                    otherNumberDescIds = ['#vtv-qf-children-number'];   
                }
                else if (sId == 'preissuche-qf-adult-number') {
                    otherNumberDescIds = ['#preissuche-qf-children-number', '#preissuche-qf-infant-number'];    
                }
                else if (sId == 'preissuche-qf-children-number'){
                    otherNumberDescIds = ['#preissuche-qf-adult-number', '#preissuche-qf-infant-number'];    
                }
                else if (sId == 'preissuche-qf-infant-number'){
                    otherNumberDescIds = ['#preissuche-qf-adult-number', '#preissuche-qf-children-number'];    
                }
                
                for (var i = 0; i < otherNumberDescIds.length; i++) {
                    jQuery(otherNumberDescIds[i]).parent().removeAttr( 'class' );
                }
            }
            // Wenn der Fokus der Selectbox in den zugehoerigen Layer "verlorengeht",
            // sollte der Layer eig. nicht geschlossen werden.
            // Da beim Blur das neue fokussierte Element jedoch nicht so einfach/browseruebergreifend feststellbar ist,
            // wird auf sonstiges automatisches Schliessen der Layer beim Verlassen der Selectboxen verzichtet.
            return;
        }
        
        if (sType === 'blur' || sType === 'focusout') {
            return;
        }

        // Tabpanel
        var sFocusTabpanelId = jQuery( oTarget ).parents('div.tabpanel').attr( 'id' );
        var iFocusTabpanel = BAHN.qfInteger( sFocusTabpanelId );
        var bFocusTabpanelAnchor = ( jQuery(oTarget).attr('class').indexOf('tabpanel-focus') != -1 );
        if ( bAltKey || bShiftKey && sType === 'keydown' || iFocusTabpanel && sType === 'keydown' && !bFocusTabpanelAnchor ) {
            return;
        }

        // Tab
        var sFocusTabId = jQuery( oTarget ).parents('li').attr( 'id' );
        var iFocusTab = BAHN.qfInteger( sFocusTabId );
        // return if it's an event or a key on the tab that doesn't interest us
        var bIsArrow = ( iKey == BAHN.key_left || iKey == BAHN.key_right || iKey == BAHN.key_up || iKey == BAHN.key_down );
        if ( !iFocusTab && !iFocusTabpanel || ( ( bFocusTabpanelAnchor || iFocusTab ) && !bIsArrow ) ) {
            return;
        }

        // Active Tab
        var sActiveTabId = jQuery( '#quickfinder ul.tablist li.active' ).attr( 'id' );
        var iActiveTab = BAHN.qfInteger( sActiveTabId );

        var i = iFocusTab || iFocusTabpanel;
        // Return if it's a key that doesn't interest us or if the event did not occur on the tabpanel
        if (i && iKey) {
            // Set new tab number
            if ((iKey === BAHN.key_left || iKey === BAHN.key_up) && i > 1) {
                iNewTab = i - 1;
            } else if ((iKey === BAHN.key_right || iKey === BAHN.key_down) && i < jQuery('#quickfinder ul.tablist li').length) {
                iNewTab = i + 1;
            }
        } else if ( sType === 'focus' || sType === 'focusin' ) {
            iNewTab = i;
        }
        // Show new active tabpanel
        if (iNewTab && ( sType === 'keydown' || iNewTab !== iActiveTab ) ) {
            var sTargetType = ( iFocusTab || bFocusTabpanelAnchor ) ? 'tab' : 'tabpanel';
            BAHN_QF.qfShowTab( jQuery('#qf-tab-' + iNewTab + ' a').attr('rel'), sTargetType );
        }
    },

    /**
     * Die QfLoc-Klasse repraesentiert eine Location/Ort (Bahnhof, Haltestelle, Adresse, PointOfInterest).
     */
    QfLoc: function() {
        this.name; // Bezeichnung
        this.id; // EVA-Nr
        this.loctyp; // Locationtyp (Bahnhof, Haltestelle, Adresse, POI)
        this.x;       // X-Koordinate
        this.y;       // Y-Koordinate
/*
        this.toString = function() {
            var result = "Loc = (";
            result += "name: ";
            if (this.name) {
                result += this.name;
            }
            result += ", id: ";
            if (this.id) {
                result += this.id;
            }
            result += ", loctyp: ";
            if (this.loctyp) {
                result += this.loctyp;
            }
            result += ", x: ";
            if (this.x) {
                result += this.x;
            }
            result += ", y: ";
            if (this.y) {
                result += this.y;
            }
            result += ")";
            return result;
        }
*/
        // alle Infos zu einer ID zusammensetzen -
        // damit kann die Auskunft dann diese Location eindeutig wiederfinden ohne teure Bahnhofsnamenaufloesung
        this.getTripleID = function() {
            var result = "";
            if (this.loctyp) {
                result += "A=" + this.loctyp + "@";
            }
            if (this.name) {
                result += "O=" + this.name + "@";
            }
            if (this.id) {
                result += "L=" + this.id + "@";
            }
            if (this.x) {
                result += "X=" + this.x + "@";
            }
            if (this.y) {
                result += "Y=" + this.y + "@";
            }
            return result;
        }
        
        // befuellt Objekt aus einer TripleID
        this.fromTripleID = function(tripleId) {
            if (tripleId != null) {
                var tokens = tripleId.split("@");
                
                for (var i = 0; i < tokens.length; i++) {                
                    var subTokens = tokens[i].split("=");
                    var key = subTokens[0];
                    var value = subTokens[1];
                    
                    if ("A" == key) {
                        this.loctyp = value;
                    } else if ("O" == key) {
                        this.name = value;
                    } else if ("L" == key) {
                        this.id = value;
                    } else if ("X" == key) {
                        this.x = value;
                    } else if ("Y" == key) {
                        this.y = value;
                    }               
                }
            }   
        }
    },

    /**
     * Die QfStrecke-Klasse repraesentiert eine Strecke bestehend aus mehreren QfLoc (Start, Vias, Ziel) und einem Namen
     */
    QfStrecke: function() {
        this.name; // Bezeichnung der Strecken
        this.index; // Index der Strecke, falls sie in einer Liste vorkommt
        this.start; // QfLoc
        this.via1; // QfLoc
        this.via2; // QfLoc
        this.ziel; // QfLoc
/*
        this.toString = function() {
            var result = "Strecke = (";
            result += "name: ";
            if (this.name) {
                result += this.name;
            }
             result += ", index: ";
            if (this.index) {
                 result += this.index;
            }
            result += ", \n  start: ";
            if (this.start) {
                result += this.start.toString();
            }
            result += ", \n  via1: ";
            if (this.via1) {
                result += this.via1.toString();
            }
            result += ", \n  via2: ";
            if (this.via2) {
                result += this.via2.toString();
            }
            result += ", \n  ziel: ";
            if (this.ziel) {
                result += this.ziel.toString();
            }
            result += "\n)";
            return result;
        }
*/
    },

    /**
     * Diese Methode ermittelt den Wert aus einem Attributnamenwert-Paar wie bspw. "n=hugo",
     * wobei Attributname und -wert durch den Marker PARAMETER_NAME_VALUE_SEP getrennt sind
     *
     * @param attrNameValueStr Attributnamenwertpaar
     * @return Attributwert, falls Marker vorhanden. Ansonsten null
     */
    qfCookieAttributeValue: function(attrNameValueStr) {
        var PARAMETER_NAME_VALUE_SEP = "=";
        var attrComponents = attrNameValueStr.split(PARAMETER_NAME_VALUE_SEP);
        var result = null;
        if (attrComponents.length == 2) {
            result = attrComponents[1];
        }
        return result;
    },

    /**
     * Die QfStreckenCookieHandler-Klasse ermoeglicht das Auslesen der Cookie-Daten fuer die Streckeninformationen.
     */
    QfStreckenCookieHandler: function() {
        // Name des zu parsenden Cookies
        var cookiename;

        // Array: StreckenIndex -> Strecke.
        // Liste von QfStrecken-Objekten aus dem Cookie.
        // Achtung wg. prototype-JS-Library: generell nur Arrays mit Integern als Index verwenden.
        // Bei Arrays mit Strings als Indices kann man durch diese nicht iterieren (per for-in-Schleife)!
        var strecken;

        var MAX_STRECKEN = 5;

        // allgemeine Parsing-Params
        var PARAMETER_ATTRIBUT_SEP = "#";
        var PARAMETER_LISTEND = "]#";

        // Params fuer Strecke und Locations
        var PARAMETER_NAME = "n=";
        // Params fuer Strecke
        var PARAMETER_STRECKE = "st=[";
        var PARAMETER_INDEX = "i=";
        var PARAMETER_START = "s=[";
        var PARAMETER_VIA1 = "v1=[";
        var PARAMETER_VIA2 = "v2=[";
        var PARAMETER_ZIEL = "z=[";
        // Params fuer Locations
        var PARAMETER_ID = "id=";
        var PARAMETER_LOCTYP = "lt=";
        var PARAMETER_X = "x=";
        var PARAMETER_Y = "y=";

        this.setCookieName = function(aCookieName) {
            if (aCookieName) {
                cookiename = aCookieName;
            }
        }

        this.getStrecken = function() {
            return strecken;
        }

        /**
         * Diese Methode erzeugt aus dem uebergebenen Cookie-Wert die Strecken-Informationen.
         * @param cookieValue cookieWert
         */
        this.parseCookie = function(cookieValue) {
            if (!cookiename)
                return;

            var cookieValue = jQuery.cookie(cookiename);
            if (!cookieValue)
                return;

            strecken = [];

            // alle Strecken-Teilstrings parsen
            while (cookieValue && (cookieValue.length > 0) && (cookieValue.indexOf(PARAMETER_STRECKE) == 0)) {
                cookieValue = parseStrecke(cookieValue);
            }
        }

        /**
         * Diese Methode extrahiert aus dem Cookie-Wert die Teilstringe mit den Steckeninformationen
         * und speichert diese jeweils in einem Strecken-Objekt ab.
         * Beispiel:
         * st=[n=zur Oma#i=1#s=[lt=A#n=Frankfurt, Frankenalle 2-4#]#z=[lt=P#n=Berlin, Hauptfriedhof#]#v1=[id=800060#n=Muenchen Hbf#]#]#
         * @param cookieValue Cookie-Wert
         * @return Cookie-Wert ohne die Streckeninformation
         **/
        var parseStrecke = function(cookieValue) {
            var strecke = new BAHN_QF.QfStrecke();
            var indexOfSep;
            var attrNameValueStr;
            var attrValue;

            // entferne Parameter fuer Strecke aus dem Cookie-Wert
            cookieValue = cookieValue.substring(PARAMETER_STRECKE.length);

            // String parsen, solange wir nicht am Listenende-Trenner
            while ((cookieValue.length > 0) && (cookieValue.indexOf(PARAMETER_LISTEND) != 0)) {
                // Extrahiere erstes Attribut
                indexOfSep = cookieValue.indexOf(PARAMETER_ATTRIBUT_SEP);
                attrNameValueStr = cookieValue.substring(0, indexOfSep);

                // Ermittle den Wert des ersten Attributs
                attrValue = BAHN_QF.qfCookieAttributeValue(attrNameValueStr);

                // Pruefe, ob es sich um komplexes Attribut handelt
                if ((cookieValue.indexOf(PARAMETER_START) == 0)
                        || (cookieValue.indexOf(PARAMETER_ZIEL) == 0)
                        || (cookieValue.indexOf(PARAMETER_VIA1) == 0)
                        || (cookieValue.indexOf(PARAMETER_VIA2) == 0)) {
                    // Aktuelles Attribut ist eine Location
                    cookieValue = parseLoc(cookieValue, strecke);
                // Atomares Attribut
                } else {
                    if (cookieValue.indexOf(PARAMETER_NAME) == 0) {
                        strecke.name = attrValue;
                    } else if (cookieValue.indexOf(PARAMETER_INDEX) == 0) {
                        strecke.index = attrValue;
                    } else {
                        continue;
                    }
                    cookieValue = cookieValue.substring(indexOfSep + 1);
                }
            }

            // wenn Strecke Namen hat und Index >= 0, dann in Liste merken
            if (strecke.index >= 0 && strecke.name && strecken.length < MAX_STRECKEN) {
                strecken.push(strecke);
            }

            // Pruefe, ob Cookie-Wert mit Listenende-Marker beginnt
            // Falls ja, wird dieser Marker aus dem Cookie-Wert entfernt
            if (cookieValue.indexOf(PARAMETER_LISTEND) == 0) {
                cookieValue = cookieValue.substring(PARAMETER_LISTEND.length);
            }

            return cookieValue;
        }

        /**
         * Diese Methode extrahiert aus dem Cookie-Wert den Ort(Start, Ziel, Via1 oder Via2),
         * der in das Streckenobjekt gesetzt wird.
         * Beispiel:
         * s=[lt=A#n=Frankfurt, Frankenalle 2-4#]
         * @param cookieValue Cookie-Wert
         * @param strecke Strecke
         * @return Cookie-Wert ohne die Ortinformationen
         **/
        var parseLoc = function(cookieValue, strecke) {
            var ort = new BAHN_QF.QfLoc();

            // Pruefe anhand des ersten Attributnamens um welchen Ortstyp es sich handelt
            // Dies wird anhand des ersten Attributnamens ermittelt
            if (cookieValue.indexOf(PARAMETER_START) == 0) {
                strecke.start = ort;
                cookieValue = cookieValue.substring(PARAMETER_START.length);
            } else if (cookieValue.indexOf(PARAMETER_ZIEL) == 0) {
                strecke.ziel = ort;
                cookieValue = cookieValue.substring(PARAMETER_ZIEL.length);
            } else if (cookieValue.indexOf(PARAMETER_VIA1) == 0) {
                strecke.via1 = ort;
                cookieValue = cookieValue.substring(PARAMETER_VIA1.length);
            } else if (cookieValue.indexOf(PARAMETER_VIA2) == 0) {
                strecke.via2 = ort;
                cookieValue = cookieValue.substring(PARAMETER_VIA2.length);
            }

            var indexOfSep;
            var attrNameValueStr;
            var attrValue;

            // Attribute des Orts parsen bis zum Listenende-Trenner
            while ((cookieValue.length > 0) && (cookieValue.indexOf(PARAMETER_LISTEND) != 0)) {
                // Extrahiere Attribut aus dem Cookie-Wert
                indexOfSep = cookieValue.indexOf(PARAMETER_ATTRIBUT_SEP);
                attrNameValueStr = cookieValue.substring(0, indexOfSep);

                // Ermittle den Wert des Attributs
                attrValue = BAHN_QF.qfCookieAttributeValue(attrNameValueStr);

                // Pruefe, um welches Attribut es sich handelt
                if (cookieValue.indexOf(PARAMETER_NAME) == 0) {
                    ort.name = attrValue;
                } else if (cookieValue.indexOf(PARAMETER_LOCTYP) == 0) {
                    ort.locTyp = attrValue;
                }   else if (cookieValue.indexOf(PARAMETER_ID) == 0) {
                    ort.id = attrValue;
                } else if (cookieValue.indexOf(PARAMETER_X) == 0) {
                    ort.x = attrValue;
                } else if (cookieValue.indexOf(PARAMETER_Y) == 0) {
                    ort.y = attrValue;
                } else {
                    continue;
                }

                // Entferne Attribut aus dem Cookie-Wert
                cookieValue = cookieValue.substring(indexOfSep+1);
            }

            // entferne Listenende-Marker beginnt
            if (cookieValue.indexOf(PARAMETER_LISTEND) == 0) {
                cookieValue = cookieValue.substring(PARAMETER_LISTEND.length);
            }

            return cookieValue;
        }
/*
        this.showModel = function() {
            var s = "showModel: Strecken\n";
            if (strecken) {
                for (var i = 0; i < strecken.length; i++) {
                    var strecke = strecken[i];
                    if (strecke) {
                        var r = strecke.name;
                        s += "Strecke(" + i + "): " + strecke.toString() + "\n\n";
                    }
                }
            }
            alert(s);
        }
*/
    },

    /**
     * Die QfReisender-Klasse repraesentiert einen Reisenden.
     */
    QfReisender : function() {
        this.typ = "";
        this.bahncard = 0;
        this.geburtsdatum = "";
        this.alter = "";
        // falls Geburtsdatum ueber Einzelfelder statt einem Feld angegeben wird
        // (fuer Auswertungen/Berechnungen (z. B. getAlter()) wird jedoch this.geburtsdatum verwendet!!)
        this.geb_tag = "";
        this.geb_monat = "";
        this.geb_jahr = "";

        /**
         * @return Alter des Reisenden am aktuellen Datum.
         *      Das Geburtsdatum muss im Format (d)d.(m)m.yyyy vorliegen.
         *      Falls diese Regeln verletzt sind, wird kein Alter, sondern "" (Leerstring) geliefert.
         */
        this.getAlter = function() {
            // Zieldatum wird in ordentlichem Format dd.mm.yyyy ins Cookie geschrieben,
            // sollte auch so hier ankommen
            if (!this.geburtsdatum || !this.geburtsdatum.length > 0 || this.geburtsdatum.length > 10) {
                if (this.alter && this.alter.length > 0) {
                    return this.alter;
                } else {
                    return "";
                }
            }
            
            var birthdate = new Date();
            // Geburtstag an "." aufsplitten, um Tag, Monat, Jahr zu erhalten
            var gdateElems = this.geburtsdatum.split(".");
            if (gdateElems.length === 3) {
                // new Date(y, m, d, ...), month in JS aus 0..11 !
                birthdate = new Date(gdateElems[2], gdateElems[1] - 1, gdateElems[0]);
            } else {
                return "";
            }
            var bday = birthdate.getDate();
            var bmonth = birthdate.getMonth();
            var byear = birthdate.getFullYear();

            var zieldate = new Date();
            var zday = zieldate.getDate();
            var zmonth = zieldate.getMonth();
            var zyear = zieldate.getFullYear();

            // Alter erstmal grob berechnen
            var age = zyear - byear;
            // Alterskorrektur in manchen Faellen
            if (zmonth < bmonth
                    || (zmonth === bmonth && zday < bday)) {
                age--;
            }
            if (age < 0) { // dann war Zieldatum < Geburtsdatum
                return "";
            } else {
                return age;
            }
        }
/*
        this.toString = function() {
            var result = "Reisender = (";
            result += "typ: ";
            if (this.typ) {
                result += this.typ;
            }
            result += ", label: ";
            if (this.label) {
                result += this.label;
            }
            result += ", bahncard: ";
            if (this.bahncard) {
                result += this.bahncard;
            }
            result += ", geburtsdatum: ";
            if (this.geburtsdatum) {
                result += this.geburtsdatum;
            }
            result += ", alter: ";
            if (this.alter) {
                result += this.alter;
            }

            result += ", geb-tag: ";
            if (this.geb_tag) {
                result += this.geb_tag;
            }
            result += ", geb-monat: ";
            if (this.geb_monat) {
                result += this.geb_monat;
            }
            result += ", geb-jahr: ";
            if (this.geb_jahr) {
                result += this.geb_jahr;
            }

            return result;
        }
*/
    },

    /**
     * Die QfReiseprofil-Klasse repraesentiert ein Reiseprofil.
     */
    QfReiseprofil : function() {
        this.name;
        this.index;
        this.schnellbuchung;
        this.klasse;
        this.reisende = [];
        // Hilfsmember
        this.adults = [];
        this.children = [];
        this.infants = [];

        /**
         * Liefert den index-ten Reisenden
         * @param {Object} index
         */
        this.getReisender = function(index) {
            var result = null;
            if ((this.index >= 0) && (this.index < this.reisende.length)) {
                result = this.reisende[index];
            }
            return result;
        }
        
        /**
         * Befuellt das Profil mit Default-Einstellungen
         */
        this.setDefaults = function() {
            this.name = "";
            this.index = -1;
            this.schnellbuchung = 0;
            this.klasse = 2; // da nur fuer PK
    
            var r = new BAHN_QF.QfReisender();
            r.typ = "E";
            r.bahncard = 0;
            r.geburtsdatum = "";
            r.geb_tag = "";
            r.geb_monat = "";
            r.geb_jahr = "";
    
            // 1 Erw., keine Kinder
            this.adults = [];
            this.adults.push(r);
            this.children = [];
            this.infants = [];
            
            this.reisende = [];
            this.reisende.push(r);
        }
/*
        this.toString = function() {
            var result = "Reiseprofil = (";
            result += "name: "
            if (this.name) {
                result += this.name;
            }
            result += ", index: "
            if (this.index) {
                result += this.index;
            }
            result += ", schnellbuchung: "
            if (this.schnellbuchung) {
                result += this.schnellbuchung;
            }
            result += ", \n  reisende: (";
            for (var i = 0; i < this.reisende.length; i++) {
                result += "\n    ";
                result += "reisender[" + i + "]: " + this.reisende[i].toString();

                if (i == this.reisende.length - 1) {
                    result += "\n  ";
                } else {
                    result += ",";
                }
            }
            result += ", klasse: "
            if (this.klasse) {
                result += this.klasse;
            }
            result += "\n)";
            return result;
        }
*/
    },

    /**
     * Die QfReiseprofilCookieHandler-Klasse ermoeglicht das Auslesen der Cookie-Daten fuer die Reiseprofilinformationen.
     */
    QfReiseprofilCookieHandler : function() {
        // Name des zu parsenden Cookies
        var cookiename;

        // Array: Reisendenprofil-Index -> Reiseprofil.
        // Liste von QfReiseprofil-Objekten aus dem Cookie.
        var reiseprofile;

        // allgemeine Parsing-Params
        var PARAMETER_ATTRIBUT_SEP = "#";
        var PARAMETER_LISTEND = "]#";

        // Obergrenzen
        var MAX_RPROFILE = 5;

        var PARAMETER_REISEPROFIL = "pr=[";
        var PARAMETER_REISENDE = "rl=[";
        var PARAMETER_REISENDER = "r=[";
        var PARAMETER_REISENDER_TYP = "t=";
        var PARAMETER_REISENDER_GEBURTSDATUM = "g=";
        var PARAMETER_REISENDER_BAHNCARD = "bc=";
        var PARAMETER_RESPREFS = "rp=[";
        var PARAMETER_RESPREFS_WAGENART = "w=";
        var PARAMETER_RESPREFS_WAGENART_UNBEDINGT = "wu=";
        var PARAMETER_RESPREFS_FENSTER_GANG = "fg=";
        var PARAMETER_RESPREFS_BESONDERHEITEN = "rk=";
        var PARAMETER_NAME = "n=";
        var PARAMETER_INDEX = "i=";
        var PARAMETER_SCHNELLBUCHUNG = "s=";
        var PARAMETER_KLASSE = "kl=";

        this.setCookieName = function(aCookieName) {
            if (aCookieName) {
                cookiename = aCookieName;
            }
        }

        /**
         * Liefert eine Liste der Reiseprofilnamen.
         *
         * @return Liste von Reiseprofilnamen
         */
        this.getReiseprofile = function() {
            return reiseprofile;
        }

        /**
         * Diese Methode erzeugt aus dem uebergebenen Cookie-Wert die Reiseprofilinformationen.
         *
         * Beispiel:
         * pr=[n=mit Family#i=1#s=0#rl=[r=[t=E#g=11.12.1950#bc=2#]#r=[t=F#g=20.07.1990#bc=3#]#]#kl=2#rp=[w=1#fg=2#]#]#pr=[n=allein#i=2#s=2#rl=[r=[t=E#g=11.12.1950#bc=2#]#]#kl=1#rp=[w=5#fg=2#rk=11#]#]#
         *
         * @param cookieValue cookieWert
         */
        this.parseCookie = function(cookieValue){
            if (!cookiename)
                return;

            var cookieValue = jQuery.cookie(cookiename);
            if (!cookieValue)
                return;

            // Neue leere Liste erzeugen
            reiseprofile = [];

            // Pruefe, ob Cookie-Wert mit dem Reiseprofilparameter beginnt
            while (cookieValue && (cookieValue.length > 0) && (cookieValue.indexOf(PARAMETER_REISEPROFIL) == 0)) {
                cookieValue = parseReiseprofil(cookieValue);
            }

            // Nachbereitung
            // Reisende in versch. Arrays verteilen je Typ
            var rprofil;
            var reisender;
            for (var i = 0; i < reiseprofile.length; i++) {
                rprofil = reiseprofile[i];
                for (var j = 0; j < rprofil.reisende.length; j++) {
                    reisender = rprofil.reisende[j];
                    if (BAHN_QF.QF_REISENDER_TYP_ERW === reisender.typ) {
                        rprofil.adults.push(reisender);
                    } else if (BAHN_QF.QF_REISENDER_TYP_FKIND === reisender.typ || BAHN_QF.QF_REISENDER_TYP_AKIND === reisender.typ) {
                        rprofil.children.push(reisender);
                    } else if (BAHN_QF.QF_REISENDER_TYP_KKIND === reisender.typ) {
                        rprofil.infants.push(reisender);
                    }
                }
            }
        }

        /**
         * Diese Methode extrahiert aus dem Cookie-Wert die Reiseprofilninformation.
         * Das erzeugte Reiseprofilnobjekt wird entsprechend der Indexinformation
         * in die Reiseprofilliste <code>reiseprofile</code> gesetzt.
         *
         * Beispiel:
         * pr=[n=mit Family#i=1#s=0#rl=[r=[t=E#g=11.12.1950#bc=2#]#r=[t=F#g=20.07.1990#bc=3#]#]#kl=2#rp=[w=1#fg=2#]#]#
         *
         * @param cookieValue Cookie-Wert
         * @return Cookie-Wert ohne die Reiseprofilninformation
         **/
        var parseReiseprofil = function(cookieValue) {
            var reiseprofil = new BAHN_QF.QfReiseprofil();

            var indexOfSep;
            var attrNameValueStr;
            var attrValue;

            // Entferne Parameter fuer Reiseprofil aus dem Cookie-Wert
            cookieValue = cookieValue.substring(PARAMETER_REISEPROFIL.length);

            // Bearbeite den Cookie-Wert solange ein Cookie-Wert noch nicht leer ist
            // und Cookie-Wert beginnt nicht mit Listenende-Trenner
            while ((cookieValue.length > 0) && (cookieValue.indexOf(PARAMETER_LISTEND) != 0)) {
                // Extrahiere erstes Attribut aus dem Cookie-Wert
                indexOfSep = cookieValue.indexOf(PARAMETER_ATTRIBUT_SEP);
                attrNameValueStr = cookieValue.substring(0, indexOfSep);

                // Ermittle den Wert des ersten Attributs
                attrValue = BAHN_QF.qfCookieAttributeValue(attrNameValueStr);

                // Pruefe, um welches Attribut es sich handelt
                if (cookieValue.indexOf(PARAMETER_REISENDE) == 0) {
                        // Aktuelles Attribut ist eine Reisendenliste
                        cookieValue = parseReisende(cookieValue, reiseprofil);
                } else if (cookieValue.indexOf(PARAMETER_RESPREFS) == 0) {
                        // Aktuelles Attribut ist eine Reisendenliste
                        cookieValue = parseResprefs(cookieValue, reiseprofil);
                } else {
                    // Atomares Attribut
                    if (cookieValue.indexOf(PARAMETER_NAME) == 0) {
                        // Name-Attribut
                        reiseprofil.name = attrValue;
                    } else if (cookieValue.indexOf(PARAMETER_INDEX) == 0) {
                        // Index-Attribut
                        reiseprofilIndex = attrValue;
                        reiseprofil.index = attrValue;
                    }  else if (cookieValue.indexOf(PARAMETER_SCHNELLBUCHUNG) == 0) {
                        // Schnellbuchung-Attribut
                        reiseprofil.schnellbuchung = attrValue;
                    }  else if (cookieValue.indexOf(PARAMETER_KLASSE) == 0) {
                        // Klasse-Attribut
                        reiseprofil.klasse = attrValue;
                    } else {
                        continue;
                    }

                    cookieValue = cookieValue.substring(indexOfSep + 1);
                }
            }

            // RProfil der Liste hinzufuegen
            if (reiseprofil.index >= 0 && reiseprofile.length < MAX_RPROFILE) {
                reiseprofile.push(reiseprofil);
            }

            // Pruefe, ob Cookie-Wert mit Listenende-Marker beginnt
            // Falls ja, wird dieser Marker aus dem Cookie-Wert entfernt
            if (cookieValue.indexOf(PARAMETER_LISTEND) == 0) {
                cookieValue = cookieValue.substring(PARAMETER_LISTEND.length);
            }

            return cookieValue;
        };

     /**
         * Diese Methode extrahiert aus dem Cookie-Wert der Reisenden.
         *
         * Beispiel:
         * rl=[r=[t=E#g=11.12.1950#bc=2#]#r=[t=F#g=20.07.1990#bc=3#]#]#
         *
         * @param cookieValue Cookie-Wert
         * @param strecke Strecke
         * @return Cookie-Wert ohne die Informationen der Reisenden
         **/
        var parseReisende = function(cookieValue, reiseprofil) {
            var indexOfSep;
            var attrNameValueStr;
            var attrValue;
            // Array: Listenindex (ohne semantische Bedeutung) -> Reisender
            // Liste von QFReisender-Objekten aus dem Cookie
            var reisende = [];

            // Entferne Parameter fuer die Reisenden aus dem Cookie-Wert
            cookieValue = cookieValue.substring(PARAMETER_REISENDE.length);

            // Bearbeite den Cookie-Wert solange ein Cookie-Wert noch nicht leer ist
                    // und Cookie-Wert beginnt nicht mit Listenende-Trenner
            while ((cookieValue.length > 0) && (cookieValue.indexOf(PARAMETER_LISTEND) != 0)) {
                // Extrahiere erstes Attribut aus dem Cookie-Wert
                indexOfSep = cookieValue.indexOf(PARAMETER_ATTRIBUT_SEP);
                attrNameValueStr = cookieValue.substring(0, indexOfSep);

                // Ermittle den Wert des ersten Attributs
                attrValue = BAHN_QF.qfCookieAttributeValue(attrNameValueStr);

                // Pruefe, um welches Attribut es sich handelt
                if (cookieValue.indexOf(PARAMETER_REISENDER) == 0) {
                    // Aktuelles Attribut ist eine Reisendenliste
                    cookieValue = parseReisender(cookieValue, reisende);
                }
            }

            // Setze die Reisenden in das Reiseprofil
            reiseprofil.reisende = reisende;

            // Pruefe, ob Cookie-Wert mit Listenende-Marker beginnt
            // Falls ja, wird dieser Marker aus dem Cookie-Wert entfernt
            if (cookieValue.indexOf(PARAMETER_LISTEND) == 0) {
                cookieValue = cookieValue.substring(PARAMETER_LISTEND.length);
            }

            return cookieValue;
        }

        /**
         * Diese Methode extrahiert aus dem Cookie-Wert des Reisenden.
         *
         * Beispiel:
         * r=[t=E#g=11.12.1950#bc=2#]#
         *
         * @param cookieValue Cookie-Wert
         * @param strecke Strecke
         * @return Cookie-Wert ohne die Informationen des Reisenden
         **/
        var parseReisender = function(cookieValue, reisende) {
            var indexOfSep;
            var attrNameValueStr;
            var attrValue;
            var reisender = new BAHN_QF.QfReisender();

            // Entferne Parameter fuer die Reisenden aus dem Cookie-Wert
            cookieValue = cookieValue.substring(PARAMETER_REISENDER.length);

            // Bearbeite den Cookie-Wert solange ein Cookie-Wert noch nicht leer ist
                    // und Cookie-Wert beginnt nicht mit Listenende-Trenner
            while ((cookieValue.length > 0) && (cookieValue.indexOf(PARAMETER_LISTEND) != 0)) {
                // Extrahiere erstes Attribut aus dem Cookie-Wert
                indexOfSep = cookieValue.indexOf(PARAMETER_ATTRIBUT_SEP);
                attrNameValueStr = cookieValue.substring(0, indexOfSep);

                // Ermittle den Wert des ersten Attributs
                attrValue = BAHN_QF.qfCookieAttributeValue(attrNameValueStr);
                // Atomares Attribut
                if (cookieValue.indexOf(PARAMETER_REISENDER_TYP) == 0) {
                    // Typ-Attribut
                    reisender.typ = attrValue;
                } else if (cookieValue.indexOf(PARAMETER_REISENDER_GEBURTSDATUM) == 0) {
                    // Geburtsdatum-Attribut
                    reisender.geburtsdatum = attrValue;
                }  else if (cookieValue.indexOf(PARAMETER_REISENDER_BAHNCARD) == 0) {
                    // Bahncard-Attribut
                    reisender.bahncard = attrValue;
                } else {
                    continue;
                }

                cookieValue = cookieValue.substring(indexOfSep+1);
            }

            if (reisende.length < BAHN_QF.QF_MAX_REISENDE) {
                reisende.push(reisender);
            } else {
                // ueueberzaehlige Reisende ignorieren
                //alert("Hinzufuegen des Reisenden fehlgeschlagen: Anzahl der Reisenden ueberschritten:\n"+cookieValue);
            }

            // Pruefe, ob Cookie-Wert mit Listenende-Marker beginnt
            // Falls ja, wird dieser Marker aus dem Cookie-Wert entfernt
            if (cookieValue.indexOf(PARAMETER_LISTEND) == 0) {
                cookieValue = cookieValue.substring(PARAMETER_LISTEND.length);
            }

            return cookieValue;
        }

        /**
         * Diese Methode entfernt (!) aus dem Cookie-Wert die Reservierungspraeferenzen.
         * Diese werden fuer den QF nicht benoetigt!
         *
         * Beispiel:
         * rp=[w=5#fg=2#rk=11#]#]#
         *
         * @param cookieValue Cookie-Wert
         * @param strecke Strecke
         * @return Cookie-Wert ohne die Informationen der Reservierungspraeferenzen
         **/
        var parseResprefs = function(cookieValue, reiseprofil) {
            var indexOfSep;
            var attrNameValueStr;
            var attrValue;

            // Entferne Parameter fueuer die Reisenden aus dem Cookie-Wert
            cookieValue = cookieValue.substring(PARAMETER_RESPREFS.length);

            // Bearbeite den Cookie-Wert solange ein Cookie-Wert noch nicht leer ist
            // und Cookie-Wert beginnt nicht mit Listenende-Trenner
            while ((cookieValue.length > 0) && (cookieValue.indexOf(PARAMETER_LISTEND) != 0)) {
                indexOfSep = cookieValue.indexOf(PARAMETER_ATTRIBUT_SEP);
                cookieValue = cookieValue.substring(indexOfSep + 1);
            }

            // Pruefe, ob Cookie-Wert mit Listenende-Marker beginnt
            // Falls ja, wird dieser Marker aus dem Cookie-Wert entfernt
            if (cookieValue.indexOf(PARAMETER_LISTEND) == 0) {
                cookieValue = cookieValue.substring(PARAMETER_LISTEND.length);
            }

            return cookieValue;
        }
/*
        this.showModel = function() {
            var s = "Reisprofile = (\n\n";
            if (reiseprofile) {
                var reiseprofil;
                for (var i = 0; i < reiseprofile.length; i++) {
                    reiseprofil = reiseprofile[i];
                    if (reiseprofil) {
                        s += "Reiseprofil[" + i + "]: "+reiseprofil.toString()+"\n\n";
                    }
                }
            }
            alert(s);
        }
*/
    },
    
    /**
     * Wenn der Wert im Bahnhofsfeld nicht dem entspr. Teil des Wertes des 
     * Feldes mit der TripleId entspricht, dann die TripleId entfernen. 
     * Voraussetzung: Die ID des Triple-ID-Feldes lautet: "<fieldId>-tripleid" !
     * @param {Object} fieldId
     *
     * todo: diese Funktionalitaet waere besser im FSuggest aufgehoben! -> Hacon
     */
    checkTripleId: function(event) {
        // Feld mit Eingabe des Bahnhofsnamens
        var oTarget = BAHN.getTarget(event);
        
        // Feld mit Triple-ID
        var tripleIdField = document.getElementById(oTarget.id + BAHN_QF.TRIPLE_ID_EXT);
        var tripleId = tripleIdField.value;

        // Triple-ID in Bestandteile zerlegen        
        var location = new BAHN_QF.QfLoc();
        location.fromTripleID(tripleId);

        // Name aus Triple-ID mit Name aus Eingabefeld vergleichen
        if (!location.name == oTarget.value) {
            // Triple-ID loeschen
            tripleIdField.value = "";
        }
    },
    
    /**
     * Captcha-Funktionalitaet fuer Preissuche-Reiter.
     * aehnlich wie de.bahn.groups.Captcha.js, jedoch anderes Fehlerhandling noetig. 
     */
    QfCaptcha : function() {   
        var that = this;
    
        this.searchTimeout = 1000;
    
        this.create = function() {
        	jQuery("#captchaReloadLink").bind("click", that.provideCaptcha);
        	
            this.provideCaptcha(); 
        };
    
        this.provideCaptcha = function() {
            var requestUrl = jQuery("#preissuche-qf-captcha-request-url").val(); // TEST: "http://www.google.de";      
            
            that.searchTimeout = parseInt(jQuery("#preissuche-qf-captcha-searchtimeout").val());
            
            jQuery.ajax({
                async: true, 
                cache: false,
                context:  that, // aendert die Bedeutung von this in den Callback-Funktionen            
                dataType: "json",
                error: that.processErrorCallback,
                success: that.processSuccessCallback,
                timeout: that.searchTimeout,
                type: "GET",
                url: requestUrl            
            });
            
            setTimeout(that.isCaptchaLoaded, (that.searchTimeout + 500));     
        };
    
        /**
         * Erweitertes ErrorHandling fuer Captcha Service. Anscheinend gibt es einen Bug im jQuery,
         * wenn der Server down ist schlaegt das ErrroHandling nach dem gesetzten Timeout nicht an.
         * Hier wird nach dem definierten Timeout (+ 500milis) geprueft ob der ScrambleCode vom Captcha
         * gesetzt wurde, wenn nicht wird der Hinweisabschnitt eingeblendet.
         */
        this.isCaptchaLoaded = function() {
            var scrambleCode = jQuery('#quickfinder #scrambleCode').val();
            if (scrambleCode == null || scrambleCode.length == 0) {
                that.handleCaptchaError("isCaptchaLoaded: Timeout Error");
            }
        };
        
        /**
         * Callback Funktion fuer erfolgreichen ajax-call
         */
        this.processSuccessCallback = function(data, textStatus, xmlHttpRequest) {
            // Im Falle dass die gelieferten Daten nicht ok sind
            if (data == undefined || data == null) {
                that.handleCaptchaError("processSuccess, AJAX ERROR: bad data from captcha server");            
            } else {
                var imageUrl = jQuery('#preissuche-qf-captcha-image-url').val();
                
                jQuery('#quickfinder #scrambleImage').attr({
                    src: imageUrl + data.img,
                    width: 154, // Breite ist im PSC auf 160 px festgelegt, hier wurde die Anzeige nochmal verkleinert.
                    height: data.height
                });
                
                jQuery('#quickfinder #scrambleCode').val(data.scramble);
                
                // load image entfernen, captcha image einblenden
                jQuery('#quickfinder #captchaloadImage').hide();
                jQuery('#quickfinder #captchaImage').show().removeClass("hide");
                jQuery('#quickfinder #captchaReload').show().removeClass("hide");
            }
        };
        
        /**
         * Callback Funktion fuer misslungenen ajax-call
         * Fehlerabschnitt wird eingeblendet.
         */
        this.processErrorCallback = function(xmlHttpRequest, textStatus, errorThrown) {    
            var errorMessage;
            if(xmlHttpRequest.status == 0) {
                errorMessage = 'You are offline!!\n Please Check Your Network.';
            } else if (xmlHttpRequest.status == 404) {
                errorMessage = 'Requested URL not found.';
            } else if (xmlHttpRequest.status == 500) {
                errorMessage = 'Internal Server Error.';
            } else if (textStatus == 'parsererror') {
                errorMessage = 'Parsing JSON Request failed.';
            } else if (textStatus == 'timeout') {
                errorMessage = 'Request Time out.';
            } else {
                errorMessage = 'Unknow Error.\n' + xmlHttpRequest.responseText;
            }
             
            that.handleCaptchaError(errorMessage);      
        };
        
        /**
         * Fehlerabschnitt einblenden 
         * @param {Object} errorMessage
         */
        this.handleCaptchaError = function(errorMessage) {
            // Preissuche-Formular aus-, Fehlerabschnitt einblenden
            jQuery('#qf-preissucheContainer').hide();
            jQuery('#qf-ps-captchafehler').show().removeClass("hidden");
        };
    },
    
    checkPreissuchePreconditions: function() {
        if (jQuery.browser.msie && jQuery.browser.version < 7) { 
        // fuer TEST im Firefox: if (jQuery.browser.mozilla) { 
            jQuery('#qf-ps-technischeVoraussetzungen').show();
            jQuery('#qf-preissucheContainer').hide();
        } else {
            jQuery('#qf-ps-technischeVoraussetzungen').hide();
            jQuery('#qf-preissucheContainer').show();
        }
    },
    
    qfOnSubmitTabPreissuche: function(startSearch) {
        var pscAnfrageData = {};
        
        // Startbhf - Name, Bhfsnr, Typ
        pscAnfrageData.startBhfName = document.getElementById("qf-preissuche-departure-point").value; // Wert aus dem Eingabefeld
        // falls im Eingabefeld noch der Default-Text steht, nicht uebernehmen
        if (pscAnfrageData.startBhfName == document.getElementById("qf-preissuche-departure-point-default").value) {
            pscAnfrageData.startBhfName = "";
        }
        // Bhfsnr + Typ aus Triple-ID-Feld, das bei Typeahead gefuellt wird
        var loc = new BAHN_QF.QfLoc();        
        var tripleId = document.getElementById('qf-preissuche-departure-point-tripleid').value; 
        if (tripleId != null && tripleId != "") {
            // Location-Objekt aus Triple-ID befuellen
            loc.fromTripleID(tripleId);
            // Daten aus Triple-ID nur dann uebernehmen, wenn der Bhfname in der Triple-ID mit dem aus dem Bhfs-Eingabefeld uebereinstimmt
            if (loc.name == pscAnfrageData.startBhfName) {
                pscAnfrageData.startBhfId = loc.id;
                pscAnfrageData.startBhfLocType = loc.loctyp;
            }
        } 

        // Zielbhf - Name, Bhfsnr, Typ
        pscAnfrageData.zielBhfName = document.getElementById("qf-preissuche-destination-point").value; // Wert aus dem Eingabefeld
        // falls im Eingabefeld noch der Default-Text steht, nicht uebernehmen
        if (pscAnfrageData.zielBhfName == document.getElementById("qf-preissuche-destination-point-default").value) {
            pscAnfrageData.zielBhfName = "";
        }
        // Bhfsnr + Typ aus Triple-ID-Feld, das bei Typeahead gefuellt wird
        loc = new BAHN_QF.QfLoc();        
        tripleId = document.getElementById('qf-preissuche-destination-point-tripleid').value; 
        if (tripleId != null && tripleId != "") {
            // Location-Objekt aus Triple-ID befuellen
            loc.fromTripleID(tripleId);
            // Daten aus Triple-ID nur dann uebernehmen, wenn der Bhfname in der Triple-ID mit dem aus dem Bhfs-Eingabefeld uebereinstimmt
            if (loc.name == pscAnfrageData.zielBhfName) {
                pscAnfrageData.zielBhfId = loc.id;
                pscAnfrageData.zielBhfLocType = loc.loctyp;
            }
        } 

        // einf./H+R-Fahrt
        pscAnfrageData.tripType = jQuery("input:radio:checked[name='ps-trip-type']").val();

        // Datum + Abfahrtszeit Hin
        pscAnfrageData.datumHin = document.getElementById('qf-preissuche-departure-date').value; 
        var sliderValues = slider.getTimeSliderValues("sucheSliderHinfahrt");
        pscAnfrageData.sliderHinMin = sliderValues[0];
        pscAnfrageData.sliderHinMax = sliderValues[1];
        
        // nur bei triptype=return:
        // Datum + Abfahrtszeit Rueck
        if (pscAnfrageData.tripType == "return") {
            pscAnfrageData.datumRueck = document.getElementById('qf-preissuche-return-date').value; 
            sliderValues = slider.getTimeSliderValues("sucheSliderRueckfahrt");
            pscAnfrageData.sliderRueckMin = sliderValues[0];
            pscAnfrageData.sliderRueckMax = sliderValues[1];
        } 
        
        // schnelle Verbindungen
        pscAnfrageData.schnelleVerbindungen = document.getElementById('qf-preissuche-travel-optimization').checked;
                 
        // Reiseprofil
        pscAnfrageData.reiseprofilIndex = document.getElementById('qf-preissuche-rprofil-select').value;
        pscAnfrageData.schnellbuchung = document.getElementById('qf-preissuche-rprofil-fastbm').value;
        
        // Reisende - Typ, BC
        var travellers = [];
        for (var i = 1; i <= BAHN_QF.QF_MAX_REISENDE; i++) {
            var rowId = "preissuche-qf-travrow-" + i;
            if (jQuery('#' + rowId + ':visible').length > 0) {
                var trav = {};
                trav.typ = document.getElementById('preissuche-qf-trav-type-' + i).value;
                trav.bc = document.getElementById('preissuche-qf-trav-bc-' + i).value;
                travellers.push(trav);
            }
        }
        pscAnfrageData.travellers = travellers;

        // Wagenklasse
        pscAnfrageData.klasse = jQuery("input:radio:checked[name='ps.tariffClass']").val();

        // Captcha Scramble + Eingabe
        // (evtl. nicht sichtbar, daher via jQuery, statt document.getelementbyid()...)
        pscAnfrageData.captchaScrambleCode = jQuery('#scrambleCode').val();
        pscAnfrageData.captchaUserInput = jQuery('#captchaInputField').val();
        
        // ob sofort die Suche im Preissucher gestartet werden soll
        if (startSearch) {
            pscAnfrageData.startSucheSofort = true;
        }

        // PscAnfrageData als JSON-String in ein Hiddenfield fuellen,
        // so werden die Daten beim Submit mitgesendet
        var pscAnfrageDataString = jQuery.toJSON(pscAnfrageData);
        //alert("pscAnfrageDataString = " + pscAnfrageDataString);
        document.getElementById("psc-anfragedata-json").value = pscAnfrageDataString;
        
        // wichtig: einen evtl. aus voriger Suche vorhandenen PS-Datencache loeschen
        window.name = "";
        
        return true;
    },
    
    // selektiert eine Option der Selectbox anhand des uebergebenen Values
    qfSelectByValue: function(selectbox, selvalue) {
        if (selectbox == null || selvalue == null)
            return;
            
        for (var i = 0; i < selectbox.options.length; i++) {
            if (selectbox.options[i].value == selvalue)
                selectbox.options[i].selected = true;
            else
                selectbox.options[i].selected = false;
         }    
    },
    
    // uebernommen aus webclient.js 
    // (direkter Aufruf von window.open() brachte nicht das gewuenschte Ergebnis, naemlich echtes neues Browser-Fenster)
    qfShowInfolinkWindow: function(filename, width, height) {
        var newwin = window.open(filename, 'hilfe', 'width=' + width + ',height=' + height + ',menubar=no,resizable=yes,scrollbars=yes');
        if (document.layers && newwin.scrollbars && newwin.scrollbars.visible == false) //NN4.x
            newwin.scrollbars.visibility = true;
        newwin.focus();
    },
    
    // Date picker opens calendar layer
    qfDatePicker: function() {
        // Integrate Bahn JavaScript for date picker
    },
    

    qfOnSubmitTabHotel: function(ibeName) {
        var urlArray = [];
        
        urlArray.push(document.getElementById('ibeUrl').value);
        urlArray.push("&ibe=");
        urlArray.push(ibeName);

        urlArray.push("&lang=");
        urlArray.push(document.getElementById('lang').value);
        urlArray.push("&country=");
        urlArray.push(document.getElementById('country').value);
        
		var defaultLocation = document.getElementById('qf-hotel-location-default').value;
		var location = document.getElementById('qf-hotel-location').value;
		if (location != "" && location != defaultLocation) {
			urlArray.push("&location=");
			// JBr 36 Location URL-encoden
			urlArray.push(encodeURI(location));
		}
		
        var arrivalDate = parseUserDateInput(document.getElementById('qf-hotel-arrival-date').value);
        urlArray.push("&startDateDay=");
        urlArray.push(arrivalDate.getDate());
        urlArray.push("&startDateMonth=");
        urlArray.push(arrivalDate.getMonth() + 1);
        urlArray.push("&startDateYear=");
        urlArray.push(arrivalDate.getFullYear());
        
        var departureDate = parseUserDateInput(document.getElementById('qf-hotel-departure-date').value);
        urlArray.push("&endDateDay=");
        urlArray.push(departureDate.getDate());
        urlArray.push("&endDateMonth=");
        urlArray.push(departureDate.getMonth() + 1);
        urlArray.push("&endDateYear=");
        urlArray.push(departureDate.getFullYear());
        
        urlArray.push("&singleRooms=");
        urlArray.push(document.getElementById('qf-hotel-rooms-single').value);
        urlArray.push("&doubleRooms=");
        urlArray.push(document.getElementById('qf-hotel-rooms-double').value);
        
		var adults = document.getElementById('qf-hotel-guests-e').value;
		if (adults != "") {
        	urlArray.push("&adults=");
        	urlArray.push(adults);			
		}

    	urlArray.push("&children=");
    	urlArray.push(document.getElementById('qf-hotel-guests-k').value);
		
        urlArray.push("&minRating=");
        urlArray.push(document.getElementById('qf-hotel-category').value);
        
        urlArray.push("&dbkanal_007=");
        urlArray.push(document.getElementById('dbkanal_007').value);
        
        window.location = urlArray.join("");
        
        return false;    	
    },
    
    qfOnSubmitTabMietwagen: function(ibeName) {
        var urlArray = [];
        
        urlArray.push(document.getElementById('ibeUrl').value);
        urlArray.push("&ibe=");
        urlArray.push(ibeName);
        
        urlArray.push("&lang=");
        urlArray.push(document.getElementById('lang').value);
        urlArray.push("&country=");
        urlArray.push(document.getElementById('country').value);
        
        urlArray.push("&STATIONCO=");
        urlArray.push(document.getElementById('qf-mietwagen-anmietstation').value); 
        urlArray.push("&STATIONCI=");
        urlArray.push(document.getElementById('qf-mietwagen-rueckgabestation').value);
        
        urlArray.push("&DATECO=");                
        urlArray.push(BAHN_QF.qfConvertToEuropcarTimestamp(
                document.getElementById('qf-mietwagen-anmietdatum').value, 
        		document.getElementById('qf-mietwagen-anmietzeit').value));
        urlArray.push("&DATECI=");
        urlArray.push(BAHN_QF.qfConvertToEuropcarTimestamp(
        		document.getElementById('qf-mietwagen-rueckgabedatum').value, 
        		document.getElementById('qf-mietwagen-rueckgabezeit').value));
        
        urlArray.push("&dbkanal_007=");
        urlArray.push(document.getElementById('dbkanal_007').value);
        
        window.location = urlArray.join("");
        
        return false;        
    },
    	
    /**
     * @param {String} dateString - dd.mm.yy
     * @param {String} timeString - HH:MM
     * @return yyyymmddHHMM
     */
	qfConvertToEuropcarTimestamp: function(dateString, timeString) {
        // uebergebene Uhrzeit in Anzahl Minuten seit 0:00 Uhr      
        // (Uhrzeit.js wird schon vom Slider im Preissuche-Reiter genutzt)  
        var timeInMinutes = de.bahn.util.Uhrzeit.getTime(timeString);
        // umrechnen der Anzahl Minuten in Stunden + Restminuten
        var hours = Math.floor(timeInMinutes / 60);
        var minutes = timeInMinutes % 60;
        
        // uebergebenes Datum in Date-Objekt umwandeln
        // und Uhrzeit ergänzen
        var newDate = parseUserDateInput(dateString);
        
        newDate.setHours(hours);    
        newDate.setMinutes(minutes);    

        // Zeitstempel aus Dateobjekt formatieren
        
        var resultString = "";
        // Jahr
        resultString += newDate.getFullYear();
        
        // Monat (JavaScript-Monate gehen von 0-11)
        var month = newDate.getMonth() + 1;
        if (month < 10) {
            month = "0" + month;
        }
        resultString += month;
        
        // Tag        
        var day = newDate.getDate();
        if (day < 10) {
            day = "0" + day;
        }
        resultString += day;
        
        // Stunden
        if (hours < 10) {
            hours = "0" + hours;
        }
        resultString += hours;
        
        // Minuten
        if (minutes < 10) {
            minutes = "0" + minutes;
        }
        resultString += minutes;
        
        return resultString;
    },	
	
    dCurDate: new Date()
};

jQuery(document).ready(function() {
    BAHN_QF.init();
});

