// ==================================================================
// Global variables
// ==================================================================

// coordinate reduction list
var reductionList = new Array();
// coordinates of the right mouse click
var ctxCoords = null;
// park and ride parking list
var parkAndRide = null;
// parking: zone assigned stops
var zoneAssignedStops = false;
// ics messages
var icsEventsArr = new Array();
// image path for journeys on output map
var efaInfoExImg = null;
// state of bike stop layer
var bikeStopLayerInit = false;


// ==================================================================
// Map configuartion
// ==================================================================

// map configuration
function initMdvMapConfig(name) {
	// configuration of orthografic map 
	if (name=='ortho') {
		// satellite map configuration
		mdvOrthoMapConfig.add('serverURL', absoluteServerPath.mapTiles + satelliteTiles); 
		mdvOrthoMapConfig.add('efaURL', absoluteServerPath.efa + '/liteVipVienna/XSLT_COORD_REQUEST');
		mdvOrthoMapConfig.add('transparentImg', imgPath + 'transparent.gif');
		mdvOrthoMapConfig.add('imagePath', imgPath);
		mdvOrthoMapConfig.add('network', 'aut');
		mdvOrthoMapConfig.add('trips.useJsonForPath', 'true');
		mdvOrthoMapConfig.add('trips.jsonServerURL', absoluteServerPath.efa + '/vip2/XSLT_TRIP_REQUEST2');
		mdvOrthoMapConfig.add('defaultScale', defaultScaleMap);	
		mdvOrthoMapConfig.add('xCenterReal', mapCenterX);
		mdvOrthoMapConfig.add('yCenterReal', mapCenterY);
		mdvOrthoMapConfig.add('mapName', nameMap);
		mdvOrthoMapConfig.add('fileType', '.jpg');
		mdvOrthoMapConfig.add('block', '100');
		mdvOrthoMapConfig.add('zoomOnDoubleClick', 'true');
		mdvOrthoMapConfig.add('language', mapLanguage);
		mdvOrthoMapConfig.add('useMagnifyGlass', 'true');
		mdvOrthoMapConfig.add('cursorMove', imgPath + 'grabbing.cur');
		mdvOrthoMapConfig.add('useBubbleForEFAInfo', 'true');
		mdvOrthoMapConfig.add('useBubbleOverflowForEFAInfo', 'true');
		mdvOrthoMapConfig.add('useBubblePinForEFAInfo', 'true');
		mdvOrthoMapConfig.add('info.stop.size.width', '300');
		mdvOrthoMapConfig.add('info.stop.size.height', '200');
		mdvOrthoMapConfig.add('info.stop.only', 'true');
		mdvOrthoMapConfig.add('info.poi.size.width', '300');
		mdvOrthoMapConfig.add('info.poi.size.height', '200');
		mdvOrthoMapConfig.add('poiArea', 'true');
		
		// satellite mini map configuration
		mdvMiniOrthoConfig.add('serverURL', absoluteServerPath.mapTiles + satelliteMiniTiles);
		mdvMiniOrthoConfig.add('efaURL', absoluteServerPath.efa + '/liteVipVienna/XSLT_COORD_REQUEST');
		mdvMiniOrthoConfig.add('transparentImg', imgPath + 'transparent.gif');
		mdvMiniOrthoConfig.add('network', 'aut');
		mdvMiniOrthoConfig.add('defaultScale', defaultScaleMap);	
		mdvMiniOrthoConfig.add('xCenterReal', mapCenterX);
		mdvMiniOrthoConfig.add('yCenterReal', mapCenterY);
		mdvMiniOrthoConfig.add('mapName', nameMap);
		mdvMiniOrthoConfig.add('fileType', '.jpg');
		mdvMiniOrthoConfig.add('block', '100');
		mdvMiniOrthoConfig.add('toolTimeOut', '20');
		mdvMiniOrthoConfig.add('zoomOnDoubleClick', 'true');	
		mdvMiniOrthoConfig.add('cursorMove', imgPath + 'grabbing.cur');
		
		// configuration of output map
		mdvOrthoMapConfig.add('tripURL', absoluteServerPath.efa + '/liteVipVienna/XSLT_TRIP_REQUEST2');
		mdvOrthoMapConfig.add('trips.marker.size.height', '200');
		mdvOrthoMapConfig.add('trips.marker.size.width', '300');
		mdvOrthoMapConfig.add('trips.polyline.size.height', '65');
		mdvOrthoMapConfig.add('trips.polyline.size.width', '300');
		mdvOrthoMapConfig.add('trips.polyline.opacity', '1');
		mdvOrthoMapConfig.add('trips.polyline.weight', '4');
		mdvOrthoMapConfig.add('motColour_0', '#0000FF'); 	// nicht belegt
		mdvOrthoMapConfig.add('motColour_1', '#FF0000');		// ubahn
		mdvOrthoMapConfig.add('motColour_2', '#00797A');		// s-bahn
		mdvOrthoMapConfig.add('motColour_3', '#FF0000');		// bus
		mdvOrthoMapConfig.add('motColour_4', '#7AA6FF');		// tram
		mdvOrthoMapConfig.add('motColour_5', '#0000FF');		// nicht belegt
		mdvOrthoMapConfig.add('motColour_6', '#0000FF');		// train
		mdvOrthoMapConfig.add('motColour_7', '#0000FF');		// nicht belegt
		mdvOrthoMapConfig.add('motColour_8', '#0000FF');		// anruf sammeltaxi
		mdvOrthoMapConfig.add('motColour_9', '#0000FF');		// nicht belegt
		mdvOrthoMapConfig.add('motColour_10', '#0000FF');	// nicht belegt
		mdvOrthoMapConfig.add('motColour_11', '#0000FF');	// nicht belegt
		mdvOrthoMapConfig.add('motColour_12', '#0000FF');	// nicht belegt
		mdvOrthoMapConfig.add('motColour_99', '#009B00');	// fussweg
		mdvOrthoMapConfig.add('motColour_100', '#009B00');	// fussweg
		mdvOrthoMapConfig.add('motColour_101', '#0000FF');	// fahrrad (bike & ride)	
		mdvOrthoMapConfig.add('motColour_102', '#0000FF');	// fahrrad (take bike along)
		mdvOrthoMapConfig.add('motColour_103', '#0000FF');	// pkw (kiss & ride)
		mdvOrthoMapConfig.add('motColour_104', '#0000FF');	// pkw (park & ride)
		mdvOrthoMapConfig.add('motColour_105', '#0000FF');	// taxi 
		mdvOrthoMapConfig.add('motColour_106', '#0000FF');	// pkw (monomodal)
		mdvOrthoMapConfig.add('motColour_107', '#000000');	// fahrrad (monomodal)
		mdvOrthoMapConfig.add('motColour_108', '#0000FF');
	}
	else {
		// map configuration
		mdvMapConfig.add('serverURL', absoluteServerPath.mapTiles + mapTiles); 
		mdvMapConfig.add('efaURL', absoluteServerPath.efa + '/liteVipVienna/XSLT_COORD_REQUEST');
		mdvMapConfig.add('transparentImg', imgPath + 'transparent.gif');
		mdvMapConfig.add('imagePath', imgPath);
		mdvMapConfig.add('network', 'aut');
		mdvMapConfig.add('trips.useJsonForPath', 'true');
		mdvMapConfig.add('trips.jsonServerURL', absoluteServerPath.efa + '/vip2/XSLT_TRIP_REQUEST2');
		mdvMapConfig.add('defaultScale', defaultScaleMap);	
		mdvMapConfig.add('xCenterReal', mapCenterX);
		mdvMapConfig.add('yCenterReal', mapCenterY);
		mdvMapConfig.add('mapName', nameMap);
		mdvMapConfig.add('block', '100');
		mdvMapConfig.add('zoomOnDoubleClick', 'true');
		mdvMapConfig.add('language', mapLanguage);
		mdvMapConfig.add('useMagnifyGlass', 'true');
		mdvMapConfig.add('cursorMove', imgPath + 'grabbing.cur');
		mdvMapConfig.add('useBubbleForEFAInfo', 'true');
		mdvMapConfig.add('useBubbleOverflowForEFAInfo', 'true');
		mdvMapConfig.add('useBubblePinForEFAInfo', 'true');
		mdvMapConfig.add('info.stop.size.width', '300');
		mdvMapConfig.add('info.stop.size.height', '200');
		mdvMapConfig.add('info.stop.only', 'true');
		mdvMapConfig.add('info.poi.size.width', '300');
		mdvMapConfig.add('info.poi.size.height', '200');
		mdvMapConfig.add('poiArea', 'true');
		
		// configuration of output map
		mdvMapConfig.add('tripURL', absoluteServerPath.efa + '/liteVipVienna/XSLT_TRIP_REQUEST2');
		mdvMapConfig.add('trips.marker.size.height', '200');
		mdvMapConfig.add('trips.marker.size.width', '300');
		mdvMapConfig.add('trips.polyline.size.height', '65');
		mdvMapConfig.add('trips.polyline.size.width', '300');
		mdvMapConfig.add('trips.polyline.opacity', '1');
		mdvMapConfig.add('trips.polyline.weight', '4');
		mdvMapConfig.add('motColour_0', '#0000FF'); 	// nicht belegt
		mdvMapConfig.add('motColour_1', '#FF0000');		// ubahn
		mdvMapConfig.add('motColour_2', '#00797A');		// s-bahn
		mdvMapConfig.add('motColour_3', '#FF0000');		// bus
		mdvMapConfig.add('motColour_4', '#7AA6FF');		// tram
		mdvMapConfig.add('motColour_5', '#0000FF');		// nicht belegt
		mdvMapConfig.add('motColour_6', '#0000FF');		// train
		mdvMapConfig.add('motColour_7', '#0000FF');		// nicht belegt
		mdvMapConfig.add('motColour_8', '#0000FF');		// anruf sammeltaxi
		mdvMapConfig.add('motColour_9', '#0000FF');		// nicht belegt
		mdvMapConfig.add('motColour_10', '#0000FF');	// nicht belegt
		mdvMapConfig.add('motColour_11', '#0000FF');	// nicht belegt
		mdvMapConfig.add('motColour_12', '#0000FF');	// nicht belegt
		mdvMapConfig.add('motColour_99', '#009B00');	// fussweg
		mdvMapConfig.add('motColour_100', '#009B00');	// fussweg
		mdvMapConfig.add('motColour_101', '#0000FF');	// fahrrad (bike & ride)	
		mdvMapConfig.add('motColour_102', '#0000FF');	// fahrrad (take bike along)
		mdvMapConfig.add('motColour_103', '#0000FF');	// pkw (kiss & ride)
		mdvMapConfig.add('motColour_104', '#0000FF');	// pkw (park & ride)
		mdvMapConfig.add('motColour_105', '#0000FF');	// taxi 
		mdvMapConfig.add('motColour_106', '#0000FF');	// pkw (monomodal)
		mdvMapConfig.add('motColour_107', '#000000');	// fahrrad (monomodal)
		mdvMapConfig.add('motColour_108', '#0000FF');
		
		// mini map configuration
		mdvMiniMapConfig.add('serverURL', absoluteServerPath.mapTiles + miniMapTiles);
		mdvMiniMapConfig.add('efaURL', absoluteServerPath.efa + '/liteVipVienna/XSLT_COORD_REQUEST');
		mdvMiniMapConfig.add('transparentImg', imgPath + 'transparent.gif');
		mdvMiniMapConfig.add('network', 'aut');
		mdvMiniMapConfig.add('defaultScale', defaultScaleMap);	
		mdvMiniMapConfig.add('xCenterReal', mapCenterX);
		mdvMiniMapConfig.add('yCenterReal', mapCenterY);
		mdvMiniMapConfig.add('mapName', nameMap);
		mdvMiniMapConfig.add('block', '100');
		mdvMiniMapConfig.add('zoomOnDoubleClick', 'true');	
		mdvMiniMapConfig.add('cursorMove', imgPath + 'grabbing.cur');
	}
	
	// coordinate reduction
	reductionList = [
		{ maxScale:   2500, epsilon:   1.0 },
		{ maxScale:   5200, epsilon:   1.5 },
		{ maxScale:  11000, epsilon:   2.5 },          
		{ maxScale:  23000, epsilon:   5.0 },
		{ maxScale:  50000, epsilon:  10.0 },
		{ maxScale: 100000, epsilon:  20.0 },
		{ maxScale: 210000, epsilon: 100.0 }
	];
}
	
	
// ==================================================================
// Common map functionality
// ==================================================================

// This function loads the map and minimap
function MDVMapHelper(name) {
	this.name = name;
	this.mdvMap = null;
	this.mdvMiniMap = null;
	if (this.name=='ortho')
		this.satelliteOverlay = null;
	this.markerLayer = null;
	this.parkAndRideLayer = null;
	this.roadworksLayer = null;
	this.blockingsLayer = null;
	this.informationLayer = null;
	this.marker = null;
	this.sync = null;
	this.parkAndRideProcessed = false;
	this.viewport = document.getElementById('mdvMap');
	this.trips = null;
	
	// initialize map and register events
	if (this.mdvMap == null) {
		this.mdvMap = new MDVMap(this.viewport);
		
		// context menu for enquiry screen
		if(document.getElementById('mapContextMenu') && document.getElementById('mapContextMenu').value == 'jpEnquiry') {
			this.ctxMenuArr = new Array();
			this.ctxMenuArr[0] = new MDVMapMenuItem(setOrigin, this.setCoordinatesOrigin);
			this.ctxMenuArr[1] = new MDVMapMenuItem(setDestination, this.setCoordinatesDestination);
			this.ctxMenu = new MDVMapMenu(this.ctxMenuArr);
			new MDVMapContextMenu(this.mdvMap, this.ctxMenu);
			this.mdvMap.events.registerEvent(MDVEvent_CONTEXT_MENU, null, ContextMenuHandler);
		}
		
		this.mdvMap.events.registerEvent(MDVEvent_TOOLTIP, this, this.onToolTip);
        this.mdvMap.events.registerEvent(MDVEvent_LAYER_UPDATED, this, this.highlightPoint);
        if(currentPage == 'parkAndRidePlanner') {
			this.mdvMap.events.registerEvent(MDVEvent_MAP_INITIALISED, this, this.setParkAndRideParking);
        }
		
		new MDVMapNavigator(this.mdvMap);
		this.createMapControl();
		this.createZoomRectangle();
		
		// output map
        if (!efaInfoExImg) {
                efaInfoExImg = imgPath;
            }     
        new MDVMapEFAInfoEx(this.mdvMap, {getMOTImage: getMOTImage, imagePath: efaInfoExImg, alignment: new MDVPoint(0.5, 0.5)} );
		this.trips = new MDVMapEFATrips(this.mdvMap, { reductionList: reductionList });
		
		// layer
		this.markerLayer = this.mdvMap.createLayer('vipMarkers');
		this.markerLayer.id = 1;
		this.markerLayer.setZIndex('18');
		this.mdvMap.addLayer(this.markerLayer);
		this.parkAndRideLayer = this.mdvMap.createLayer('parkAndRideMarkers');
		this.markerLayer.id = 15;
		this.parkAndRideLayer.setZIndex('15');
		this.mdvMap.addLayer(this.parkAndRideLayer);
		this.roadWorksLayer = this.mdvMap.createLayer('roadWorks'); 
		this.roadWorksLayer.setZIndex('22');
		this.mdvMap.addLayer(this.roadWorksLayer);
		this.blockingsLayer = this.mdvMap.createLayer('blockings'); 
		this.blockingsLayer.setZIndex('23');
		this.mdvMap.addLayer(this.blockingsLayer);
		this.informationLayer = this.mdvMap.createLayer('information'); 
		this.informationLayer.setZIndex('21');
		this.mdvMap.addLayer(this.informationLayer);
	}
	
	// initialize the mini map
	if (this.mdvMiniMap == null) { 
		this.mdvMiniMap = new MDVMap(document.getElementById('mdvMiniMap'));
		new MDVMapNavigator(this.mdvMiniMap); 
	}
	
	// execute map and minimap
	if (this.mdvMap) {
		createMapOverlays(this);
		if (this.name == 'ortho') {
            this.satelliteOverlay = this.mdvMap.createOverlay('Labels', absoluteServerPath.mapTiles + satelliteLabelTiles)
			this.satelliteOverlay.setFileType('.png');
			this.mdvMap.addOverlay(this.satelliteOverlay);
			this.mdvMap.execute(mdvOrthoMapConfig);
			this.satelliteOverlay.setActive(document.getElementById('showLabels').checked);
			this.mdvMap.update();
		}
		else {
			this.mdvMap.execute(mdvMapConfig);
		}
		if (this.mdvMiniMap) {
			if (this.name == 'ortho') {
				this.mdvMiniMap.execute(mdvMiniOrthoConfig);
			}
			else {
				this.mdvMiniMap.execute(mdvMiniMapConfig);
            }
            this.sync = new MDVMapSyncBound(this.mdvMap, this.mdvMiniMap);
            this.mdvMap.registerGadget(this.sync);
		}
	}
	
	// z-index of trips layer
	this.mdvMap.getLayer('efa_trip').setZIndex('4');
	
	// display external markers
	if (enableMapMarkers == 'true') {
		this.displayExternalMarkers(commonMapMarkers);
	}
	
	// display stops for bike & ride or take bike along 
	if (currentPage == 'cycling' && bikeStopSelection == 'map') {
		this.bikeStopLayer = null;
		this.bikeStopLayer = this.mdvMap.createLayer('bikeStops');	
		this.bikeStopLayer.setZIndex('1');
		this.mdvMap.addLayer(this.bikeStopLayer);
		if (showBikeStops == 'true') {
			var bikeStopSearch = new MDVEFABikeStopSearch();
			bikeStopSearch.getBikeStops();
		}
	}

	// centre on identified origin/destination
	if ((document.getElementById('nameX_origin') && document.getElementById('nameX_origin').value!='') || (document.getElementById('nameX_destination') && document.getElementById('nameX_destination').value != '')) {
		var usage = new Array();
		if (document.getElementById('nameX_origin') && document.getElementById('nameX_origin').value!='') 
			usage.push('origin');
		if (document.getElementById('nameX_destination') && document.getElementById('nameX_destination').value!='') 
			usage.push('destination');
		this.doIdentified(usage);
	}
	
	// map does not move if it is grapped and the mouse moved over the borders of the map
	attachEventListener(document, 'mouseover', this.mdvMap.release.bind(this.mdvMap), false);
	if (this.mdvMiniMap)
		attachEventListener(document, 'mouseover', this.mdvMiniMap.release.bind(this.mdvMiniMap), false);
}


// Determine POI icons by draw class 
function getMOTImage (mot, type, pin) {
    if (!efaInfoExImg) {
		img = imgPath;
    }
    else {
        img = efaInfoExImg;
    }
    if((type =='POI_POINT' || type == 'POI_AREA') && pin.attrs[1].value){
        if (pin.attrs[1].value == 'PoiCycleParking'){
            img += 'citybike.png';
        }
        else {
            img += 'poi.gif';	
        }
    }
    else {
		img += 'mot' + mot + '.gif';		
    }
    return img;
}

	
// This function destroys the map and clears the cache.
MDVMapHelper.prototype.destroy = function() {
	storeMapCentreAndZoomlevel();

	// destroy map elements
	getDivsByClassName('MDVMapControl')[0].parentNode.removeChild(getDivsByClassName('MDVMapControl')[0]);
 	document.getElementById('mdvMap_mdvMap_mapper0_mapTiles').parentNode.removeChild(document.getElementById('mdvMap_mdvMap_mapper0_mapTiles'));
 	document.getElementById('mdvMap_mdvMarkers').parentNode.removeChild(document.getElementById('mdvMap_mdvMarkers'));
 	document.getElementById('mdvMap_mapper0').parentNode.removeChild(document.getElementById('mdvMap_mapper0'));
 	document.getElementById('mdvMap_mapper1').parentNode.removeChild(document.getElementById('mdvMap_mapper1'));

	// destroy mini map elements
	if (mdvMap.mdvMiniMap) {
		getDivsByClassName('MDVMapSync_Inner')[0].parentNode.removeChild(getDivsByClassName('MDVMapSync_Inner')[0]);
		getDivsByClassName('MDVMapSync_Outer')[0].parentNode.removeChild(getDivsByClassName('MDVMapSync_Outer')[0]);
		document.getElementById('mdvMiniMap_mdvMiniMap_mapper0_mapTiles').parentNode.removeChild(document.getElementById('mdvMiniMap_mdvMiniMap_mapper0_mapTiles'));
		document.getElementById('mdvMiniMap_mdvMarkers').parentNode.removeChild(document.getElementById('mdvMiniMap_mdvMarkers'));
		document.getElementById('mdvMiniMap_mapper0').parentNode.removeChild(document.getElementById('mdvMiniMap_mapper0'));
		mdvMap.mdvMiniMap.destroy()
		mdvMap.mdvMiniMap = null;
	}
	
	mdvMap.mdvMap.destroy();
	mdvMap.mdvMap = null;
	mdvMap.mdvMiniMap = null;
	mdvMap = null;
}


// ==================================================================
// Input map functionality.
// ==================================================================

// Highlights a preselected stop or poi
MDVMapHelper.prototype.highlightPoint = function(id, msg, layer) {
	var odv = new Array();
	if (document.getElementById('itdLPxx_odv_origin') && document.getElementById('itdLPxx_odv_origin').value!='')
		odv.push({id: document.getElementById('itdLPxx_odv_origin').value, type: ''});
		
	if (document.getElementById('itdLPxx_odv_destination') && document.getElementById('itdLPxx_odv_destination').value!='')
		odv.push({id: document.getElementById('itdLPxx_odv_destination').value, type: ''});
	
	// parkings (green zone)
	if (parkAndRide) {
		for (var i=0; i<parkAndRide.length; i++) {
			if (parkAndRide[i].id)
				odv.push({id: parkAndRide[i].id, type: 'parkAndRide'});
		}
	}
	
	if (layer && odv) {
		var markers = layer.getMarkers();
		for (var m = 0; m < markers.length; m++) {
			var object = markers[m].getObjectId();
			var poiID = '';
			if (object.type=='POI_AREA'){
				var separator = object.id.indexOf('-');
				if (separator > 0) {
					poiID = object.id.substring(separator+1, object.id.length);
				}
			}
			for (var i=0; i<odv.length; i++) {
				if (object.id == odv[i].id || poiID == odv[i].id) { 
					var img = markers[m].getImage();
					img.className = 'markedIcon';
					if (odv[i].type == 'parkAndRide') {
						img.className = 'markedIconParking';
					}
                    // open tool tip for address input
                    if (currentPage == 'address') {
                        markers[m].toolTip.display();
                        markers[m].toolTip.setFixedPin(true);
                    }
					break;	
				}
			}
		}
	}
}


// Display and highlight the identified point.
MDVMapHelper.prototype.doIdentified = function(usage) {
	var zl = 7;
	var nc = null;
	
	for (var i=0; i<usage.length; i++) {
		var mapName = document.getElementById('nameMapName_' + usage[i]).value;
		var x = document.getElementById('nameX_' + usage[i]).value;
		var y = document.getElementById('nameY_' + usage[i]).value;
	
		// address (selected by click or entered by form) or full hit on address/poi screen
		if(showBikeStops == 'true' || (document.getElementById('type_' + usage[i]) && (document.getElementById('type_' + usage[i]).value=='coord' || document.getElementById('type_' + usage[i]).value=='crossing' || (document.getElementById('type_' + usage[i]).value=='any') && document.getElementById('anyType_' + usage[i]) && document.getElementById('anyType_' + usage[i]).value!='stop' && document.getElementById('anyType_' + usage[i]).value!='poi'))) {
			// set origin/destination marker
			if (x && y && mapName) {
				var marker = new MDVCoordinates(mapName, parseInt(x), parseInt(y));
				this.setMarker(marker, usage[i]);
			}
		}

		// get zoomlevel and map centre; do not center on identified point if no input by form
		if (!parkAndRide && document.getElementById('type_' + usage[i]) && document.getElementById('type_' + usage[i]).value!='any' && i==usage.length-1 && document.getElementById('itdLPxx_mapCentre') && document.getElementById('itdLPxx_zoomLevel')) {
			var centre = document.getElementById('itdLPxx_mapCentre').value.split(':');
			x = centre[0];
			y = centre[1]; 
			mapName = centre[2];
			zl = document.getElementById('itdLPxx_zoomLevel').value;
		}
	}
	
	this.mdvMap.update();
	
	if (x <= 0 || y <= 0) 
		return;
	
	if (!parkAndRide) {
		nc = new MDVCoordinates(mapName, parseInt(x), parseInt(y));
		this.mdvMap.setCentre(nc);
		this.mdvMap.setZoomLevel(parseInt(zl));
	}
};


// This function sets the origin/destination marker.
MDVMapHelper.prototype.setMarker = function(obj, usage) {
	var mc = new MDVCoordinates(obj.mapName, parseInt(obj.x), parseInt(obj.y));
	var text;
	var size = new MDVPoint(300, 200);
	
	if (usage=='destination') {
		if (document.getElementById('name_destination') && document.getElementById('name_destination').value!='')
			text = document.getElementById('name_destination').value;
		else
			text = mapDestination;
	}
	else {
		if (document.getElementById('name_origin') && document.getElementById('name_origin').value!='')
			text = document.getElementById('name_origin').value;
		else
			text = mapOrigin;
	}
	this.marker = this.mdvMap.createMarker(mc, 0, this.getImage(usage));
	var tool = this.mdvMap.createToolTip(size,'<b>' + text + '</b>');
	this.marker.setToolTip(tool);
	this.markerLayer.addMarker(this.marker);
	// open tooltip for address-search
	if (currentPage == 'address' && !this.marker.toolTip.isVisible()){
        this.mdvMap.update();
        this.marker.toolTip.display();
		this.marker.toolTip.setFixedPin(true);
	}
};


// This function returns the marker image.
MDVMapHelper.prototype.getImage = function(usage) {
	var img = imgPath + 'address.gif';

	switch(usage) {
		case 'origin':
			img = imgPath + 'origin.gif';
			break;
		case 'destination':
			img = imgPath + 'destination.gif';
			break;
	}

	var i = new Image();
	i.src = img;

	return img;
};


// This function sets the park and ride parkings
MDVMapHelper.prototype.setParkAndRideParking = function(id, msg, obj) {	
	var size = new MDVPoint(300, 200);
	var zl = 4;
	var zlStop = 6;
	if (zoneAssignedStops)
		zl = zlStop;
	if (!this.parkAndRideProcessed && parkAndRide) {
		for (var i=0; i<parkAndRide.length; i++) {
			if (parkAndRide[i].x && parkAndRide[i].y && parkAndRide[i].mapName) {
				var mc = new MDVCoordinates(parkAndRide[i].mapName, parseInt(parkAndRide[i].x), parseInt(parkAndRide[i].y));
				// set park and ride symbols
				if (parkAndRide[i].anyType!='stop') {
					// parking zone
					if (parkAndRide[i].parkObjType == 8)
						this.marker = this.mdvMap.createMarker(mc, 0.5, imgPath + 'parkingZone.gif');
					// park and ride
					else if (parkAndRide[i].PR == 1) {
						if (parkAndRide[i].hasRealtime == 1)
							this.marker = this.mdvMap.createMarker(mc, 0.5, imgPath + 'parkAndRideRealtime.gif');
						else
							this.marker = this.mdvMap.createMarker(mc, 0.5, imgPath + 'parkAndRide.gif');
					}
					// garage
					else {
						if (parkAndRide[i].hasRealtime == 1)
							this.marker = this.mdvMap.createMarker(mc, 0.5, imgPath + 'garageRealtime.gif');
						else
							this.marker = this.mdvMap.createMarker(mc, 0.5, imgPath + 'garage.gif');
					}
					var tool = this.mdvMap.createToolTip(size,'<b>' + parkAndRide[i].name + '</b>');
					tool.parkAndRide = parkAndRide[i].id;
					tool.selectionLink = true;
					this.marker.setToolTip(tool);
					this.parkAndRideLayer.addMarker(this.marker);
					this.marker.toolTip.setPin(true);
					// center y mark best match
					if (parkAndRide[i].selected == '1') {
						var img = this.marker.getImage();
						img.className='markedIconParking';
						this.mdvMap.setCentre(mc);
						this.mdvMap.setZoomLevel(zl);
					}
				}
				// zoom in for park and right stop - stop highlighted by hightlightPoint function
				else if (parkAndRide[i].selected == '1') {
					this.mdvMap.setCentre(mc);
					this.mdvMap.setZoomLevel(zlStop);
				}
			}
		}
		// set marker for origin/destination stop/poi because symbol is not displayed in all zoom levels
		var usage = new Array('origin', 'destination');	
		if (document.getElementById('nameMapName_' + usage[i])) {
			for (var i=0; i<usage.length; i++) {	
				var mapName = document.getElementById('nameMapName_' + usage[i]).value;
				var x = document.getElementById('nameX_' + usage[i]).value;
				var y = document.getElementById('nameY_' + usage[i]).value;
				var marker = new MDVCoordinates(mapName, parseInt(x), parseInt(y));
				this.setMarker(marker, usage[i]);
			}
		}
		this.parkAndRideProcessed = true;	
		this.mdvMap.update();
	}
}


// ==================================================================
// Stop/station, poi, address and parking tooltips.
// ==================================================================

function MDVToolTipHelper(toolTip) {
	this.toolTip = toolTip;
	this.processed = false;
}


// This function creates the tooltip bubble.
MDVToolTipHelper.prototype.execute = function(tooltip) {
	var id = tooltip.getParent().id;
	if (tooltip.getParent().objectId) {
		id = tooltip.getParent().objectId.id;
    }
	if (tooltip.bikeStopID) {
		id = tooltip.bikeStopID;
    }
    
    var isCitybike = false;
    if (citybikeInfo != '' && tooltip.container.lastParent && (tooltip.container.lastParent.objectId.type == 'POI_POINT' || tooltip.container.lastParent.objectId.type == 'POI_AREA') && tooltip.container.lastParent.objectId.attrs[1].value && tooltip.container.lastParent.objectId.attrs[1].value == 'PoiCycleParking') {
        isCitybike = true;
    }
        
	if (!this.processed) {
		// ics message
		if (tooltip.validity) {
			createICSBubble ('IT', tooltip);
		}
		// tooltip for stops with bike & ride or takt bike along access
		else if (tooltip.bikeStopID) {
			var body = '<div id="' + id + '">';
			body += this.toolTip.getInnerHTML();
			body += '<br/><br/>';
			body += '<a href="javascript:document.getElementById(\'execInst\').value=\'normal\';document.getElementById(\'itdLPxx_view\').value=\'bikeStopSelected\';this.submitBikeStop(\'' + id + '\',\'' + tooltip.bikeStopName + '\')">' + selectBikeStop + '</a>';
			if (enableDMBubble) {
				body += '<div id=\'dmLoading_' + id +'\'>';
				body += '<br/>';
				body += dmLoading;
				body += '</div>';
			}
			body += '</div>';
			this.toolTip.setInnerHTML(body);
		}
		// tooltip for park and ride parking and for parking on journey planner screen (monomodal car journey)
		else if (tooltip.parkAndRide || tooltip.parkingSearch) {
			var body = '<div id="' + id + '">';
			body += '</div>';
			this.toolTip.setInnerHTML(body);
			// get tooltip information
			tooltip.parking = new MDVEFAParkObjectInfo(id, absoluteServerPath.efa + '/parkingInfo/XML_PARKOBJECT_REQUEST');
			tooltip.parking.getParkingInfo(id, tooltip.parkAndRide, tooltip.selectionLink);
		}
		// tooltip on address/poi input screen
		else if(currentPage == 'address' && document.forms[0].name_origin.value != '' && !(tooltip.getParent() && tooltip.getParent().objectId && (tooltip.getParent().objectId.type == 'STOP' | tooltip.getParent().objectId.type == 'POI_AREA' | tooltip.getParent().objectId.type == 'POI_POINT'))) {
			var body = '<div id="' + id + '">';
			body += this.toolTip.getInnerHTML();
			body += '<br/><br/>';
			body += '<span style="float:left;">' + route + '&nbsp;</span>';
			body += '<a id="fromHere_active" style="float:left;" href="javascript:void(0);" onclick="setAddressTooltipInput(\'destination\');">' + fromHere + '</a>';
			body += '<span id="fromHere_inactive" style="display:none;float:left;">' + fromHere + '</span>';
			body += '<span style="float:left;">&nbsp;-&nbsp;</span>';
			body += '<a id="toHere_active" style="float:left;" href="javascript:void(0);" onclick="setAddressTooltipInput(\'origin\');">' + toHere  + '</a>';
			body += '<span id="toHere_inactive"  style="display:none;float:left;">' + toHere + '</span>';
			// input for second location (origin or destination) to compute a journey
			if (bubbleInput) {
				body += '<div style="clear:both;line-height:1px;">&nbsp;</div><br/>';
				body += '<div id="startLocation" style="display:none;">';
				body += startLocation;
				body += '<br/>';
				body += '<input type="text" class="bubbleLocalityInput" name="name_bubble" id="name_origin_bubble" ondblclick="this.select();"/>';
				// submit button for plone
				if(document.forms['efaRequest'])
					body += '<p class="its-efa-submit its-efa-adressBubbleButton"><input type="submit" value="' + goButton + '" class="submitButton" onclick="mdv.its.submitAdressPoiForm(\'toHere\')"/></p>';
				// normal submit button
				else
					body += '<input type="submit" value="' + goButton + '" class="submitButton"/>';
				body += '</div>';
				body += '<div id="endLocation" style="display:none;">';
				body += '<span id="bubbleTextOrigDest">' + endLocation + '</span>';
				body += '<br/>';
				body += '<input type="text" class="bubbleLocalityInput" name="name_bubble"  id="name_destination_bubble" ondblclick="this.select();"/>';
				// submit button for plone
				if(document.forms['efaRequest'])
					body += '<p class="its-efa-submit its-efa-adressBubbleButton"><input type="submit" value="' + goButton + '" class="submitButton" onclick="mdv.its.submitAdressPoiForm(\'fromHere\')"/></p>';
				// normal submit button
				else
					body += '<input type="submit" value="' + goButton + '"  class="submitButton" />';
				body += '</div>';
				body += '</div>';
			}
			this.toolTip.setInnerHTML(body);
			if (!bubbleInput) {
				var size = new MDVPoint(300, 80);
				this.toolTip.container.setSize(size);
			}
		}
		// stop, poi tooltip (not on result screen)
		else if (tooltip.getParent() && tooltip.getParent().objectId && !document.getElementById('tripSelector')) { 
			var type = tooltip.getParent().objectId.type;
			var omc = tooltip.getParent().objectId.omc;
			var body = '<div id="' + id + '">';

			body += this.toolTip.getInnerHTML();
			// marker
			if (type=='coord') {
				var size = new MDVPoint(300, 80);
				this.toolTip.container.setSize(size);
				this.toolTip.container.updateBubble();
			}
			// stop in zone 
			else if (zoneAssignedStops) {
				body += '<br/><br/>';
				body += '<a href="javascript:submitParking(\'' + id + '\', \'stop\')">' + selectStop + '</a>';
				body += '<br/><br/>';
				body += tooltipInfoGreenZone;
			}
			// stop, poi
			else {
				body += '<br/><br/>';
				body += route;
				body += '<a href="javascript:this.submitObject(\'' + id + '\',\'' + type + '\',\'' + omc + '\', 1)">' + fromHere + '</a>';
				body += ' - ';
				body += '<a href="javascript:this.submitObject(\'' + id + '\',\'' + type + '\',\'' + omc + '\', 2)">' + toHere  + '</a>';
				if (parkAndRide) {
					for (var i=0; i<parkAndRide.length; i++) {
						if (parkAndRide[i].id && parkAndRide[i].id == id) {
							body += '<br/></br>';
							body += '<a href="javascript:submitDeselectionParking(\'' + id + '\', \'stop\');">' + deselectStop + '</a>';
                        }
					}
				}
			}
            // departure monitor for stops
			if (enableDMBubble && tooltip.getParent().objectId.type == 'STOP') {
				body += '<div id=\'dmLoading_' + id +'\'>';
				body += '<br/>';
				body += dmLoading;
				body += '</div>';
			}
            // real time information for citybike
            if (isCitybike) {
                body += '<div id=\'citybikeLoading_' + id +'\'>';
				body += '<br/>';
				body += citybikeLoading;
				body += '</div>';
				//reference
				body += '<br/><div>';
				body += '<img src="' + imgPath + 'citybike_reference.gif' + '" alt="' + citybikeRef + '" style="vertical-align: text-bottom;margin-right: 5px;"/>';
				body += citybikeRef;
				body += '</div>';
            }
			body += '</div>';
			this.toolTip.setInnerHTML(body);
			// jump to journey planner if in addrress/poi input
			if (document.getElementById('currentPage').value=='address')
				document.getElementById('currentPage').value='journeyPlanner';
		}
		// result screen
		else if (tooltip.getParent() && tooltip.getParent().objectId && ((enableDMBubble && tooltip.getParent().objectId.type == 'STOP') || isCitybike)) {
			var body = '<div id="' + id + '">';
			body += this.toolTip.getInnerHTML();
            if (isCitybike) {
                body += '<div id=\'citybikeLoading_' + id +'\'>';
                body += '<br/>';
                body += citybikeLoading;
				body += '</div>';
				//reference
				body += '<br/><div>';
				body += '<img src="' + imgPath + 'citybike_reference.gif' + '" alt="' + citybikeRef + '" style="vertical-align: text-bottom;margin-right: 5px;"/>';
				body += citybikeRef;
				body += '</div>';
            }
            else {
                body += '<div id=\'dmLoading_' + id +'\'>';
                body += '<br/>';
                body += dmLoading;
            }
			body += '</div>';
			body += '</div>';
			this.toolTip.setInnerHTML(body);
		}
		this.processed = true;
		// display departure monitor for stops
		if (enableDMBubble && tooltip.getParent() && tooltip.getParent().objectId && (tooltip.getParent().objectId.type == 'STOP' || tooltip.bikeStopID)) {
			tooltip.dm = new MDVEFADepartureMonitor(id, absoluteServerPath.efa + '/parkingInfo/XML_DM_REQUEST');
			tooltip.dm.getDepartures(id);
		}
        // display realtime information for citybike POIs
        if (isCitybike) {
            tooltip.citybike = new MDVEFACitybikeInformation(id, citybikeInfo);
            tooltip.citybike.getCitybikeInformation(id);
        }
	}
	// reload park and ride bubble
	else if (tooltip.parking){
		tooltip.parking.getParkingInfo(id, tooltip.parkAndRide, tooltip.selectionLink);
	}
	// reload departure monitor
	else if (tooltip.dm) { 
		tooltip.dm.getDepartures(id);
	}
    // reload citybike realtime information
    else if (tooltip.citybike) {
        tooltip.citybike.getCitybikeInformation(id);
    }
    // resize poi tooltips (except citybike)
	else if (tooltip.getParent() && tooltip.getParent().objectId && !document.getElementById('tripSelector') && tooltip.getParent().objectId.type == 'coord') {
		var size = new MDVPoint(300, 80);
		this.toolTip.container.setSize(size);
		this.toolTip.container.updateBubble();
	}
    // resize citybike tooltip
    if (isCitybike) {
        var size = new MDVPoint(300, 200);
        this.toolTip.container.setSize(size);
        this.toolTip.container.updateBubble();
    }
}


// This function sets the focus on the text input for addres/poi screen
function setInputFocus(usage) {
	if(usage='origin' && document.getElementById('name_origin_bubble') && document.getElementById('startLocation').style.display!='none')
		document.getElementById('name_origin_bubble').focus();
	else if(usage='destination' && document.getElementById('name_destination_bubble') && document.getElementById('endLocation').style.display!='none')
		document.getElementById('name_destination_bubble').focus();
}

// This function displays the origin or destination input in the address bubble and renames interchanges origin and destination
// if necessary.
function setAddressTooltipInput (usage) {
	if(currentPage == 'address' ) {
		if (!bubbleInput) {
			var use = 1;
			if (usage == 'origin')
				use = 2;
			document.getElementById('currentPage').value = 'journeyPlanner';
			document.getElementById('nameState_origin').value = 'empty';
			document.getElementById('name_origin').value = '';
			document.getElementById('nameInfo_origin').value = '';
			document.getElementById('anyObjFilter_origin').value = '0';
			document.getElementById('anyType_origin').value = '';
			submitObject (document.getElementById('nameX_origin').value + ':' + document.getElementById('nameY_origin').value + ':' + document.getElementById('nameMapName_origin').value + ':' + document.getElementById('nameText_origin').value, 'coord', null, use);
		}
		else if (usage == 'destination') {
			// show destination input and hide origin input
			document.getElementById('endLocation').style.display='block';
			document.getElementById('startLocation').style.display='none';
			document.getElementById('fromHere_active').style.display='none';
			document.getElementById('fromHere_inactive').style.display='block';
			document.getElementById('toHere_active').style.display='block';
			document.getElementById('toHere_inactive').style.display='none';
			setInputFocus('destination');
			// preserve original input as origin
			if(document.forms[0].name_destination) {
				// the destination is now the origin (only possible if the user switches 'from here' before 'to here'
				document.forms[0].name_destination.name = 'name_origin';
				document.getElementById('type_origin').value = 'coord'; 
				// destination is entered, therefore reset the values
				document.getElementById('type_destination').value = 'any';
				document.getElementById('anyObjFilter_destination').value = '0';
				document.getElementById('anyType_destination').value = '';
				document.getElementById('nameState_destination').value = 'empty';
			}
			// convert the origin to coord input (to guarantee full hit in journey planner)
			else if (document.getElementById('nameX_origin') && document.getElementById('nameY_origin') && document.getElementById('nameMapName_origin') && document.getElementById('nameText_origin').value) {
				document.forms[0].name_origin.value = document.getElementById('nameX_origin').value + ':' + document.getElementById('nameY_origin').value + ':' + document.getElementById('nameMapName_origin').value + ':' + document.getElementById('nameText_origin').value;
				document.getElementById('type_origin').value = 'coord';
			}
			// hide origin input and show destination input: elements must be renamed to prevent from having two name_origin parametrs 
			document.getElementById('name_origin_bubble').name = 'name_bubble';
			document.getElementById('name_destination_bubble').name = 'name_destination';	
		}
		else if (usage == 'origin') {
			// show origin input and hide destination input
			document.getElementById('startLocation').style.display='block';
			document.getElementById('endLocation').style.display='none';
			document.getElementById('fromHere_active').style.display='block';
			document.getElementById('fromHere_inactive').style.display='none';
			document.getElementById('toHere_active').style.display='none';
			document.getElementById('toHere_inactive').style.display='block';
			setInputFocus('origin');
			// preserve original input as destination
			if (document.forms[0].name_origin) {
				// the former origin is now the destination. if not converted to coordinate format, convert now.
				document.forms[0].name_origin.name = 'name_destination';
				if (document.getElementById('nameX_origin') && document.getElementById('nameY_origin') && document.getElementById('nameMapName_origin') && document.getElementById('nameText_origin').value) {
					document.forms[0].name_origin.value = document.getElementById('nameX_origin').value + ':' + document.getElementById('nameY_origin').value + ':' + document.getElementById('nameMapName_origin').value + ':' + document.getElementById('nameText_origin').value;
				}
				document.getElementById('type_destination').value = 'coord';
				// origin is entered, therefore reset the values
				document.getElementById('type_origin').value = 'any';
				document.getElementById('anyObjFilter_origin').value = '0';
				document.getElementById('anyType_origin').value = '';
				document.getElementById('nameState_origin').value = 'empty';
			}
			// hide origin input and show destination input: elements must be renamed to prevent from having two name_destination parametrs 
			document.getElementById('name_origin_bubble').name = 'name_origin';
			document.getElementById('name_destination_bubble').name = 'name_bubble';
		}
		document.getElementById('nameState_origin').value = 'empty';
		document.getElementById('nameState_destination').value = 'empty';
		// jump to journey planner
		if (document.getElementById('currentPage').value=='address')
			document.getElementById('currentPage').value='journeyPlanner';
	}	
}


// Set the parameters for the request and submits the form.
function submitObject (id, type, omc, usage) {
	var prefix = '';

	if (type == 'POI_POINT' || type == 'POI_AREA') 
		type= 'poiID';
	else if (type == 'STOP') 
		prefix = 'stopID:';
		
	switch (type) {
		case 'coord':
			var postfix;
			if(usage == 2) 
				postfix = 'destination';
			else 
				postfix = 'origin';
			document.getElementById('nameInfo_' + postfix).value = id; 
			document.getElementById('typeInfo_' + postfix).value = 'coord';
			break;
		case 'poiID':
			id = id.substr(id.indexOf('-') + 1);
			if(usage == 2) 
				document.forms[0].placeInfo_destination.value = omc + ':-1';
			else 
				document.forms[0].placeInfo_origin.value = omc + ':-1';
			// do default
		default:	
			if(usage == 2) {
				document.forms[0].typeInfo_destination.value = type;
				document.forms[0].nameInfo_destination.value = prefix + id;
			}

			else {
				document.forms[0].typeInfo_origin.value = type;
				document.forms[0].nameInfo_origin.value = prefix + id;
			}
	}
	// store map centre and zoomlevel
	storeMapCentreAndZoomlevel();
	
	if (document.forms[0].execInst)
		document.forms[0].execInst.value = 'verifyOnly';	

	document.forms[0].submit();
};


// This function selects a park and ride parking.
function submitParking (id, mode) {
	// stop of green zone
	if (mode=='stop')
		document.forms[0].selPAStop.value = id;
	// parking
	else if (document.forms[0].selPA) 
		document.forms[0].selPA.value = id;
	// parking after monomodal journey 
	if (currentPage=='journeyPlanner') {
		document.forms[0].command.value = 'mono2PR';
		document.forms[0].paID.value = id;
		document.forms[0].maxMonoTWoPT.value = '15';
		document.forms[0].itdLPxx_odvIdentified.value = '1';
		document.forms[0].itdLPxx_currentPage.value = 'parkAndRidePlanner';
		document.forms[0].direct.value = '1';
	}
	document.forms[0].execInst.value='';
	document.forms[0].submit();
}

// This function deselects a park and ride parking
function submitDeselectionParking (id, mode) {
	// stop of green zone
	if (mode == 'stop')
		document.forms[0].deselPAStop.value = id;
	// parking
	else if (document.forms[0].deselPA) {
		document.forms[0].deselPA.value = id;
	}
	document.forms[0].execInst.value='';
	document.forms[0].submit();
}


// ==================================================================
// Trip request context menu functions.
// ==================================================================

// The context menu handler gets the mouse coordinates and the centre coordinates 
// when on origen/destination was selected via context menu. The centre coordinates 
// are useful to set the origin/destination marker on the clicked point. 
function ContextMenuHandler(id, status, obj) {
	if(status == true) {
		ctxCoords = obj;
	}
}


// This context menu functions submits a selected point.
MDVMapHelper.prototype.setCoordinatesOrigin = function() {
	setCoordinates('origin');
};


MDVMapHelper.prototype.setCoordinatesDestination = function() {
	setCoordinates('destination');
};


function setCoordinates(usage) {
	if (mdvMap.mdvMap) {
		// text displayed in the GUI
		var text = mapOrigin;

		if(usage=='destination')
			text = mapDestination;
		
		document.getElementById('nameInfo_' + usage).value = parseInt(ctxCoords.x) + ':' + parseInt(ctxCoords.y) + ':' + ctxCoords.mapName + ':' + text; 
		// store coordinates and type
		document.getElementById('typeInfo_' + usage).value = 'coord';
		document.getElementById('nameState_' + usage).value = 'notidentified';
		if (document.getElementById('placeState_' + usage))
			document.getElementById('placeState_' + usage).value = 'notidentified';
		if (document.getElementById('placeInfo_' + usage))
			document.getElementById('placeInfo_' + usage).value = '';
		
		mdvMap.mdvMap.mapper.style.cursor = 'wait';
		// store zoomlevel and centre coordinates
		storeMapCentreAndZoomlevel();
		document.getElementById('execInst').value = 'verifyOnly';
		if (document.getElementById('currentPage').value=='address')
			document.getElementById('currentPage').value = 'journeyPlanner';
		// deselect parking if new destination selected
		if (document.getElementById('paID') && usage=='destination') {
			document.getElementById('paID').value='';
			document.getElementById('itdLPxx_paID').value='';
		}
		document.forms[0].submit();
	}
};	


// ===============================================================================
// Departure monitor (in tooltip) 
// ===============================================================================

// Departure monitor
function MDVEFADepartureMonitor(id, url) {
	this.id 		= id;
	this.url 		= url;
}


// Request departure monitor.
// Parmeter:	identifier - id of the tooltip content container
MDVEFADepartureMonitor.prototype.getDepartures = function(identifier) {
	var _params = { useRealtime: 1, language: mapLanguage, itdLPxx_id: identifier, name_dm: this.id, type_dm: 'stopID', mode: 'direct', limit: dmBubbleNoDep, itdLPxx_MOTImages: dmBubbleMOTImg, itdLPxx_enableMOTText: dmBubbleMOTText, itdLPxx_imgPath: imgPath, ts: new Date().getTime()};
	var ajax = mdvLib.ajax({ host: this.url, parameters: _params, method: 'get', onComplete: MDVEFADepartureMonitor_onAjaxComplete });
}


// Create departure monitor. 
function MDVEFADepartureMonitor_onAjaxComplete(request) {
	if (request && request.responseXML) {
		var firstChild = request.responseXML.firstChild;
		var text = request.responseText;

		while (firstChild.nodeType != 1) 
			firstChild = firstChild.nextSibling;
		
		var id = firstChild.getAttribute('id');
		var target = document.getElementById('dmLoading_' + id);
		if (target) {
			target.innerHTML = '<br/>' + text; 
        }
		else {
			target = document.getElementById(id);
			if (target) {
				target.innerHTML += '<br/><br/>' + text; 
            }
		}
	}
}


// ==================================================================
// Parking search for monomodal car journeys.
// ==================================================================

// Parking search
function MDVEFAParkingSearch(url) {
	this.url 	= url;
}


// Search park objects.
MDVEFAParkingSearch.prototype.getParkings = function(parkingSearchCenter) {
	var _params = { type_origin: 'coord', name_origin: parkingSearchCenter, parkingType: 'nearStart', parkingObjectType: '3', parkingMaxSizeHitList: parkingMaxSizeHitListValue, parkingMaxDistance: parkingMaxDistanceValue, parkingSearchMethod: 'radialEscalation'};
	var ajax = mdvLib.ajax({host: absoluteServerPath.virtDir + this.url, parameters: _params, method: 'get', onComplete: MDVEFAParkingSearch_onAjaxComplete });
}


// Displays the parkobjects on the map.
// Ajax request response: two dimensional array - each parking object contains 0. ID, 1. type, 2. x coordinate, 3. y coordinate, 4. map name, 5. parking name. 
function MDVEFAParkingSearch_onAjaxComplete(request) {
	if (request && request.responseText) {
		var size = new MDVPoint(300, 200);
		var response = request.responseText.split('++');

		for (var i=1; i < response.length; i++) {
            if (response[i] === '') {
                continue;
            }
            response[i] = response[i].split(':');
			var position = new MDVCoordinates(response[i][4], parseInt(response[i][2]), parseInt(response[i][3]));
			if (response[i][1] == '1') {
				if (response[i][6] == '1'){
					mdvMap.marker = mdvMap.mdvMap.createMarker(position, 0.5, imgPath + 'parkAndRideRealtime.gif');
				}
				else {
					mdvMap.marker = mdvMap.mdvMap.createMarker(position, 0.5, imgPath + 'parkAndRide.gif');
				}	
			}
			else
				if (response[i][6] == '1'){
					mdvMap.marker = mdvMap.mdvMap.createMarker(position, 0.5, imgPath + 'garageRealtime.gif');
				}
				else {
					mdvMap.marker = mdvMap.mdvMap.createMarker(position, 0.5, imgPath + 'garage.gif');
				}
			var tool = mdvMap.mdvMap.createToolTip(size,'<b>' + response[i][5] + '</b>');
			tool.parkingSearch = true;
			tool.selectionLink = true;
			tool.parkAndRide = response[i][0];
			mdvMap.marker.setToolTip(tool);
			mdvMap.parkAndRideLayer.addMarker(mdvMap.marker);
			mdvMap.marker.toolTip.setPin(true);
		}
		mdvMap.mdvMap.update();
	}
}


// ===============================================================================
// Citybike realtime information (in tooltip) 
// ===============================================================================

// Citybike realtime information
function MDVEFACitybikeInformation(id, url) {
	this.id 		= id;
	this.url 		= url;
}


// Request citybike realtime information.
// Parmeter:	identifier - id of the tooltip content container
MDVEFACitybikeInformation.prototype.getCitybikeInformation = function(identifier) {
	var _params = { ts: new Date().getTime() };
	var ajax = mdvLib.ajax({ host: absoluteServerPath.efa + '' + this.url, parameters: _params, method: 'get', onComplete: this.citybikeInformationOnComplete.bind(this) });
}


// Create city bike information. 
MDVEFACitybikeInformation.prototype.citybikeInformationOnComplete = function(response) {
	var json;
	var _response = response.responseText || response;
	eval('json=' + _response + ';');
    var id = this.id;
    var tmp = this.id.split('-');
    if (tmp[1] != '') {
        id = tmp[1];
    }
    
	for (var i=0; i < json.length; i++) { 
		if (json[i].id == id) {
            var text = '';
            if (json[i].info.length > 0) {
                text = '<table class="its_citybike">';
                for (var j=0; j < json[i].info.length; j++) {
                    text += '<tr>';
                    text += '<td class="its_citybikeLabel">' + json[i].info[j].name + ': </td>';
                    text += '<td>' + json[i].info[j].value + '</td>';
                    text += '</tr>';
                }   
                text += '</table>';
            }
            var target = document.getElementById('citybikeLoading_' + this.id);
            if (target) {
                target.innerHTML = '<br/>' + text; 
            }
            else {
                target = document.getElementById(id);
                if (target) {
                    target.innerHTML += '<br/><br/>' + text; 
                }
            }
        }
	}
}


// ==================================================================
// Stop search for bike & ride and take bike along.
// ==================================================================

function MDVEFABikeStopSearch (url) {
	this.url 				= 'XSLT_TRIP_REQUEST';
	this.sessionID			= document.getElementById('sessionID').value;	
	this.requestID			= document.getElementById('requestID').value;
}


// Click on bike and ride option: get stops or display stops layer.
MDVEFABikeStopSearch.prototype.verifyBikeAndRide = function() {
	if (bikeStopRequest == 'true') {
		// request bike stops (initial)
		if (!bikeStopLayerInit) {
			// TODO: Warum muss man hier noch mal einen Request abschicken? Falls nicht kommen zu viele Hst.
			document.getElementById('execInst').value = 'verifyOnly';
			document.forms[0].submit();
		}
		// show hidden layer with bike stops
		else if (mdvMap.bikeStopLayer){
			mdvMap.bikeStopLayer.setVisibility(true);
		}
	}
}


// Stop search ajax request.
MDVEFABikeStopSearch.prototype.getBikeStops = function() {
	// request stops if they have not been requested yet
	if (!bikeStopLayerInit) {
		// set state of bike stop layer 
		bikeStopLayerInit = true;
		// ajax request
		var _params = { language: mapLanguage, sessionID: this.sessionID, requestID: this.requestID, itdLPxx_view: 'bikeStopSelection', execInst: 'verifyOnly', selectAssignedStops4Journey_origin: 1, selectAssignedStops_origin: 1};
		var ajax = mdvLib.ajax({host: absoluteServerPath.virtDir + this.url, parameters: _params, method: 'get', onComplete: MDVEFABikeStopSearch_onAjaxComplete });
	}
}


// Displays the stops on the map.
// Ajax request response: two dimensional array - each parking object contains 0. ID, 1. x coordinate, 2. y coordinate, 3. map name, 4. stop name. 
function MDVEFABikeStopSearch_onAjaxComplete(request) {
	if (request && request.responseText) {
		var response = request.responseText.split('++');
		var size = new MDVPoint(300, 200);
		var zl = 4;
		// display stops
		for (var i=1; i < response.length; i++) {
			response[i] = response[i].split(':');
			var position = new MDVCoordinates(response[i][3], parseInt(response[i][1]), parseInt(response[i][2]));
			mdvMap.marker = mdvMap.mdvMap.createMarker(position, 0.5, imgPath + 'stop.gif');
			var tool = mdvMap.mdvMap.createToolTip(size,'<b>' + response[i][4] + '</b>');
			tool.bikeStopID = response[i][0];
			tool.bikeStopName = response[i][4];
			mdvMap.marker.setToolTip(tool);
			mdvMap.bikeStopLayer.addMarker(mdvMap.marker);
		}
		// center on origin
		mdvMap.mdvMap.setCentre (new MDVCoordinates(nameMap, parseInt(document.getElementById('nameX_origin').value), parseInt(document.getElementById('nameY_origin').value)));
		mdvMap.mdvMap.setZoomLevel(zl);
		mdvMap.mdvMap.update();
	}
}


// Hide bike stops layer if it contains stops.
MDVEFABikeStopSearch.prototype.hideBikeStops = function() {
	if (bikeStopLayerInit) {
		// hide bike stop layer
		mdvMap.bikeStopLayer.setVisibility(false);
	}
}


// selectes a stop with bike & ride or take bike along access
function submitBikeStop (id, name) {
	document.getElementById('assignedStop_origin').value = id + ':' + name;
	document.getElementById('selectAssignedStop4Journey_origin').value = 1;
	document.getElementById('selectAssignedStops_origin').value = 1;
	// store map centre and zoomlevel
	storeMapCentreAndZoomlevel();
	document.forms[0].submit();
};


// ==================================================================
// Map output functions.
// ==================================================================

// This function displays a journey on the map.
MDVMapHelper.prototype.displayJourney = function(sessionID, requestID, tripIndex) {
	if (tripIndex && tripIndex != '') {
		this.trips.loadTrip(sessionID, requestID, tripIndex, true);
	}
	else if (document.getElementById('itdLPxx_displayJourney') && document.getElementById('itdLPxx_displayJourney').value != '') {
		var tripInd = document.getElementById('itdLPxx_displayJourney').value;
		this.trips.loadTrip(sessionID, requestID, tripInd, true);
	}
}


// This function clears all journeys on the map.
MDVMapHelper.prototype.clearJourney = function() {
	this.trips.clear();
}


// This function displays the IT ICS Messages on the map 
function displayItICSMessages (mot, state) {
	mdvMap.displayITEvents(mot);
	if (document.getElementById('itdLPxx_showICSMsg'))
		document.getElementById('itdLPxx_showICSMsg').value = 'true';
}


// This function hides the IT ICS Messages on the map 
function hideItICSMessages () {
	mdvMap.blockingsLayer.removeAllMarkers();
	mdvMap.roadWorksLayer.removeAllMarkers();
	mdvMap.informationLayer.removeAllMarkers();
	if (document.getElementById('itdLPxx_showICSMsg'))
		document.getElementById('itdLPxx_showICSMsg').value = 'false';

}


// This function checkes it the message is valid for a certain mean of transport.
function checkMessageMOT (mot, messageType) {
	var returnValue = false ;

	// test
	if (messageType=='unknown' || messageType=='allUser' || (mot=='100' && messageType=='pedestrian') || 
		(mot=='106' && (messageType=='allMotorizedUsers' || messageType=='car' || messageType=='lorry' || messageType=='motorCar' || messageType=='passengerCar' || messageType=='highOccupncyVehicle' || messageType=='emergencyVehicle' || messageType=='taxi' || messageType=='deliveryTruck' || messageType=='coach' || messageType=='publicBus')) ||
		(mot=='107' && messageType=='bicycle')) {
		returnValue = true;
	}
	
	return returnValue;
}


// ==================================================================
// Overwritten map functionality.
// ==================================================================

// Changed: Load stops assigned to zone.
MDVMapEFAInfoEx.prototype.fetchPins = function() {
	// Get Pins for current position & zoom level.
  	if (this.mdvMap.config.get('efaURL') && !(zoneAssignedStops && !document.getElementById('parkingTypeZone').checked) && showBikeStops != 'true') {
  		var host   = this.mdvMap.config.get('efaURL');
  		var centre = this.mdvMap.getCentre();
  		var language = this.mdvMap.config.get('language') != null ? this.mdvMap.config.get('language') : 'en';
  		var zoomLevel = this.mdvMap.config.getZoomLevel(this.mdvMap.config.getZoomLevelIndex());
  		var isLast = this.mdvMap.config.getZoomLevel(parseInt(this.mdvMap.config.getZoomLevelIndex())+1) == null;
  		var isOneBeforeLast = this.mdvMap.config.getZoomLevel(parseInt(this.mdvMap.config.getZoomLevelIndex())+2) == null && this.mdvMap.config.getZoomLevel(parseInt(this.mdvMap.config.getZoomLevelIndex())+1) != null;
  		var showStops = zoomLevel.get('showSTOP') == "true" && this.stops.visible ? 1 : 0;
  		var showPOI   = zoomLevel.get('showPOI') == "true" && this.poi.visible && (!zoneAssignedStops || !document.getElementById('parkingTypeZone').checked) ? 1 : 0;
  		var poiArea = this.mdvMap.config.get('poiArea') =="true";
  		var poiPoint = this.mdvMap.config.get('poiPoint')=="false";  		  		
  		var vpReal = this.mdvMap.getViewportRealExtends();
  		var radius = Math.floor(0.5 + Math.sqrt((Math.pow(vpReal.width/2, 2) 
  			+ Math.pow(vpReal.height/2, 2))));
		var _params = { language: language, coord: Math.floor(centre.x + 0.5) + ':' + Math.floor(centre.y + 0.5) + ':' 
			+ centre.mapName, inclFilter: 1, purpose: '', max: -1, coordListFormat: 'STRING', 
			language: 'en', itdLPxx_mdvMapName: 'mdvMap_' + this.mdvMap.getName(), coordListOutputFormat: 'STRING' };
		var ifilter = 1;
	
		if (showStops) {
			var temp = '';
			if (zoomLevel.get('showSTOP.majorMeans')) {
				temp = zoomLevel.get('showSTOP.majorMeans');
			}
			_params['type_' + ifilter] = 'STOP';
			_params['radius_' + ifilter] = radius;
			_params['inclDrawClasses_' + ifilter] = temp;
			if(zoneAssignedStops && document.getElementById('parkingTypeZone').checked) {
				var parkingCharge = 'undefined';
				if (document.getElementById('parkingCharge'))
					parkingcharge = document.getElementById('parkingCharge').value;
				// display only stops in zones
				//_params['fltrParkObj'] = 1;
				_params['parkingCharge'] = parkingCharge;
			}
			ifilter++;
			if ((isLast || isOneBeforeLast) && !this.stopsOnly) {
				temp = '';
				if (isLast) {
					_params['type_' + ifilter] = 'ENTRANCE';
					_params['radius_' + ifilter] = radius;
					_params['inclDrawClasses_' + ifilter] = temp;
					ifilter++;
				}
				temp = '';
				_params['type_' + ifilter] = 'BUS_POINT';
				_params['radius_' + ifilter] = radius;
				_params['inclDrawClasses_' + ifilter] = temp;
				ifilter++;
			}
		}
		if (showPOI) {
			var temp = '';

			// All POI DrawClasses
			for (var ii=39; ii <= 80; ii++) {
				temp += ii + ':';
			}
			if(poiArea) {
				temp ='';
				_params['type_' + ifilter] = 'POI_AREA';
				_params['radius_' + ifilter] = radius;
				_params['inclDrawClasses_' + ifilter] = temp;
				ifilter++;
			}
			if(!poiPoint) {
				temp ='';
				_params['type_' + ifilter] = 'POI_POINT';
				_params['radius_' + ifilter] = radius;
				_params['inclDrawClasses_' + ifilter] = temp;
				ifilter++;
			}
			if (this.options && this.options.pools) {
				for (pl in this.options.pools) {
					_params['type_' + ifilter] = pl;
					_params['radius_' + ifilter] = radius;
	
					if (this.options.pools[pl].inclDrawClasses && this.options.pools[pl].inclDrawClasses.length > 0)
						_params['inclDrawClasses_' + ifilter] = this.options.pools[pl].inclDrawClasses;
	
					if (this.options.pools[pl].exclLayers && this.options.pools[pl].exclLayers.length > 0)
						_params['exclLayers_' + ifilter] = this.options.pools[pl].exclLayers;
					ifilter++;
				}
			}
		}
		var _ajax = mdvLib.ajax({ host: host, parameters: _params, onComplete: MDVMapEFAInfoEx_onAjaxComplete });
  	}
} 

  
MDVMapSyncBound.prototype.destroy = function() {
    this.mdvMiniMap.viewport.removeChild(this.border);
    
    if (this.mdvMap) {
 		this.mdvMap = null;
    }
	this.ondblclick = null;
	this.onkeypress = null;
	this.onmousedown = null;
	this.onmousemove = null;
	this.onmouseout = null;
	this.onmouseover = null;
	this.onmouseup = null;
	this.onmousewheel = null;
	this.oncontextmenu = null;
};


// Changed: Parkobject image  
MDVMapEFATrips.prototype.getMarker = function(type, usage, coords, alignment, pos) {
  	var src = '';
  	
	if (type >= 100 && this.imgs[type + '_' + usage] && this.imgs[type + '_' + usage].complete) {
		if (type == 104 && parkAndRideObj) {
			src = imgPath + 'mot104_parkAndRide_' + usage + '.gif';
		}
		else if (type == 104) {
			src = imgPath + 'mot104_parking_' + usage + '.gif';
		}		
		else {
			src = this.imgs[type + '_' + usage];
		}
	}
	else if (this.imgs[type]) {
		if (type == 104 && parkAndRideObj) {
			src = imgPath + 'mot104_parkAndRide.gif';
		}
		else if (type == 104) {
			src = imgPath + 'mot104_parking.gif';
		}
		else {
			src = this.imgs[type];
		}
		src = this.imgs[type];
	}
	else
		src = this.imgs['stop'];

	if (type == 104) {
		var m = this.mdvMap.createMarker(coords, alignment, src);
	}
	else {
		var m = this.mdvMap.createMarker(coords, alignment, src.src);
	}
			
  	return m;
}
  
  
// Changed: Set z-index of animation images 
MDVLayer.prototype.addMarker = function(marker) {
	var update = true;
	for (var m=0; m < this.markers.length; m++) {
		if (this.markers[m].id == marker.id) {
			return false;
		}
	}
	
	if (arguments.length == 2)
		update = arguments[1];

	marker.layer = this;
	
	this.markers.push(marker);		
	marker.img.src = marker.imgSrc;
	
	if (marker.imgSrc && marker.imgSrc.indexOf('_follow')) 
		marker.img.style.zIndex = '16';
















	
	return true;
}



