/**
*   @desc Script to add javascript files dynamicly. Hard coded for controls.
**/
function cAddScript() {    
    
    this.load = function(sType){    
        this.s = document.createElement('script'); 
        this.s.type = 'text/javascript'; 
        this.s.src = this.getSrc(sType);
        document.getElementsByTagName('head')[0].appendChild(this.s);    
        
        this.s.onload = function(){
            oGeoStart.displayControls();
        };
        this.s.onreadystatechange = function(){
            oGeoStart.displayControls();
        };
    };
    
    
    this.getSrc = function(sType){
        switch ( sType ) {
            case 'small':
                return 'GeoStart/libs/mapcontrols/default_minicontrols.js';
            default:
                return 'GeoStart/libs/mapcontrols/default_greycontrols_terrain.js';
        }
    };
};/**
*   Class for GeoCode query and returning results.
*   @Notes: showPlace: Might need to put this function in cMapObjects and refer to cMapObjects from here.
*   @class 
**/
function cGeoSearch(){
    /**
    *   Initialize the object.
    *   @param Object GMap2 object.
    *   @param Element Element to load search results into
    **/
    this.init = function(oMap, eGeoSearch){

        this.oCoder = new GClientGeocoder();
        this._oMap = oMap;
        this._searchDiv     = eGeoSearch            ||  $('GeoCode_search') || null;
        this._sBaseCity     = oSettings._sBaseCity;
        // this._sBaseProvince = _sProvince            ||  'Zuid Holland';
        this._sCountryCode  = oSettings._sCountryCode;
        this.oCoder.setBaseCountryCode(this._sCountryCode);

    };
    
    /**
    *   Place temporary marker. Also add listener to marker to remove when infowindow is closed.
    *   @note: Shouldn't we put this in MapObjects
    *   @param i Placemark ID
    *   @private
    **/
    this.showPlace = function(i){
        // Open info window       
        var point = new GLatLng(this._oResult.Placemark[0].Point.coordinates[1], this._oResult.Placemark[0].Point.coordinates[0]);
        
        oGeoStart.checkZoom();
        this._oMap.setCenter(point, this._oMap.getZoom());
        this._oMap.openInfoWindowHtml(point, this._oResult.Placemark[i].address.split(',')[0]);
    };
    
    /**
    *   Asychronous call to GeoCoder.
    *   @param sSearch Search string
    **/
    this.getSearch = function(sSearch){
        var self = this;
        
        if ( sSearch.length > 3 ) {
            this.oCoder.getLocations(sSearch + ', ' + self._sBaseCity, function(oResult){
                if ( oResult.Status.code == G_GEO_SUCCESS ) {
                    oGeoStart.oSearch._oResult = oResult;
                    oGeoStart.oSearch.loadResult();
                } else {
                    oGeoStart.oSearch.cleanResult();
                }
            });
        } else {
            oGeoStart.oSearch.cleanResult();
        }
    };
    
    /**
    *   Load result into div.
    *   Currently uses strict layout, no template
    *   @private
    **/    
    this.loadResult = function(){
        var bGotResults = false;
        var sResult = '';
        var iLength = this._oResult.Placemark.length;
        
        if ( iLength > 3  ) iLength = 3;
        
        for (i=0; i<iLength; i++) { 
            var aInfo = this._oResult.Placemark[i].address.split(',');

            if ( this._oResult.Placemark[i].AddressDetails.Country.CountryNameCode == this.oCoder.getBaseCountryCode() ) {
                sResult += oGeoStart.html.htmlSingleSearchResult(i, aInfo);
                bGotResults = true;
            }
        }
        
        if ( bGotResults === true ) {
            if ( this._searchDiv == null ) {
                this._searchDiv = $('GeoCode_search');
            }
            this._searchDiv.innerHTML = sResult;
        }
    };
    
    /**
    *   Clean up if empty set.
    *   @private
    **/
    this.cleanResult = function(){
        if ( this._searchDiv == null ) {
            this._searchDiv = $('GeoCode_search');
        }
        this._searchDiv.innerHTML = '';
    };
};
/** 
 * @fileoverview GeoStart klasse. Verantwoordelijk voor het sturen van alle functinaliteit.
 *
 * @author Bjorn Brala bjorn@swis.nl
 * @version 3.01b
 */
 

// set maximum zoomlevels             

G_NORMAL_MAP.getMaximumResolution = function () { return 14};



/**
 * Construct the MapObjects object
 * @class cGeoStart class
 * @constructor
 */
 function cGeoStart(){
    /************************************************
    *                                               *
    *    Initialisation, listeners and settings.    *
    *                                               *
    ************************************************/
        /** 
        *   Initiazlize the map  
        *   @param {string} sMapid Name of map div
        *   @param {float} fLat latitute of startpoint
        *   @param {float} fLon longitute of startpoint
        *   @param {int} iZoom default zoom level
        **/     
        this.init = function(sMapId, fLat, fLong, iZoom){
            this.oMap = new GMap2(document.getElementById(sMapId));

            cGeoStartPoly.apply(this, []); // Extend with poly objects
            
            /** Array met mapcontrols **/
            this.aControls      = [];
            
            /** Huigige lat **/
            this._fLat = parseFloat(fLat);                      // Start viewport
            /** Huigige long **/
            this._fLng = parseFloat(fLong);                     // |
            /** Huigige zoom**/
            this._iZoom = parseInt(iZoom, 10);                  // |
            
            this.loadSettings();                                // Load map specific settings
            this.loadListeners();                               // Load map listeners

            
            if ( this._bPreloaderEnabled ){
                /** Preloader object {@link cPreloader} **/
                this.oPreloader = new cPreloader(this.oMap);    // Preloader
                this.oPreloader.init(this.oMap, 248);                // Bind to map object                
            }
            
            /** Category state array. Filled with category visibility. **/
            this.aCategorystate = [];                  
            
            // Object contains all geometry objects
            this.oPoints        = {};                 
            
            //this._oTooltip = document.getElementById('GeoTooltip'); // Tooltip element
            
            /** Tooltip object ( {@link cTooltip} ) **/
            this._oTooltip = new cTooltip(this.oMap, 'GeoTooltip', 22, 22, 2, 3);
            
            
            this._bUpdateWaiting = false;                       // Set queue to clean
                                            
            this.loadObjects();                                 // Start loading of markers in current view
            this.aCategorystate = this._oMenu.getCatStates();
        };
        
        
        /**
        *   @desc Init geheel clean, zo min mogelijk laden. Geen data laden.
        *   @param sMapId Id van de map div
        *   @param fLat Start latitude
        *   @param fLong Start longlitude
        *   @param iZoom Start zoom niveau
        *   @param {Object} mapOptions Eventuele mapopties (<a target"_blank" href="http://code.google.com/intl/nl/apis/maps/documentation/reference.html#GMapOptions">GMapOptions</a>)
        **/
        this.cleanInit = function(sMapId, fLat, fLong, iZoom, mapOptions){
            var opts = mapOptions || {};
            /**
            *   GMap2 object, standard google map
            **/
            this.oMap = new GMap2(document.getElementById(sMapId), mapOptions);
            
            this._fLat = fLat;                      // Start viewport
            this._fLng = fLong;                     // |
            this._iZoom = iZoom;                    // |
            
            this.oMap.setCenter(new GLatLng(this._fLat, this._fLng), this._iZoom); 
            
            this.oMap.enableContinuousZoom();
        };

        
        /**
        *    Load settings for the map.
        **/
        this.loadSettings = function(){
            // ms Interval per group of objects
            this._iLoadInterval    = 100;      
            // Objects per load 
            this._iLoadStep        = 5;        
            
            // Que next update call. True: update, False: do nothing
            this._bQueueLastRequest = true;     
                                                
            // Enable preloader
            this._bPreloaderEnabled = oSettings._bPreloaderEnabled;              
            // Enable hover (tooltips)
            this._bEnableHover      = oSettings._bEnableHover;                   
            // Enable balloon
            this._bEnableBalloon    = this._bEnableBalloon          || 'true';   
            
            // Preferred zoom level. Map will zoom here if a marker isnt loaded and the default zoom for the marker is below the treshhold defined here.            
            this._iPreferredZoom    = parseInt(oSettings._iPreferredZoom, 10);       
                                                
            // Category key in database
            this._sCategoryKey = 'sg_id';       
            
            // Wip 2.1 Filters
            // Initialize filter palceholders.
            // Use: 
            //      this.createFilter(sKey)
            //      this.removeFilter(sKey)
            //      this.addFilterItem(sKey, sValue)
            //      this.removeFilterItem(sKey, sValue)
            this._aGeoFilterKeys = [];                 
            // Wip 2.1 Filters
            // Initialize filter palceholders.
            // Use: 
            //      this.createFilter(sKey)
            //      this.removeFilter(sKey)
            //      this.addFilterItem(sKey, sValue)
            //      this.removeFilterItem(sKey, sValue)
            this._aGeoFilterState = [];
                        
            // Relative URL for GeoStart data requests            
            this._sDataUrl = 'GeoStart/ajax/getData.php';    
            
            /**
            *   Menu object {@link cMenu}
            **/
            this._oMenu = oMenu;                
            
            this.oMap.setCenter(new GLatLng(parseFloat(this._fLat), parseFloat(this._fLng)), parseInt(this._iZoom, 10), eval(oSettings.map_default_type)); 

            this.oMap.enableScrollWheelZoom();    // Enable scroll wheel zoom.
            
            /**
            *   Powered by geostart
            **/            
            this.oMap.addControl(new powered_by_geostart(this.oMap));
            
            /**
            *   Load map controls.
            **/            
            this.loadControls('default');
            
            this.oMap.enableContinuousZoom();
            
        };
        
        /**
        *   Display different controls on the map.
        *   @param sSet Welke set met controls moet geladen worden
        **/
        this.loadControls = function(sSet){
            if ( this.sCurrentControlSet != sSet ) {
                this.sCurrentControlSet = sSet;
                
                //this.displayControls();
            }        
        };
        
        /**
        *   @desc Add controls to the map and save the controls in {@link cGeoStart#aControls}
        *   @private
        **/
        this.displayControls = function(){                
        
                if ( this.aControls.length > 0 ) {
                    this.removeCurrentControls();
                }               
                
                switch ( this.sCurrentControlSet ) {        
                    case 'none':
                        break;            
                    case 'small':
                        var eZoomControl = new Mini_control_grey_zoom(this.oMap);
                        this.oMap.addControl(eZoomControl); 
                        this.aControls.push(eZoomControl);
                            
                        var eKaartControl = new Mini_control_grey_left(this.oMap);
                        this.oMap.addControl(eKaartControl);  
                        this.aControls.push(eKaartControl);                        
                        
                        var eSatControl = new Mini_control_grey_right(this.oMap);
                        this.oMap.addControl(eSatControl);  
                        this.aControls.push(eSatControl);                        
                
                        break;
                    default:
                        /** Map controls **/
                        var eZoomPanControl = new Control_grey_panzoom(this.oMap);
                        this.oMap.addControl(eZoomPanControl); 
                        this.aControls.push(eZoomPanControl);
                            
                        var eKaartControl = new Control_grey_center(this.oMap, 'Kaart');
                        this.oMap.addControl(eKaartControl);  
                        this.aControls.push(eKaartControl);
                            
                        var eSatellietControl = new Control_grey_right(this.oMap, 'Satelliet');
                        this.oMap.addControl(eSatellietControl); 
                        this.aControls.push(eSatellietControl);
                        
                        var eHistoryControl = new Control_grey_center_left(this.oMap, 'Terrein');
                        this.oMap.addControl(eHistoryControl); 
                        this.aControls.push(eHistoryControl);                        
                        
                        var eHelpControl = new Control_grey_left(this.oMap, 'Help');
                        this.oMap.addControl(eHelpControl);  
                        this.aControls.push(eHelpControl);
                        break;
                }
        };
        
        /**
        *   remove current controls from the map in preperation of loading new controls
        **/ 
        this.removeCurrentControls = function(){
            var i = this.aControls.length;
            while ( i-- ) {
                this.oMap.removeControl(this.aControls[i]);
            }            
        };

    
    /************************************************
    *                                               *
    *    Data handling.                             *
    *                                               *
    ************************************************/
        /**
        *    Handle the loading of data.
        *        - Check if currently loading, if so set queued request to true.
        *        - Generate get string for bounds + zoom
        *        - Call GDownloadUrl for asynchronous data request
        **/
        this.loadObjects = function(){
            if ( !this.isBusy() ) {                     // If no update is running.
                
                if ( this._bPreloaderEnabled ) {        // Check if Preloader is enabled.
                    this.oPreloader.start();            // Initialize the preloader 
                }
                this.bRemoving = true;                    // Update status, set object to busy removing
                this.bAdding = true;                    // and adding.
                
                var bounds = this.oMap.getBounds();        // Save current bounds
                var iZoom = this.oMap.getZoom();        // Save current zoom
                
                
                if ( oMenu ) {
                // Generate the $_GET string for _sDataUrl
                    var sGet = "?cats=" + oMenu.getCheckBoxDataString() + "&nelng=" + ( bounds.getNorthEast().lng() ) + "&nelat=" + ( bounds.getNorthEast().lat() ) + "&swlng=" + ( bounds.getSouthWest().lng() ) + "&swlat=" + ( bounds.getSouthWest().lat() ) + "&iZoom=" + iZoom + "&sMapMaker=" + sMapMaker;
                } else {
                    var sGet = "?cats=&nelng=" + ( bounds.getNorthEast().lng() ) + "&nelat=" + ( bounds.getNorthEast().lat() ) + "&swlng=" + ( bounds.getSouthWest().lng() ) + "&swlat=" + ( bounds.getSouthWest().lat() ) + "&iZoom=" + iZoom + "&sMapMaker=" + sMapMaker;
                }
                // Check if filled for session problems ( F5 reloads JS, but not PHP Session! )
                sGet += '&oMapObjects=' + this.filled();
                
               // Start the Asynchonous request
                GDownloadUrl( this._sDataUrl + sGet, GEvent.callback(this, this.updateObjects));
            } else {                                    // If an update is running
                if ( this._bQueueLastRequest ){         // Check if queuing enabled.
                    this._bUpdateWaiting = true;
                }
            }
        };
        
        
        /**
        *    Check if MapObjects contains any geometry
        **/
        this.filled = function(){
            var i = 0; 
            for ( var x in this.oPoints ) { i += x; break; }  
            if ( i ) {  return true; }
            else {      return false; }
        };
        
        /**
        *    Check for queued commands and execuste appropiate commands if needed
        *   @private
        **/
        this.checkQueue = function(){
            if ( !this.isBusy() ) {                          // If not busy
                if ( this._bMenuUpdateWaiting ) {                   // If MENU update is waiting
                    this._bMenuUpdateWaiting = false;         
                    this.syncCategories();                   // Re-Synchronize category visiblity
                                                                    // Fix for: Click hide category when
                                                                    // updateing. Only the markers who
                                                                    // appear after the click are properly 
                                                                    // Hidden
                    oMenu.countOffItems('GeoCounter_visible'); // Recalculate the total visible markers.
                }
                                                                    // If viewport update is waiting
                if ( this._bQueueLastRequest && this._bUpdateWaiting ) {
                    this._bUpdateWaiting = false;                
                    this.loadObjects();                      // Re-load objects based on current viewport
                }
                
                
                // Handle queues events like clicks ( currrently only used for clicks (4-7-2007) )
                if ( oGeoStart._oQueuedCommand !== null && typeof(oGeoStart._oQueuedCommand) == 'object' ){
                    oGeoStart.trigger(this._oQueuedCommand['iId'], oGeoStart._oQueuedCommand['sEvent']);
                    oGeoStart._oQueuedCommand = null;
                // Queued function
                } else if ( oGeoStart._oQueuedCommand !== null && typeof(oGeoStart._oQueuedCommand) == 'function' ){
                    oGeoStart._oQueuedCommand();
                    oGeoStart._oQueuedCommand = null;
                }
            }
        };
        
        /**
        *    Check if currently busy updating
        **/
        this.isBusy = function(){
            if ( this.bRemoving || this.bAdding ) { return true;    } 
            else                                  { return false;   }
        };
                
        
        /**
        *   Update map objects. Parse data and send 
        *   requests to update functions for objects
        *   and the oMenu.
        *   @private
        *   @param json Json string with data from getData.php
        *   @private
        **/
        this.updateObjects = function (json){
                var oData = eval('(' + json + ')');

            //** Update menu data. **/
                this._oMenu.update(oData.oMenu);
            
            
            /** Category state **/
                this.aCategorystate = this._oMenu.getCatStates();
            
            /** Added Geometry data **/
                this.aNewGeometry     = oData.aNewGeometry;
            /** Removed Geometry data **/
                this.aRemoved         = oData.aRemovedGeometry;
                
            /** Organisatie data **/
                this.aOrganisatieInfo = oData.organisatie_info;
                            
    
            /** Load preloader **/
                var iOperations = oData.aOverview.iRemoved + oData.aOverview.iNew; // Count of actions, (add+remove)
                
                if ( this._bPreloaderEnabled ) {                // Check if preloader should be used.
                    this.oPreloader._iOperations = iOperations; // Initialize max counter
                }
            
            /** Start removal loader **/
                this.iRemovedCounter = 0;                       
                this.iRemoved       = oData.aOverview.iRemoved;
                
                // Start the interval to remove per batch.
                this.oDelInterval = setInterval(function() { oGeoStart.removeBatch(); }, this._iLoadInterval/10);    
            
            /** Start preloader and add loader. **/
                this.iNewCounter = 0;
                this.iNewGeometry = oData.aOverview.iNew;
                
                // Start the interval to add per batch
                this.oAddInterval = setInterval(function() { oGeoStart.displayBatch(); }, this._iLoadInterval);                
            
        };
    
        
        /**
        *   Check visibility of object and hide if category isn't visible or filtered.
        *   @param oRef MapObject to check (marker/polygon/polyline)
        **/
        this.checkVisibility = function(oRef) {
            if ( oRef._GeoInfo['id'].indexOf("route") == -1 ) {
                // Nieuwe Regel: Bij beide zichtbaar dan laten zien
                if ( !this.checkVisibilityCategory(oRef) && !this.checkVisibilityFilter(oRef) ) {
                    if ( oRef.isHidden() ) {
                        oRef.show(); 
                    }                
                } else {
                    oRef.hide();                
                }            
            }
        };
        
        
        /**
        *   Check category visibility for referenced object.
        *   @private
        *   @param oRef MapObject to check (marker/polygon/polyline)
        **/
        this.checkVisibilityCategory = function(oRef) {
            /** Categgory states for menu **/            
            if ( this.aCategorystate ) {
                /** Check if point is in hidden category **/
                var i = this.aCategorystate.length;
                var iHiddenCount = 0;
                while ( i-- ) {
                    var j = oMenu.oCatOf[oRef._GeoInfo['id']].length;
                    while ( j-- ) {   
                        if ( parseInt(oMenu.oCatOf[oRef._GeoInfo['id']][j], 10) == parseInt(this.aCategorystate[i], 10) ) {
                            iHiddenCount++;
                        }
                        if ( iHiddenCount >= oMenu.oCatOf[oRef._GeoInfo['id']].length ) {
                            return true;
                        }
                    }
                }
                return false;                
            } else {
                return false;
            }
        };
            
            
        /**
        *   Check filter for referenced item
        *   @private
        *   @param oRef MapObject to check (marker/polygon/polyline)
        **/
        this.checkVisibilityFilter = function(oRef){
            if ( !this._aGeoFilterKeys ) {
                this._aGeoFilterKeys = [];
            }
            /** Check special filters **/           
            var j = this._aGeoFilterKeys.length;          // Initialize loop through filters
            
            while ( j-- ) { 
                // If filter contains 
                if ( this._aGeoFilterState[this._aGeoFilterKeys[j]] && this._aGeoFilterState[this._aGeoFilterKeys[j]].length > 0 ) { // Check if the filter has been filled
                    var k = this._aGeoFilterState[this._aGeoFilterKeys[j]].length;
                    while ( k-- ) { // Loop throught the filter states
                        if ( oRef._GeoInfo[this._aGeoFilterKeys[j]].indexOf(this._aGeoFilterState[this._aGeoFilterKeys[j]][k]) != -1 ) {
                            return true;
                        }
                    }                    
                }
            }
            return false;
        };
        
        /** 
        *   Add command to command queue. 
        *   @param sCommand String of the event to be triggered
        *   @param iSubject Id of the object on who the command should be triggered
        **/        
        this.queueCommand = function(sCommand, iSubject){
            this._oQueuedCommand            = {};
            this._oQueuedCommand['sEvent']  = sCommand;
            this._oQueuedCommand['iId']     = iSubject;
        };
        
        
    /************************************************
    *                                               *
    *    Filter functions                           *
    *                                               *
    ************************************************/
        /**
        *   Create filter for FIELD - Currently only suppport values to filter on, no ranges.
        *   @param sKey Fieldname for filter, field should be in oPoints[]._GeoInfo
        **/
        this.createFilter = function(sKey) {
            this._aGeoFilterKeys.push(sKey);
            this._aGeoFilterState[sKey] = [];
        };
        
        /**
        *   Remove filter for FIELD
        *   @param sKey Fieldname for filter
        **/
        this.removeFilter = function(sKey) {
            if ( this._aGeoFilterKeys ) {
                var i = this._aGeoFilterKeys.length;
                while( i-- ) {
                    if ( this._aGeoFilterKeys[i] == sKey ) {
                        delete(this._aGeoFilterKeys[i]);
                        break;
                    }
                }                
                if ( this._aGeoFilterState[sKey] ) {
                    delete(this._aGeoFilterState[sKey]);
                }
            }
        };
        
        /**
        *   Add value to filter 
        *   @param sKey Keyname of the filter/_GeoInfo field.
        *   @param sValue Value that should be shows on the map
        **/
        this.addFilterItem = function(sKey, sValue) {
            if ( this._aGeoFilterState[sKey] ) {
                this._aGeoFilterState[sKey].push(sValue);                
            }
        };
        
        /**
        *   Remove value from filter
        *   @param sKey Keyname of the filter/_GeoInfo field.
        *   @param sValue Value that should be shows on the map
        **/
        this.removeFilterItem = function(sKey, sValue) {
            if ( this._aGeoFilterState[sKey] ) {
                var i = this._aGeoFilterState[sKey].length;
                while ( i-- ) {
                    if ( this._aGeoFilterState[sKey][i] == sValue ) {
                        delete(this._aGeoFilterState[sKey][i]);
                        break;
                    }
                }
            }
        };
    


    /************************************************
    *                                               *
    *    MapObject functions. Front for all objects *
    *                                               *
    ************************************************/
        /**
        *   Trigger event on object.id. Contains logic for hover etc. Might need to move the logic to the listeners?
        *   @param iId Id of map object
        *   @param sEvent Event to be triggered on mapobject
        **/
        this.trigger = function(iId, sEvent){
            switch(sEvent){
                case 'mouseout':
                    if ( this._bEnableHover && !this.isBusy() ) {
                        GEvent.trigger(this.oPoints[iId], sEvent);                        
                    }
                    break;
                case 'mouseover':
                    if ( this._bEnableHover && !this.isBusy()) {
                        GEvent.trigger(this.oPoints[iId], sEvent);                        
                    }
                    break;
                case 'click':
                    if ( this._bEnableBalloon && !this.isBusy()) {
                        GEvent.trigger(this.oPoints[iId], sEvent);                        
                    }
                    break;
                case 'deleteObject':
                    if ( this.oPoints[iId] && ( this.oPoints[iId]._GeoInfo['g_type'] == 'POLYGON' || this.oPoints[iId]._GeoInfo['g_type'] == 'LINESTRING' ) ) {
                        delete(this.aPolyBounds[iId]);
                    }
                    this.oMap.removeOverlay(this.oPoints[iId]);   // Remove object from the map.
                    delete(this.oPoints[iId]);                    // Remove object from map objects
                    break;
                default:
                    if ( !this.isBusy() ) {
                        GEvent.trigger(this.oPoints[iId], sEvent);
                    }
                    break;
            }
        };
        
        
        /**
        *   Open a hidden object. Uses json string with object data as argument.
        *   @param json Hidden marker data.
        **/
        this.gotoHidden = function(json){
            var aInfo =  eval ( '(' + json + ')');            

            // Check current zoom level
            
            if ( this.oMap.getZoom() < aInfo.zoom ) {
                if ( aInfo.iZoom < this.iPrefferedZoom ) {
                    var iZoom = this.iPrefferedZoom;
                } else {
                    var iZoom = aInfo.zoom;
                }                
                this.oMap.setCenter(new GLatLng(parseFloat(aInfo.lat), parseFloat(aInfo.lng)), parseInt(iZoom, 10));
            }
            
            this.aCategorystate = this._oMenu.getCatStates();
            this.createPoint(aInfo);
            this.oPoints[aInfo['id']].show();
                 
            swap('tab', false);
                       
            GEvent.trigger(this.oPoints[aInfo.id], 'click');
        };
        
        /**
        *   Open a hidden object, new style uses ajax request to get data 
        *   @param iId MapObject id
        **/
        this.gotoHiddenId = function(iId){
            if ( !this.isBusy() ) {      // Check if an map update is running
                if ( !oGeoStart.oMap.getInfoWindow().isHidden() ) { // Close opened info window
                    oGeoStart.oMap.closeInfoWindow();
                }
                GDownloadUrl( sBaseUrl + 'GeoStart/ajax/getItemById.php?id='+iId, GEvent.callback( this, this.gotoHidden ) );
            } else {
                setTimeout('oGeoStart.gotoHiddenId('+iId+')', 100);
            }
        };

        
        
        /**
        *   Check zoom level and goto minimum zoom level. Returns true if no change.
        *   @private
        *   @return {boolean} Changed zoom level to preffere 
        **/
        this.checkZoom = function(){
            if ( this.oMap.getZoom() < this._iPreferredZoom ) {
                this.oMap.setZoom(this._iPreferredZoom);
                return false;
            } else {
                return true;
            }
        };
        
        
        /**
        *   Hide object.id
        *   @param iId object Id
        **/
        this.hide = function(iId){
            this.oPoints[iId].hide();
        };
        
        /**
        *   Show object.id
        *   @param iId object Id
        **/
        this.show = function(iId){
            this.oPoints[iId].show();
        };
        
        
        /**
        *   Hide category.id
        *   Uses this._sCategoryKey to identify category in oPoints[id].dbInfo
        *   @param int iId Id reference to MapObjects
        **/
        this.hideCategory = function(iId){
            // If busy remember to update categories after load.
            if ( this.isBusy() ) { this._bMenuUpdateWaiting = true; }

            for ( k in this.oPoints ) {
                if ( this.oPoints[k]._GeoInfo[this._sCategoryKey] == iId ) {
                    this.hide(k);
                }
            }            
        };
        
        /**
        *   Show category.id
        *   Uses this._sCategoryKey to identify category in oPoints[id].dbInfo
        *   @param int iId id of geomtry
        **/
        this.showCategory = function(iId){
            // If busy remember to update categories after load.
            if ( this.isBusy() ) { this._bMenuUpdateWaiting = true; }

            for ( var k in this.oPoints ) {
                if ( this.oPoints[k]._GeoInfo[this._sCategoryKey] == iId ) {
                    this.show(k);
                }
            }            
        };
        
        /**
        *   Show category.id by array 
        *   Uses this._sCategoryKey to identify category in oPoints[id].dbInfo
        *   @param array aInfo Array (NON ASSOCIATIVE) with the categories to be shown.
        **/
        this.showCategoryGroup = function(aInfo){
            // If busy remember to update categories after load.
            if ( this.isBusy() ) { this._bMenuUpdateWaiting = true; }
            
            var i = aInfo.length;
            for ( var k in this.oPoints ) {
                var j = i;
                while ( j-- ) {
                    if ( this.oPoints[k]._GeoInfo[this._sCategoryKey] == aInfo[j] ) {
                        this.show(k);
                    }
                }
            }            
        };

        /**
        *   Hide category.id by array 
        *   Uses this._sCategoryKey to identify category in oPoints[id].dbInfo
        *   @param array aInfo Array (NON ASSOCIATIVE) with the categories to be shown.
        **/
        this.hideCategoryGroup = function(aInfo){
            // If busy remember to update categories after load.
            if ( this.isBusy() ) { this._bMenuUpdateWaiting = true; }

            var i = aInfo.length;
            for ( var k in this.oPoints ) {
                var j = i;
                while ( j-- ) {
                    if ( this.oPoints[k]._GeoInfo[this._sCategoryKey] == aInfo[j] ) {
                        this.hide(k);
                    }
                }
            }            
        };
        
        /**
        *    Sync categorie and points
        *    Used for updateing map if categories got selected while updateing.
        *   @private
        **/
        this.syncCategories = function(){
            this.aCategorystate = this._oMenu.getCatStates();        // Get current state from Menu object
            var i = this.aCategorystate.length;
            
            for ( var k in this.oPoints ) {
                this.checkVisibility(this.oPoints[k]);                
            }       
        };
        
        
        /**
        *   Show or hide ALL markers.
        *   @param {boolean} bVisibility
        **/
        this.setAll = function( bVisiblity ){
            // If busy remember to update categories after load.
            if ( this.isBusy() ) { this._bMenuUpdateWaiting = true; }
            
            if ( !bVisiblity ) { this.oMap.closeInfoWindow(); }
            
            for ( var k in this.oPoints ) {                
                if ( bVisiblity ) {                
                    if ( this.oPoints[k].isHidden() ) {
                        this.show(k);
                    }
                } else {
                    if ( !this.oPoints[k].isHidden() ) {
                        this.hide(k);
                    } 
                }
            }        
        };
        
        /**
        *   Generate counters for visible / invisible items.
        **/      
        this.getVisiblityCounters = function(){
            var iVisible = 0;
            var iTotal = 0;
            for ( k in this.oPoints ) {
                iTotal++;
                if ( !this.oPoints[k].isHidden() ) {
                    iVisible++;
                }
            }
            
            return  {
                        'iTotal':iTotal,
                        'iVisible':iVisible,
                        'iHidden':iTotal - iVisible
                    };
                                    
        };
}/** 
* HTML namespace in cGeoStart 
* @extends cGeoStart  
* @namespace
**/
cGeoStart.prototype.html = function(){};       

    /************************************************
    *                                               *
    *    HTML generation functions.                 *
    *                                               *
    ************************************************/
        
        /**
        *   Make request for "Meer informatie"
        *   @param int Marker ID
        **/
        cGeoStart.prototype.html.htmlMeerInfoRequest = function(iMarkerId){
            // De inhoud van de informatie DIV alleen bijwerken als er een iMarkerID is opgegeven
            if(iMarkerId){
                GDownloadUrl(sBaseUrl  + 'GeoStart/ajax/getMeerinfoHtml.php?id=' + iMarkerId, oGeoStart.html.htmlMeerInfoLoad);
            }
        };
    
    
        /**
        *   @desc Handle the "Meerinfo" request and load the data into the proper div.
        *   @param sJson Single location data based on ajax call
        *   @private
        **/
        cGeoStart.prototype.html.htmlMeerInfoLoad = function(sJson){
            aJson = eval('(' + sJson + ')');

            /** Activate tabtitle, show tab and set right content block **/
            swap('tab', true);

            activate('tabTitle');
            setTabContent('info');

            // De naam van het informatie tabje veranderen
            document.getElementById('tabTitleText').innerHTML = aJson.sTitel.substring(0,43); // de titel moet niet langer zijn als 43 tekens anders loopt ie het tabje uit

            // De informatie in de informatie div zetten
            document.getElementById('tab_contents_info').innerHTML = aJson.html;

            // In het hidden field het markers id zetten
            document.getElementById('iMarkerId').value = aJson.iId;

            // Statistieken bijhouden
            pageHit(aJson.permlink + '/meer_informatie');
            
            swap('tab', true);
        };
        
        
        
        
        
        /**
        *   Make request for search in geostart
        *   @param sKeyword Search for this word
        *   @param iPage page of search results
        **/
        cGeoStart.prototype.html.showSearch = function(sKeyword, iPage){    
            if ( !iPage ) { 
                /** 
                *   @default 1 
                **/
                var iPage = 1;
            }
            
            setTabContent('search');
            
            if ( sKeyword ) { 
            
                oGeoStart.html.sKeyword= sKeyword;
                $('keyword').value = sKeyword;
                $('keyword_menu').value = sKeyword;
                
                GDownloadUrl(sBaseUrl + 'GeoStart/ajax/getSearchResults.php?keyword='+sKeyword+'&iPage='+iPage+ '&sMapMaker=' + sMapMaker, oGeoStart.html.loadSearch);
            } else {
                swap('tab', true);
                
            }        
        };
        

        /**
        *   Display search result HTML into proper div.
        *   @param html Generated HTML
        *   @private
        **/
        cGeoStart.prototype.html.loadSearch = function(html){
            
            activate('tabSearch');
            swap('tab', true);

            setTabContent('search');
            
            $('searchResultWrap').style.display = "block";
            
            if(oGeoStart.html.sKeyword){        
                
                oGeoStart.oSearch.getSearch(oGeoStart.html.sKeyword);
                        
                document.getElementById('searchResultWrap').innerHTML = html;
                
            } else {
                swap('tab', true);
            }
        };
        
        
        /**
        *   @desc Single search result
        *   @param iId Id of the marker
        *   @param aInfo Array with information
        *   @private
        **/
        cGeoStart.prototype.html.htmlSingleSearchResult = function(iId, aInfo){
                if ( !oGeoStart.oTemplate ) {
                    oGeoStart.oTemplate = new cTemplate();
                    oGeoStart.oTemplate.sTemplateDir = sBaseUrl + 'GeoStart/templates/';
                }                
                
                oGeoStart.oTemplate.loadTemplate('enkel_zoek_resultaat.js.tpl');
                
                oGeoStart.oTemplate.assign('sTitel', aInfo[0]);
                oGeoStart.oTemplate.assign('sStraat', aInfo[0]);
                oGeoStart.oTemplate.assign('sPlaats', aInfo[1]);
                oGeoStart.oTemplate.assign('iId', iId);
                return oGeoStart.oTemplate.fetch();
        };
        
        
        /**
        *   @desc show sport organisatie informatie
        *   @param iId Id of organisatie
        *   @param sTitel Titel of the organisatie.
        **/
        cGeoStart.prototype.html.showOrganisatieInfo = function(iId, sTitel){
            oGeoStart.html.sOrganisatieTitel = sTitel;
            GDownloadUrl(sBaseUrl + 'GeoStart/ajax/getOrganisatieHtml.php?id='+iId, oGeoStart.html.loadOrganisatieInfo);
        };
        
        /**
        *   @desc Load html into tab.
        *   @param sHtml Html to load into info tab
        *   @private
        **/
        cGeoStart.prototype.html.loadOrganisatieInfo = function(sHtml){
            swap('tab', true);
            activate('tabTitle');
            setTabContent('info');
            
            // De naam van het informatie tabje veranderen
            // de titel moet niet langer zijn als 43 tekens anders loopt ie het tabje uit
            document.getElementById('tabTitleText').innerHTML = oGeoStart.html.sOrganisatieTitel.substring(0,43); 
            
            // De informatie in de informatie div zetten
            document.getElementById('tab_contents_info').innerHTML = sHtml;
            
        };
        
        
        
        /**
        *   Zoom in ballon als je te ver uitgezoomed bent.
        *   @param iId Id van marker
        *   @return string Html van ballon
        **/
        cGeoStart.prototype.html.htmlInfowindowZoomuit = function(iId){
            if ( !oGeoStart.oTemplate ) {
                oGeoStart.oTemplate = new cTemplate();
                oGeoStart.oTemplate.sTemplateDir = sBaseUrl + 'GeoStart/templates/';
            }
            oGeoStart.oTemplate.loadTemplate('ballon_zoomin.js.tpl');
            oGeoStart.oTemplate.assign('iId', iId);
            return oGeoStart.oTemplate.fetch();
                        
        };

       /**
       *    generate InfoWindow with embed/link information for object
       *    @param sKey key ( keyfield type ) for marker.
       *    @param iId Marker object id
       *    @return sHtml Window containing link and embed information
       **/
       cGeoStart.prototype.html.htmlLinkEmbedWindow = function( sKey, iId ) {
            if ( !oGeoStart.oTemplate ) {
                oGeoStart.oTemplate = new cTemplate();
                oGeoStart.oTemplate.sTemplateDir = sBaseUrl + 'GeoStart/templates/';
            }
            
            oGeoStart.oTemplate.loadTemplate('ballon_link_embed.js.tpl');
           
            oGeoStart.oTemplate.assign('sTitelKey', oGeoStart.oPoints[iId]._GeoInfo['titel_key']);
            oGeoStart.oTemplate.assign('iId', iId );
            oGeoStart.oTemplate.assign('sKey', sKey );
            oGeoStart.oTemplate.assign('sIframeCode', oGeoStart.getMiniMapCode(sKey, 310, 257));
            
            return oGeoStart.oTemplate.fetch();          
       };
       
       
       /**
       *    Generate info window based on Array of information gotten from AJAX request
       *    @param array aInfo Information about the point
       *    @return string content String with info window html for marker
       **/
       cGeoStart.prototype.htmlInfoWindow = function(aInfo) {
                if ( !oGeoStart.oTemplate ) {
                    oGeoStart.oTemplate = new cTemplate();
                    oGeoStart.oTemplate.sTemplateDir = sBaseUrl + 'GeoStart/templates/';
                }
                
                if ( oSettings._bMenu !== false ) {
                    oGeoStart.oTemplate.loadTemplate('ballon.js.tpl');
                } else {
                    oGeoStart.oTemplate.loadTemplate('ballon_mapmaker.js.tpl');
                }
                
                if(aInfo.organisaties){
                    var aOrganisaties = aInfo.organisaties[aInfo.id];
                } else if(oGeoStart.aOrganisatieInfo[aInfo.id]){
                    var aOrganisaties = oGeoStart.aOrganisatieInfo[aInfo.id];
                } else {
                    var aOrganisaties = false;
                }
                
                if ( aOrganisaties !== false && typeof(aOrganisaties) != 'undefined' ) {                
                    var bOrganisaties = 'true';
                    oGeoStart.oTemplate.assign('iOrganisaties', aOrganisaties.length);
                    oGeoStart.oTemplate.assign('aOrganisaties', aOrganisaties);
                }
                
                
                if ( aInfo.omschrijving  != '' || aOrganisaties !== false  ) {
                    var bOmschrijvingEnOrganisaties = true;
                } 
                
                var aSubgroepen = Array();
                var aSg = oMenu.oCatOf[aInfo.id] || [];
                var i = aSg.length || 0;
                
                while ( i-- ) {       
                    aSubgroepen[i] = Object();
                    aSubgroepen[i].image = oIconmanager.get(aSg[i]).image;
                    aSubgroepen[i].sg_titel = oIconmanager.get(aSg[i]).sg_titel;
                    aSubgroepen[i].sg_id = aSg[i];
                    aSubgroepen[i].counter = oMenu.oCounter[aSg[i]].counter;
                }                
                
                oGeoStart.oTemplate.assign('aSubgroepen', aSubgroepen);
                
                
                if ( bOmschrijvingEnOrganisaties === false && aInfo.website ) {
                    var bWebsite = true;
                    if ( aInfo.website.substring(0,7) != 'http://') {
                        aInfo.website = 'http://' + aInfo.website;
                    }
                    if ( aInfo.website.length > 30 ) {
                        var sWebby = aInfo.website.substring(7, 28)+'...';
                    } else {
                        var sWebby = aInfo.website + '...';
                    }
                    oGeoStart.oTemplate.assign('sWebsite', aInfo.website);
                }

                
                oGeoStart.oTemplate.assign('id', aInfo.id);
                
                oGeoStart.oTemplate.assign('titel', aInfo.titel);
                oGeoStart.oTemplate.assign('adres', aInfo.adres);
                oGeoStart.oTemplate.assign('postcode', aInfo.postcode);
                
                oGeoStart.oTemplate.assign('link', aInfo.link);
                oGeoStart.oTemplate.assign('zorgaanbieder_naam', aInfo.zorgaanbieder_naam);
                
                oGeoStart.oTemplate.assign('zorgaanbieder_website', aInfo.zorgaanbieder_website);
                oGeoStart.oTemplate.assign('aantal_groepswoningen', aInfo.aantal_groepswoningen);
                oGeoStart.oTemplate.assign('aantal_bewoners_per_woning', aInfo.aantal_bewoners_per_woning);
                oGeoStart.oTemplate.assign('aantal_bewoners_project', aInfo.aantal_bewoners_project);
                oGeoStart.oTemplate.assign('plaats', aInfo.plaats);
                
                oGeoStart.oTemplate.assign('sMeerInfo', aInfo.id);
                
                oGeoStart.oTemplate.assign('titel_key', aInfo.titel_key);
                
                
                if ( bOmschrijvingEnOrganisaties ) {
                    oGeoStart.oTemplate.assign('bOmschrijvingEnOrganisaties', 'true');            
                }        

                if ( bOrganisaties ) {
                    oGeoStart.oTemplate.assign('bOrganisaties', 'true');
                }
                
                if ( bWebsite ) {
                    oGeoStart.oTemplate.assign('bWebsite', 'true');                    
                }
                
                oGeoStart.oTemplate.assign('sTitelSafe', aInfo.titel.replace("'", '&quot;').replace('"', ''));
                
                return oGeoStart.oTemplate.fetch();
       };
       
  
       /**
       *    Generate info window for minimap based on Array of information gotten from AJAX request
       *    @param array aInfo Information about the point
       *    @return string content String with info window html for marker
       **/
       cGeoStart.prototype.htmlMiniInfoWindow = function(aInfo) {
            if ( !oGeoStart.oTemplate ) {
                oGeoStart.oTemplate = new cTemplate();
                oGeoStart.oTemplate.sTemplateDir = sBaseUrl + 'GeoStart/templates/';
            }
            
            oGeoStart.loadTemplate('ballon_minimapinfo.js.tpl');
            
            
            oGeoStart.oTemplate.assign('id', aInfo.id);
            oGeoStart.oTemplate.assign('titel', aInfo.titel);
            
            oGeoStart.oTemplate.assign('titel_key', aInfo.titel_key);


            if ( aInfo.omschrijving == '' && aInfo.website ) {
                var bWebsite = true;
                if ( aInfo.website.substring(0,7) != 'http://') {
                    aInfo.website = 'http://' + aInfo.website;
                }
                if ( aInfo.website.length > 30 ) {
                    var sWebby = aInfo.website.substring(7, 28)+'...';
                } else {
                    var sWebby = aInfo.website + '...';
                }
                oGeoStart.oTemplate.assign('sWebsite', aInfo.website);
            } else {
                oGeoStart.oTemplate.assign('bOmschrijving', 'true');
            }
                
            return oGeoStart.oTemplate.fetch();
       };/**
*   Prototype for GeoStart listener.
*      
*   Maplistener and GeoMetry listeners
*
*   @extends cGeoStart
**/

        /**
        *    Load listeners needed on the oMap
        *   @private
        **/
        cGeoStart.prototype.loadListeners = function(){
            
            /** Update map objects on moveend ( also triggers on zooms ) **/
            GEvent.addListener(oGeoStart.oMap, 'moveend', function() { oGeoStart.loadObjects();} );
            
            /** Remove the tooltip when movement starts **/
            GEvent.addDomListener(oGeoStart.oMap.getContainer(), 'mouseout', function() { 
                oGeoStart._oTooltip.hide(); 
            });
            GEvent.addListener(oGeoStart.oMap, 'movestart', function() { oGeoStart._oTooltip.hide(); } );
            GEvent.addListener(oGeoStart.oMap, 'zoomend', function() { oGeoStart._oTooltip.hide(); oGeoStart.oMap.closeExtInfoWindow() } );
            
            /** Polygone check map listener thingie **/
            GEvent.addListener(oGeoStart.oMap, 'click', function(overlay, point) { 
                if ( point ) {
                    var result = oGeoStart.checkClickedPoly(point);
                    if ( result ) {
                        oGeoStart.trigger(result, 'click');
                    }
                }
            });
            oGeoStart._hoverListener = GEvent.addListener(oGeoStart.oMap, 'mousemove', oGeoStart.handleMouseMove);
            
        };
        
        /**
        *   Check on mousemove if hovering a polygon.
        *   @param GPoint <a target="_blank" href="http://code.google.com/intl/nl/apis/maps/documentation/reference.html#GPoint">Google GPoint</a>
        *   @private
        **/
        cGeoStart.prototype.handleMouseMove = function(point){
            // Check if not hovering marker, fixes bug that marker hover does not stick when marker on polygon
            if ( oGeoStart._hoveringMarker !== true ) {
                // Result is the id of the poly.
                var result = oGeoStart.checkClickedPoly(point);
                if ( result ) {
                    // Not hidden?
                    if ( !oGeoStart.oPoints[result].isHidden() ) {
                        oGeoStart.trigger(result, 'mouseover');
                        oGeoStart.oMap.getDragObject().setDraggableCursor("pointer");
                        if ( oGeoStart._bEnableHover ) {
                            oGeoStart._oTooltip.setText(oGeoStart.oPoints[result].titel);
                            if ( oMenu.oCatOf[result] )  {
                                oGeoStart._oTooltip.addCat( oMenu.oCatOf[result] );
                            } else {
                                oGeoStart._oTooltip.addCat(parseInt(oGeoStart.oPoints[result]._GeoInfo['sg_id']));
                            }
                            oGeoStart._oTooltip.show(point);
                        }
                    }
                } else {
                    oGeoStart.oMap.getDragObject().setDraggableCursor(GDraggableObject.getDraggableCursor());
                }
            }
        };
        
        /**
        *   Load listeners for geometry. Currently supports only markers.
        *   @param object oRef Reference object to apply listeners to
        *   @private
        **/
        cGeoStart.prototype.loadGeometryListeners = function(oRef){
            GEvent.addListener(oRef, 'infowindowclose', function(){ 
                oGeoStart.checkVisibility(oRef); 
            });
            
            
            /** Open info window on marker **/
            GEvent.addListener(oRef, 'infowindowopen', function() {
                pageHit( sBaseUrl + 'locatie/' + oRef._GeoInfo['titel_key'] );

                /** Add listener, if removed open special window to be able to zoom back to the marker. **/          
                GEvent.addListener(oRef, 'remove', function() {
                        oGeoStart.oMap.closeInfoWindow();                                            
                        var iZoom   = oRef._GeoInfo['zoom'];
                        if ( iZoom > oGeoStart.oMap.getZoom() ){
                            var iId = oRef._GeoInfo['id'];
                            var fLat    = oRef.getPoint().lat();
                            var fLng    = oRef.getPoint().lng();
                            oGeoStart.oMap.openInfoWindowHtml(oRef.getPoint(), oGeoStart.html.htmlInfowindowZoomuit(iId));
                        }
                    });
            });
            
            /** Remove the 'remove' listener when infowindow is closed **/
            GEvent.addListener(oRef, 'infowindowclose', function(){
                GEvent.clearListeners(oRef, 'remove');
            });
            
            /** Onclick event. Hide tooltip ( looks bad on moving map ) and open info window **/
            GEvent.addListener(oRef, 'click', function(clickPoint) {
                    /** Ajust lat/lng on poly object to facilitate infowindow opened at clickpoint **/
                    if (    oRef._GeoInfo['g_type'] == 'POLYGON' ||
                            oRef._GeoInfo['g_type'] == 'MULTIPOLYGON' ||
                            oRef._GeoInfo['g_type'] == 'LINESTRING' ){
                        if ( clickPoint ) { 
                            oRef._GeoInfo['lat'] = clickPoint.lat();
                            oRef._GeoInfo['lng'] = clickPoint.lng();
                        }
                    }
            
            
                    if ( oGeoStart._bEnableHover ) {
                        oGeoStart._oTooltip.hide();                          // Onclick hide the tooltip
                    }
                    //oRef.openInfoWindowHtml(oRef.content);                  // Open the InfoWindow
                    oRef.openExtInfoWindow(
                        oGeoStart.oMap, 
                        "simple_example_window",
                        oRef.content,
                        {
                            beakOffset: -10,
                            paddingY: 40
                        }
                    );  
                    
                    //oGeoStart.oMap.panTo(oRef.getLatLng());
                       
                                    // Open the InfoWindow
                    
                    //swap('tab', false);                                     // Close the InfoTab

                    if ( oRef.bHoverShow ) {                                // Logic if tooltip is shown
                        oRef.tempMouseoutListener.remove();                     // Cancel listnerer that hides marker after mouseout
                        oRef.bForceShow = true;                                 // Tag the marker as forced to show
                        
                        // Remove the marker again when the infowindow is closed
                        /*
                        oRef.tempClickListener = GEvent.addListener(oRef, 'infowindowclose', function(){
                            // Reset the mouseout listener for a hidden marker
                            GEvent.addListener(oRef, 'mouseout', function(){ oRef.hide(); });
                        });*/
                        oRef.show();                                            // Show the marker
                    }
            });                            
            
            /** Mouseover event to facilitatie our tooltip **/
            GEvent.addListener(oRef, "mouseover", function() {
                if ( oRef.type == "point" ) {
                    if ( oGeoStart._bEnableHover ) {
                        oGeoStart._hoveringMarker = true;
                        oGeoStart._hoverListener.remove();
                    
                        if ( oGeoStart._oTooltip.markerOnScreen(oRef.getPoint()) ) {                // Check if marker is onscreen
                            oGeoStart._oTooltip.checkAlign(oRef._GeoInfo['g_type']);
                            oGeoStart._oTooltip.setText(oRef.tooltip);
                            
                            oGeoStart._oTooltip.addCat(oMenu.oCatOf[oRef._GeoInfo['id']]);                            
                            oGeoStart._oTooltip.show(oRef.getPoint());
                            // Add a listener to hide it again on mouseout
                            if ( oRef.isHidden() ) {                            // If marker is hidden show it
                                oRef.bHoverShow = true;                             // Mark the marker as "shown by hover"
                                oRef.show();                                        // Show the marker
                                
                                // Add a listener to hide it again on mouseout
                                oRef.tempMouseoutListener = GEvent.addListener(oRef, 'mouseout', function(){
                                    oRef.hide();                                    // Hide the marker
                                    oRef.tempMouseoutListener.remove();             // Remove self (listener)
                                });
                            }
                        }
                    }
                }
            });
            
            /** Mouseout event for tooltip **/                
            GEvent.addListener(oRef, "mouseout", function() {
                if ( oGeoStart._bEnableHover ) {
                    if ( oRef.type == 'point' ) {
                        oGeoStart._hoveringMarker = false;                        
                    }
                    oGeoStart._oTooltip.hide();
                    oRef.bHoverShow = false;
                    oGeoStart._hoverListener = GEvent.addListener(oGeoStart.oMap, 'mousemove', oGeoStart.handleMouseMove);
                }
            });
        };
        /**
*   Marker cache extentie. 
*   
*   Vervangt de oude remove/add/createPoint voor nieuwe(betere). In 
*   plaats van altijd een nieuwe marker maken slaat hij de markers op en verbergd hij ze
*
*   @extends cGeoStart  
**/

        /**
        *   Remove a batch of markers
        *   @private
        **/
        cGeoStart.prototype.removeBatch = function(){
            var i = 0;
            
            if ( typeof(this.oMarkerCache) != 'object' ) {
                this.oMarkerCache = [];
            }
            
            for ( var key in this.aRemoved ) {                            // Loop trough global map objects.
                if ( i < this._iLoadStep && this.iRemovedCounter <= this.iRemoved ) { // Loop until max per batch (_iLoadStep) 
                                                                                      // and check if all updates were done.
                    
                    if ( this.oPoints[key] && ( this.oPoints[key]._GeoInfo['g_type'] == 'POLYGON' || this.oPoints[key]._GeoInfo['g_type'] == 'LINESTRING' ) ) {
                        delete(this.aPolyBounds[key]);
                        this.trigger(key, 'deleteObject');
                    } else {
                        this.oMarkerCache.push(this.oPoints[key]);
                        this.oPoints[key].hide();
                        delete(this.oPoints[key]);
                    }                    
                    
                    delete(this.aRemoved[key]);                    // Remove object from remove data update array
                    this.iRemovedCounter++;                                // Global counter to check if remval is done.
                } else {
                    break;
                }
                i++;
            }
            if ( this._bPreloaderEnabled ) {                            // Only update preloader if enabled
                this.oPreloader.updateLoader( i );
            }


            // Little update check counter thingie...
            if ( oMenu ) 
                oMenu.countOffItems('GeoCounter_visible');
            
            // Cleanup functions if done.
            if ( this.iRemovedCounter >= this.iRemoved ) {
                clearInterval(this.oDelInterval);                 // Clear the loop.
                this.iRemovedCounter = 0;
                this.aRemoved = null;
                this.iRemoved = null;
                this.bRemoving = false;                            // Tell map objects hes done.
                
                this.checkQueue();                               /// Call checkqueue to handle queued requests
            }
            
            //$('keyword_menu').value = 'Er zijn ' + this.oMarkerCache.length + ' marker gecached.';
        };
    
    
        /**
        *    Batch display of data. Updates mapobjects internal arrays.
        *    Comments added to lines different from this.removeBatch
        *   @private
        **/
        cGeoStart.prototype.displayBatch = function(){
            var i = 0;
            for ( var key in this.aNewGeometry ) {
                if ( i < this._iLoadStep && this.iNewCounter <= this.iNewGeometry ) {
                    if( typeof(this.oPoints[key]) != 'object' )                    
                        this.createPoint(this.aNewGeometry[key]);
                    delete(this.aNewGeometry[key]);                        // Remove from 'todo' object.
                    this.iNewCounter++;
                } else { 
                    break; 
                }
                i++;
            }
            if ( this._bPreloaderEnabled ) {
                this.oPreloader.updateLoader( i );                // Update preloader if enabled
            }
            
            // Little update check counter thingie...
            if ( oMenu ) 
                oMenu.countOffItems('GeoCounter_visible');
            
            // Cleanup functions if done.
            if ( this.iNewCounter >= this.iNewGeometry ) {
                clearInterval(this.oAddInterval);
                this.aNewGeometry = null;
                this.iNewGeometry = null;
                this.iNewCounter = 0;
                this.bAdding = false;
                if ( this._bPreloaderEnabled ) {
                    this.oPreloader.remove();             // Hide preloader again.
                }
                this.checkQueue();                        // Call checkqueue to handle queued requests
            }
            //$('keyword_menu').value = 'Er zijn ' + this.oMarkerCache.length + ' marker gecached.';
        };

        /**
        *    Create point (marker) on map. 
        *    Uses information from cGeoData::aVisible, add any fields from there.
        *    @param aInfo Array with information
        **/
        cGeoStart.prototype.createPoint = function(aInfo){
            if( typeof(this.oPoints[aInfo['id']]) != 'object' ) {
                switch ( aInfo.g_type ) {
                    case "POLYGON":
                        var oPoly = this.createPolygon(aInfo); 
                        this.oMap.addOverlay(oPoly);                       
                        oPoly.titel = aInfo.titel;
                        oPoly.tooltip = aInfo[oSettings._sTooltipField];
                        oPoly.type = "polygon";
                        oPoly.content = this.htmlInfoWindow(aInfo);
                        oPoly._GeoInfo  = aInfo;                // All information given by cGeoData(PHP!)
                        this.loadGeometryListeners(oPoly);
                        var id = aInfo.id;
                        this.oPoints[id] = oPoly;               // Add object to factory
                        this.checkVisibility(oPoly);
                        break;
                        
                    case "LINESTRING":
                        var oPoly = this.createPolyline(aInfo);
                        this.oMap.addOverlay(oPoly);
                        oPoly.titel = aInfo.titel;
                        oPoly.tooltip = aInfo[oSettings._sTooltipField];                        
                        oPoly.type = "linestring";
                        oPoly.content = this.htmlInfoWindow(aInfo);
                        oPoly._GeoInfo  = aInfo;                // All information given by cGeoData(PHP!)
                        this.loadGeometryListeners(oPoly);
                        var id = aInfo.id;
                        this.oPoints[id] = oPoly;               // Add object to factory
                        this.checkVisibility(oPoly);
                        break;
                        
                    case "POINT":
                    
                        // marker cache
                        if ( this.oMarkerCache.length > 0 ) {
                            
                            var oMarker = this.oMarkerCache.pop();
                            oMarker.setPoint(new GLatLng( parseFloat(aInfo.lat), parseFloat(aInfo.lng) ), oIconmanager.get(aInfo.sg_id));
                            var id = aInfo.id;
                            oMarker.title     = aInfo.titel;          // Define title
                            oMarker.tooltip   = aInfo[oSettings._sTooltipField];
                            oMarker.type        = "point";            // Set geometry type. Not used yet in 1.0
                            oMarker._GeoInfo  = aInfo;                // All information given by cGeoData(PHP!)
                            oMarker.content = this.htmlInfoWindow(aInfo);
                            
                            oMarker.setImage(oIconmanager.get(oMarker._GeoInfo.sg_id).image);
                            
                            this.oPoints[id] = oMarker;
                            
                            this.checkVisibility(oMarker);                            
                        
                        } else {
                            var point = new GMarker( new GLatLng( parseFloat(aInfo.lat), parseFloat(aInfo.lng) ), oIconmanager.get(aInfo.sg_id));    // Create object
                            var id = aInfo.id;
                            this.oPoints[id] = point;               // Add object to factory
                            
                            point.title     = aInfo.titel;          // Define title
                            point.tooltip   = aInfo[oSettings._sTooltipField];
                            point.type        = "point";            // Set geometry type. Not used yet in 1.0
                            point._GeoInfo  = aInfo;                // All information given by cGeoData(PHP!)

                            point.content = this.htmlInfoWindow(aInfo);
                        
                            /** Default event listener for opening info window **/
                            this.loadGeometryListeners(point);
                            
                            /** Add the overlay to the map **/
                            this.oMap.addOverlay(this.oPoints[aInfo.id]);
                            
                            this.checkVisibility(point);
                        }
                        break;
                    case "MULTIPOLYGON":
                        var i = aInfo.aGeometry.length;
                        var aGeo = aInfo.aGeometry;
                        var aPolylines = [];
                        while ( i-- ) {
                               aPolylines.push(eval('({ color: "#'+sColor+'", weight: '+iPGWidth+', opacity: '+iPGOpacy+', points: "' + aGeo[i][0] + '",levels: "' + aGeo[i][1] + '", zoomFactor: 2, numLevels: 18 })'));
                        }
                        var oEncoded = { 
                            polylines: aPolylines,
                            fill: true,
                            color:'#' + oIconmanager.get(sg_id).bgColor,
                            opacity: iPGFillOpacy,
                            outline: true};
                            
                        var oPoly = new GPolygon.fromEncoded(oEncoded);
                        GMultiPolygon.apply(oPoly, []);                    
                        
                        oPoly._gInitMulti(oEncoded);                    
                        oPoly.titel = aInfo.titel;
                        oPoly.tooltip = aInfo[oSettings._sTooltipField];
                        oPoly.type = "MULTIPOLYGON";
                        oPoly.content = this.htmlInfoWindow(aInfo);
                        oPoly._GeoInfo  = aInfo;                // All information given by cGeoData(PHP!)
                        
                        this.oMap.addOverlay(oPoly);        
                        this.loadGeometryListeners(oPoly);
                        var id = aInfo.id;                    
                        this.aPolyBounds[id] = oPoly.getBounds();                    
                        this.oPoints[id] = oPoly;               // Add object to factory
                        this.checkVisibility(oPoly);
                        break;
                }
            }
            return this.oPoints[id];
        };/** 
* @extends cGeoStart  
**/

    /************************************************
    *                                               *
    *    Minimap functions. Generate minimap code,  *
    *    load / init minimap                        *
    *                                               *
    ************************************************/

        /**
        *   Init a mini map. Clean map with one marker.
        *   Will callback this.loadMiniMap to load JSON data of marker.
        *   @param sMapId Name of the map div
        *   @param iId Id of the marker shown in the minimap
        **/
        cGeoStart.prototype.initMinimap = function(sMapId, iId){
            this.oMap = new GMap2(document.getElementById(sMapId));
            
            this.oPoints = Object();
            cGeoStartPoly.apply(this, []); // Extend with poly objects
            
            GDownloadUrl( 'GeoStart/ajax/getItemById.php?id='+iId, GEvent.callback( this, this.loadMiniMap ) );
        };
        
        /**
        *   Callback function to load the minimap based on the init string.
        *   @param JSON string with single marker data array
        *   @note Highly customized function for use with minimap.tpl
        *   @private
        **/
        cGeoStart.prototype.loadMiniMap = function(JSON){
            aInfo = eval('(' + JSON + ')');
            
            this.oMap.setCenter(new GLatLng(aInfo.lat, aInfo.lng), aInfo.zoom);
            
            this.point = new GMarker( new GLatLng( parseFloat(aInfo.lat), parseFloat(aInfo.lng) ), oIconmanager.get(aInfo.sg_id));    // Create object
            this.point['_GeoInfo'] = aInfo;
            
            
            if ( aInfo.g_type == "point" ) {
                GEvent.addListener(this.point, 'click', function(){
                    oGeoStart.point.openInfoWindowHtml(oGeoStart.htmlMiniInfoWindow(oGeoStart.point._GeoInfo));
                });
            }
            
            this.oMap.addOverlay(this.point);
            
            document.getElementById('miniTitel').innerHTML = aInfo.titel;
            
            // Delay needed. oMap needs a little while... buggy API :/
            setTimeout('oGeoStart.oMap.setZoom('+aInfo.zoom+');', 100);
        };
        
        /**
        *   Generate minimap iFrame code for inclusion in antoher webpage. 
        *   @param iMarkerId 
        *   @param iH Height in pixels.
        *   @param iW Width in pixels.
        **/
        cGeoStart.prototype.getMiniMapCode = function(iMarkerId, iH, iW){
            var sCode = '<iframe style="float:none;margin:2px;" src="' + sBaseUrl + '?minimap=1&marker_key=__MARKERID__&w=__WIDTH__&h=__HEIGHT__" width="__WIDTH2__" height="__HEIGHT__"></iframe>';
            
            /** Dynamicly replace variables. More of a proof of concept. Tho is makes changing a lot easier **/
            sCode = sCode.replace(/__HEIGHT__/g, iH);
            sCode = sCode.replace(/__WIDTH__/g, iW);
            sCode = sCode.replace(/__WIDTH2__/g, iW - 2);
            sCode = sCode.replace(/__MARKERID__/g, iMarkerId);
            
            return sCode;                        
        };
        
        
        /**
        *   Open embed InfoWindowHtml at place of current InfoWindow
        *   @param sKey Key of geometry/marker
        *   @param iId Id of the geometry/marker in the database
        *   @private
        **/
        cGeoStart.prototype.openEmbed = function(sKey, iId){
            var point = oGeoStart.oMap.getInfoWindow().getPoint();
            oGeoStart.oMap.closeInfoWindow();
            
            oGeoStart.oMap.openInfoWindowHtml(point, oGeoStart.html.htmlLinkEmbedWindow(sKey, iId));
        };
        
        /**
        *   Update the iFrame code based on inputs in cMapObjects::openEmbed
        *   @private
        **/
        cGeoStart.prototype.updateIframecode = function(){
            $('iframecode').value = this.getMiniMapCode( $('ifid').value, $('ifl').value, $('ifb').value );
        };

/**
*   Extend on cGeoStart
*   Adds poly functinality
*   @extends cGeoStart  
*   @namespace cGeoStartPoly
*   @class
**/
function cGeoStartPoly(){
    this.bPolyLoaded = true;
    this.aPolyBounds = [];

    /**
    *   Create a polyline
    **/   
    this.createPolyline = function(aInfo){
        var aPoints = this.createPoints(aInfo);
        
        if ( aInfo.polykleur.length > 0 ){
            var oPoly = new GPolyline(aPoints, "#" + aInfo.polykleur, 4, 0.5);
        } else {
            var oPoly = new GPolyline(aPoints, "#" + oIconmanager.get(aInfo.sg_id).bgColor, 4, 0.5);
        }
        oPoly._GeoInfo = aInfo;
        return oPoly;
    };
    
    /**
    *   Create a polyline
    **/   
    this.createPolygon = function(aInfo){        
        var aPoints = this.createPoints(aInfo);
        
        var sEdgecolor = "#" + sColor;
        if ( aInfo.polykleur.length > 0 ){
            var oPoly = new GPolygon(aPoints, "#"+sColor, 1, 1, '#' + aInfo.polykleur, 0.2);
        } else {
            var oPoly = new GPolygon(aPoints, "#"+sColor, 1, 1, '#' + oIconmanager.get(aInfo.sg_id).bgColor, 0.2);
        }
        oPoly._GeoInfo = aInfo;
        return oPoly;
    };
    
    /**
    *   Convert array of lat's and lng's to real GPoints()
    **/
    this.createPoints = function(aInfo){
        this.aPolyBounds[aInfo.id] = new GLatLngBounds();
        var aPoints = aInfo['aGeometry'];
        var i = aPoints.length;
        var aGPoints = [];
        aPoints.reverse;
        while ( i -- ) {
            point = new GLatLng( parseFloat(aPoints[i].lat), parseFloat(aPoints[i].lng) );
            if ( aInfo['g_type'] == 'POLYGON' ) {
                this.addPolyBound(aInfo.id, point);
            }
            aGPoints.push(point);            
        }
        return aGPoints;
    };
    
    /**
    *   @desc Fills collection of bounds for polygones.
    **/    
    this.addPolyBound = function(iId, point){
        this.aPolyBounds[iId].extend(point);
    };
    
    /**
    *   @desc Check if point is in polygon. Trigger click on item.
    *   @param point GPoint
    *   @return boolean Was an item found.
    **/
    this.checkClickedPoly = function(point){
        if ( point ) {
            for ( var i in this.aPolyBounds ){
                if (this.aPolyBounds[i].contains(point)){                    
                    if (this.oPoints[i] && this.oPoints[i].Contains(point)){
                        return i;
                        break;
                    }
                }
            }
        }
        return false;
    };
};/**
*   GMultiPolygon extension. Single mapobject with multiple polygons as geometry
**/
function GMultiPolygon(){
    this._aPolys = Array();
    this._aPolyBounds = Array();
    
    /**
    *   Init, overwrites google functions
    *   @private
    **/
    this._gInitMulti = function(oArg){    
        var aPolyLines = oArg.polylines;
        var i = aPolyLines.length;
        while ( i-- ) {
            this._gAddPoly(GPolygon.fromEncoded({polylines:Array(aPolyLines[i]), fill:false, color:'#000000', opacity:100, outline:false}));
        }    
    };

    /**
    *   Add polygon and polybounds to list.
    *   @param oPoly <a target="_blank" href="http://code.google.com/intl/nl/apis/maps/documentation/reference.html#GPolygon">GPolygon</a> class
    *   @private
    **/ 
    this._gAddPoly = function(oPoly){
        this._aPolyBounds.push( oPoly.getBounds() );
        this._aPolys.push( oPoly );
    };

    /**
    *   Check if multipoly contains point.
    *   @param GPoint <a target="_blank" href="http://code.google.com/intl/nl/apis/maps/documentation/reference.html#GPoint">Google GPoint</a>
    **/
    this.Contains = function(point){
        var i = this._aPolyBounds.length;
        while ( i-- ) {
            if ( this._aPolyBounds[i].contains(point) ) {
                if ( this._gCheckPoly(i, point) ) {
                    return true;
                }
            }
        }
        return false;
    };
    
    /**
    *   @private
    **/
    this._gCheckPoly = function(index, point){
        return this._aPolys[index].Contains(point);
    }    ;
    
    /**
    *   Get bounds of polygon
    **/
    this.getBounds = function() {
        if ( !this.oBounds ) {
            this.oBounds = new GLatLngBounds();
            var i = this._aPolyBounds.length;
            while ( i-- ) {
                this.oBounds.extend(this._aPolyBounds[i].getSouthWest());
                this.oBounds.extend(this._aPolyBounds[i].getNorthEast());
            }
        }
        return this.oBounds;
    };
};/**
*   @extends GPolygon
**/

/**
*   getPoint function for polygon
**/
GPolygon.prototype.getPoint = function(){
    return new GLatLng(parseFloat(this._GeoInfo['lat']), parseFloat(this._GeoInfo['lng']));
};

/**
*   Open InfoWindows for Polyline
**/    
GPolygon.prototype.openInfoWindowHtml = function(content){
    var oRef = this;    
    oGeoStart.oMap.openInfoWindowHtml(this.getPoint(), content, {onOpenFn:this.setUpListeners(this)});
};

GPolygon.prototype.setUpListeners = function(oRef){
    var closeEvent = GEvent.addListener(oGeoStart.oMap, 'infowindowclose', function(){
        GEvent.trigger(oRef, 'infowindowclose');
    });    
    this.handleInfoWindowClose();    
};

GPolygon.prototype.handleInfoWindowClose = function() { 
    var oRef = this;
    GEvent.addListener(oRef, 'infowindowclose', function(){
        try { closeEvent.remove(); } catch(e){}
        try { GEvent.removeListener(closeEvent);  } catch(e){}
    });
    GEvent.trigger(oRef, 'infowindowopen');
};
    
/**
*   @desc Check if polygon contains point.
*   @return boolean
**/    
GPolygon.prototype.Contains = function(point) {
    var j=0;
    var oddNodes = false;
    var x = point.lng();
    var y = point.lat();
    for (var i=0; i < this.getVertexCount(); i++) {
      j++;
      if (j == this.getVertexCount()) {j = 0;}
      if (((this.getVertex(i).lat() < y) && (this.getVertex(j).lat() >= y))
      || ((this.getVertex(j).lat() < y) && (this.getVertex(i).lat() >= y))) {
        if ( this.getVertex(i).lng() + (y - this.getVertex(i).lat())
        /  (this.getVertex(j).lat()-this.getVertex(i).lat())
        *  (this.getVertex(j).lng() - this.getVertex(i).lng())<x ) {
          oddNodes = !oddNodes;
        }
      }
    }
    return oddNodes;
};/**
* @extends GPolyline
**/

/**
*   getPoint function for polyline
**/
GPolyline.prototype.getPoint = function(){
    return new GLatLng(parseFloat(this._GeoInfo['lat']), parseFloat(this._GeoInfo['lng']));
};
    
/**
*   Open InfoWindows for Polyline
*   @param content Html content for infowindow
**/    
GPolyline.prototype.openInfoWindowHtml = function(content){
    var oRef = this;    
    oGeoStart.oMap.openInfoWindowHtml(this.getPoint(), content, {onOpenFn:this._setUpListeners(this)});
};

/**
*   Add event listeneners for inforwindowclose
*   @param oRef  Referenced mapobject
*   @private
**/    
GPolyline.prototype._setUpListeners = function(oRef){
    var closeEvent = GEvent.addListener(oGeoStart.oMap, 'infowindowclose', function(){
        GEvent.trigger(oRef, 'infowindowclose');
    });
    this._handleInfoWindowClose();    
};

/**
*   Handle close of infowindow
*   @private
**/
GPolyline.prototype._handleInfoWindowClose = function() { 
    var oRef = this;
    GEvent.addListener(oRef, 'infowindowclose', function(){
        try { closeEvent.remove(); } catch(e){}
        try { GEvent.removeListener(closeEvent);  } catch(e){}
    });
    GEvent.trigger(oRef, 'infowindowopen');
};

/**
*   @desc Check if polygon contains point. Hopefully works for polyline... *pray*
*   @param GPoint <a target="_blank" href="http://code.google.com/intl/nl/apis/maps/documentation/reference.html#GPoint">Google GPoint</a>
*   @return boolean
**/    
GPolyline.prototype.Contains = function(point) {
    var j=0;
    var oddNodes = false;
    var x = point.lng();
    var y = point.lat();
    for (var i=0; i < this.getVertexCount(); i++) {
      j++;
      if (j == this.getVertexCount()) {j = 0;}
      if (((this.getVertex(i).lat() < y) && (this.getVertex(j).lat() >= y))
      || ((this.getVertex(j).lat() < y) && (this.getVertex(i).lat() >= y))) {
        if ( this.getVertex(i).lng() + (y - this.getVertex(i).lat())
        /  (this.getVertex(j).lat()-this.getVertex(i).lat())
        *  (this.getVertex(j).lng() - this.getVertex(i).lng())<x ) {
          oddNodes = !oddNodes
        }
      }
    }
    return oddNodes;
};/**
*   handle icons. Added to help handle errors in groups etc.
*   @class cIconManager manage icon data in the JS api
*   @constructor
**/
function cIconManager(){
    /**
    *   Get icon of subgroep
    *   @param iId Subgroep id
    *   @param sColor Optionsal color, only used when iId = route
    *   @return oIcon Modified <a href="http://code.google.com/intl/nl/apis/maps/documentation/reference.html#GIcon" target="_blank">GIcon</a>, sg_titel as extra, used by {@link cTooltip} to identify category name.
    **/
    this.get = function(iId, sColor) {
        
        if( typeof(this.oIcons[iId]) == "object" ) {
    
            return this.oIcons[iId];
    
        } else if( iId.indexOf("poi") > -1 ){
            var oIcon           = new GIcon(this.oBaseIcon);
            oIcon.image         = sBaseUrl + "GeoStart/images/poi_icon.png";
            oIcon.sg_titel      = "Bezienswaardigheid";
            return oIcon;
        } else if ( iId.indexOf("route_start") > -1 ) {
            var oIcon           = new GIcon(this.oBaseIcon);
            oIcon.iconSize      = new GSize(10, 10);
            oIcon.iconAnchor    = new GPoint(5, 5);
            oIcon.image         = sBaseUrl + "GeoStart/images/route_start.png";
            oIcon.sg_titel      = "Start van de route";
            return oIcon;
        } else if ( iId.indexOf("route_end") > -1) {
            var oIcon           = new GIcon(this.oBaseIcon);
            oIcon.iconSize      = new GSize(10, 10);
            oIcon.iconAnchor    = new GPoint(5, 5);
            oIcon.image         = sBaseUrl + "GeoStart/images/route_end.png";
            oIcon.sg_titel      = "Einde van de route";
            return oIcon;
        } else if ( iId == 'route' ) {
            var oIcon           = new GIcon(this.oBaseIcon);
            oIcon.iconSize      = new GSize(15, 15);
            oIcon.iconAnchor    = new GPoint(8, 8);
            oIcon.infoWindowAnchor  = new GPoint(8, 8);
            oIcon.image         = sBaseUrl + "icon/" + sColor + "/trans/dot.gif.png";
            oIcon.sg_titel      = "Bezienswaardigheid";
            return oIcon;               
        } else {
            GLog.write("No icon found for " + iId);
            for(var key in this.oIcons ){
                return this.oIcons[key];                
            }
        }
    };
};/**
*	Menu handler.
*	Responsible for menu operations like current status.
*   @class cMenu handle menu data and state's
*   @contructor
**/
function cMenu(){
    /** Array with states **/
	var aState;				// Stores open elements in menu. Reference by menuitem.id
	/** Array with base tree of menu **/
    var aTree;
	/** The menu element (dom) **/
    var oMenuElement;		// The menu element
    
    /** Hoofdrubriek **/
    var iPortal;
    
    /** Subrubriek **/
    var iRubriek;
	
	/**
	*	Initialize menu class
    *   @param sMenuElement Name of the menu element
    *   @param sMenuItemsElement Name of the element to load HTML into
    *   @param sMenuCounterElement Name of the element to load counter data into
	**/
	this.init = function(sMenuElement, sMenuItemsElement, sMenuCounterElement ){
        this.oMenuElement = document.getElementById(sMenuElement);
        this.oMenuItemsElement = document.getElementById(sMenuItemsElement);
		this.oMenuCounterElement = document.getElementById(sMenuCounterElement);
		this.oStateMenu = {};
		this.oStateCB = {};
		this.oStateCategory = {};
		this.oTree = {};
        this.iPortal = 0;
        this.iRubriek = 0;
	};
	

	/**
	*	Call all load state functions
	**/
	this.loadState = function(){
		oMenu.loadDisplayState();
		oMenu.loadCbState();
	};

	/**
	*	Update menu
    *   @param oMenuData Eval-led data gotten from getData.php {@link cGeoStart#update()}
	*   @private
    **/
	this.update = function(oMenuData){
        
        // Als het menu moet worden getoond
        if ( typeof(oSettings) == 'undefined' || oSettings._bMenu !== false ) {
            this.oMenuItemsElement.innerHTML = oMenuData.sMenuHtml;
            this.oMenuCounterElement.innerHTML = oMenuData.sCounterHtml;
        }
        
        // Staat laden
        oMenu.loadState();
        oMenu.oTree = oMenuData.aTree;
		oMenu.oCounter = oMenuData.aMenu;
        oMenu._iVisible = oMenuData.iVisible;
        oMenu.oCatOf = oMenuData.oPointToCat;
        oMenu.iHidden = oMenuData.iHidden;
        
        // Link to cat/subcat afhandelen
        if ( this.iPortal > 0 ) {
            oMenu.setPortal();
        }
        
        
        
        var i = 0; 
        // Tel aantal hoofdmenu items
        for ( var x in this.oTree ) { i++; } 
        
        if ( $('GeoMenu_hg_route') != null ) {
            // Open / closed onthouden
            if ( $('GeoMenu_hg_route') != null && $('GeoMenu_hg_route').className.indexOf('closed') != -1 ) { var sExtra = 'GeoMenu_closed '; } else { var sExtra = ''; }
            
            // Even oneven bepalen
            if (i%2 == 0) { $('GeoMenu_hg_route').className = sExtra + "even"; } 
            else { $('GeoMenu_hg_route').className = sExtra + "uneven"; } 
        }
	};
	
	/**
	*	Return category states, restructured object to array for quicker loops
    *   @return Array
	**/
	this.getCatStates = function(){
		var aReturn = []; // Redo object to array for speed.
		for ( var k in this.oStateCategory ) {
			if ( this.oStateCategory[k] == false ) {
				aReturn.push(k);
			}
		}
		return aReturn;	
	};

	/************************************************
	*												*
	*	Menu display/hide functions					*
	*												*
	************************************************/
		/**
		*	Toggle item referenced by id.
        *   @param sId String DOM id of element
		**/
		this.toggleDisplay = function(sId){
            var oItem = document.getElementById(sId);
            var aClasses = oItem.className.split(' ');
            
            if ( typeof(aClasses[1]) == 'undefined' ) { aClasses[1] = ' '; }
            
            if ( aClasses[0] == 'GeoMenu_closed' ) {
                oItem.className = 'GeoMenu_open ' + aClasses[1];
                oMenu.oStateMenu[sId] = aClasses[1];
            } else {
                oItem.className = 'GeoMenu_closed ' + aClasses[1];
                delete(oMenu.oStateMenu[sId]);
            }
		};
		
        /**
        *   Close all root categories.
        *   @param iClickedId Which element was clicked. This element will not be closed. This is used to be sure only 1 item is open
        **/
        this.closeRoot = function(iClickedId){
            for ( var k in this.oTree ){
                if ( this.oStateMenu['GeoMenu_hg_' + k] != undefined && k != iClickedId) {
                    this.toggleDisplay('GeoMenu_hg_' + k, this.oStateMenu['GeoMenu_hg_' + k]);
                }
            }
        };
        
        /**
        *   Close all subcategories within given root.
        *   @param iHg hoofdgroep id
        *   @param iSg subgroep id
        **/
        this.closeSubs = function(iHg, iSg){
            for ( var k in this.oStateMenu ) {
                if ( this.oStateMenu[k] == " " && k != "GeoMenu_sg_"+iSg ) {
                    this.toggleDisplay(k, this.oStateMenu[k]);
                }
            }
        };
        
        
		/**
		*	Load menu state from {@link cMenu#oStateMenu}
		**/
		this.loadDisplayState = function(){
			for ( k in oMenu.oStateMenu ){
                if ( k.indexOf('_route') == -1 ) {
				    oMenu.toggleDisplay(k, oMenu.oStateMenu[k] );
                }
			}
		};
        
        
        /**
        *   Count current "visible" items whose 
        *   checkboxes arn't checked.
        *   @param string Element which contains the counter.
        **/
        this.countOffItems = function(sElement){
            if ( $(sElement) ) {
                $(sElement).innerHTML = oGeoStart.getVisiblityCounters().iVisible;                
            }
        };
        
        /**
        *   @deprecated Was niet mooi.
        *   @private
        **/
        this.openMenuGroup = function(sId){
            if ( !this.oHeaders ) { this.initMenuGroup(); }        
            for ( var k in this.oHeaders ) {
                if ( k == sId ) {
                    this.oHeaders[k]['menu'].style.display = "";
                    //this.oHeaders[k]['header'].getElementsByTagName('a')[0].innerHTML = "";
                    this.oHeaders[k].action();
                } else {
                    this.oHeaders[k]['menu'].style.display = "none";
                    //this.oHeaders[k]['header'].getElementsByTagName('a')[0].innerHTML = "<img src='images/help_plus.gif'>";
                    this.oHeaders[k]['header'].style.borderTop = "1px solid #D9D9D9";
                    //this.oHeaders[k].action();
                }
            }
        };
        
        
        /**
        *   @deprecated Was niet mooi.
        *   @private
        **/
        this.initMenuGroup = function(){
            this.oHeaders = {};
            this.oHeaders = { 'rubrieken': {'menu':    document.getElementById('menu_rubrieken'),
                                            'header':  document.getElementById('header_rubrieken'),
                                            'action':  function(){ oMenu.toggleAll(true); oGeoStart.oRoutes.hide(); }},
                              'routes':    {'menu':    document.getElementById('menu_routes'),
                                            'header':  document.getElementById('header_routes'),
                                            'action':  function(){ oMenu.toggleAll(false); oGeoStart.oRoutes.show(); }}
                                            };
        };
        
	/************************************************
	*												*
	*	Menu checkbox functions						*
	*												*
	************************************************/
		/**
		*	Toggle a category. Send appropiate commands to cMapObjects
        *   @param iId id of cateogry
        *   @param bDisplay Display or hide
		**/
		this.toggleCategory = function(iId, bDisplay){
			this.setCbState('sg', iId, bDisplay);
			if ( bDisplay ) { oGeoStart.showCategory(iId);
			} else {		  oGeoStart.hideCategory(iId);	}
		};
		
        /**
        *   Handle click of open HG. If currently closed, make sure the markers become visible.
        *   @param iId hoofdgroep id
        *   @private
        **/
        this.handleOpenHg = function(iId){        
            var sResult = $('GeoMenu_hg_'+iId).className.indexOf('closed');
            if ( sResult != -1 ) {
                this.toggleParent(iId, true);
            }            
        }
        
		/**
		*	Toggle parent category.
        *   @param iId Hoofdgroep id
        *   @param bDisplay Show or hide
		*   @private
        **/
		this.toggleParent = function(iId, bDisplay){
            
			var aInfo = [];
			this.setCbState('hg', iId, bDisplay);
			
			for ( var k in this.oTree[iId] ) {
				this.setCbState('sg', k, bDisplay);
				aInfo.push(k);
			}
			
			this.setChildCheckboxes('GeoMenu_hg_' + iId, bDisplay);
			
			if ( bDisplay ){
				oGeoStart.showCategoryGroup(aInfo);
			} else {
				oGeoStart.hideCategoryGroup(aInfo);
			}
		};
		
		/**
		*	Set all child checkboxes of hoofdmenu iId
        *   @param iId Hoofdgroep id
        *   @param bDisplay Show or hide
        *   @privata
		*   @private
        **/
		this.setChildCheckboxes = function(iId, bState){
            var aChildren = document.getElementById(iId).getElementsByTagName('input');
			var i = aChildren.length;
			while ( i-- ){
				aChildren[i].checked = bState;
                oMenu.oStateCB[aChildren[i].id] = bState;
			}
		};
		
		/**
		*	Save checkbox state
        *   @private
		**/
		this.setCbState = function(sG, iId, bChecked){
			oMenu.oStateCB['GeoMenu_' + sG + '_cb_' + iId] = bChecked;			
			if ( sG == 'sg' ) { 
                oMenu.oStateCategory[iId] = bChecked; 
                oGeoStart.loadObjects();
            }
		};
		
		/**
		*   Load checkboxes state into menu.
		**/
		this.loadCbState = function(){
			var aChildren = this.oMenuElement.getElementsByTagName('input');
			var i = aChildren.length;
			while ( i-- ){            
				if ( oMenu.oStateCB[aChildren[i].id] == false ) {
					aChildren[i].checked = false;
				} else {
					aChildren[i].checked = true;	
				}
			}
		};
        
        /**
        *   Toggle all items.
        *   @param sClick What was clicked. Used to check if you click a checkbox, to fix a bug.
        **/
        this.toggleAll = function(sClick){
            var sClick = sClick || '';        
        
            var eCb = document.getElementById('toggleAll');
            
            if ( eCb.type == 'checkbox' ) {                
                if ( sClick != 'input' ) {
                    eCb.checked = !eCb.checked;
                }
                bState = eCb.checked;
            } else {            
                bState = sClick;
                if ( sClick ) {
                    $('toggleOff').className = 'off';
                    $('toggleOn').className = 'on';
                } else {
                    $('toggleOff').className = 'on';
                    $('toggleOn').className = 'off';
                }
            }
                
            this.oStateCB['toggleAll'] = bState;
            this.setChildCheckboxes(this.oMenuElement.id, bState);
            
            for ( var k in this.oTree ) {
                for ( var i in this.oTree[k] ) {
                    this.oStateCategory[i] = bState;
                }
            }
            
            oGeoStart.setAll( bState );
            oGeoStart.loadObjects();
        };
        
    /*************************************************
    *                                                *
    *    List items functions                        *
    *                                                *
    *************************************************/
        /**
        *   Get list of all items in the cateogriy
        *   @param iCategory Category to get the list from
        *   @param iPage Page of the list, defaults to 1.
        **/
        this.getItemList = function(iCategory, iPage){
            var iPage = iPage || 1;
            GDownloadUrl("GeoStart/ajax/getCategoryItems.php?category="+iCategory+"&iPage="+iPage, oMenu.showItemList);
        };
        
        
        /**
        *   Get list of all sport accommedaties
        *   @param iCategory Sport to get the list from
        *   @param iPage Page of the list, defaults to 1.
        **/
        this.getSportList = function(iCategory, iPage){
            var iPage = iPage || 1;
            GDownloadUrl("GeoStart/ajax/getSportItems.php?sport="+iCategory+"&iPage="+iPage, oMenu.showItemList);
        };
        
        
        /**
        *   Show category item list
        *   @param aData array with data from json request {@link cMenu#getSportList}
        **/
        this.showItemList = function(aData){
            
            setTabContent('list');
            
            aJSON = eval("("+aData+")");
            
            /*
            if ( iPage == 1 && typeof(aJSON.sport_titel) == 'undefined' ) {
                pageHit(sBaseUrl + 'portaal/' + aInfo[0].hg_key + '/' + aInfo[0].sg_key );
            }
            */

            document.getElementById('tab_contents_list').innerHTML = aJSON.html;
            document.getElementById('tabTitleText').innerHTML = aJSON.sTitel;
            
            swap('tab', true);
            document.getElementById('iMarkerId').value = '';
            //document.getElementById('iCatId').value = aInfo[i-1].sg_id;
            activate('tabTitle');
            
            return; 
        };
        
    /**
    *   Load the hoofdgroep (open and toggle display)
    **/
    this.setPortal = function(){
        pageHit();

        this.toggleAll(); 
        if ( this.iRubriek > 0 ) {
            this.toggleDisplay("GeoMenu_hg_" + this.iPortal );
            this.toggleDisplay("GeoMenu_sg_" + this.iRubriek );
            $('GeoMenu_sg_cb_'+ this.iRubriek).checked=true;            
            this.toggleCategory(this.iRubriek, true);
        } else {
            this.toggleParent(this.iPortal, true);
            this.toggleDisplay("GeoMenu_hg_" + this.iPortal );
        }
        this.iPortal = 0;
        this.iRubriek = 0;
    }        ;
    
    
    /**
    *   Create a PIPE seperated string to send to getData.php to only load the markers that should be shown.
    **/
    this.getCheckBoxDataString = function(){
        if ( !this.oCheckBoxes ) {
            this.oCheckBoxes = this.oMenuItemsElement.getElementsByTagName('input');
        }        
        var i = this.oCheckBoxes.length;
        
        var aOnBoxes = [];
        
        while ( i-- ) {
            if ( this.oCheckBoxes[i].checked ) {
                if ( this.oCheckBoxes[i].id.indexOf('GeoMenu_sg_cb_') != -1 ) {
                    aOnBoxes.push(this.oCheckBoxes[i].id.substring(14));
                }
            }
        }
        return aOnBoxes.join('|');        
    };
};/**
*	Preloader class.
*		.init(oMap)
*		.updateLoader(iMax, iCurrent)
*		.remove()
*   @class cPreloader Voorgang contol op de kaart, hoeveel is geladen e.d.
**/
function cPreloader(){
	/**
	*	Init the preloader. Create a Control on the map.
	*	Loader: 	geo_preloader_container
	*	Info:		geo_preloader
    *   @param oMap GMap2 object
    *   @param iWidth How width should it be
	**/    
	this.init = function(oMap, iWidth){
        this._iWidth = iWidth || 176;
		this._oMap = oMap;                                                      // GMap2 reference
		this._oControl = new LoaderControl(oMap, iWidth);                               // Control object reference
		this._oMap.addControl(this._oControl);                                  // Load control into map
		this._oDiv = document.getElementById('geo_preloader');                  // Preloader DIV
		this._oText = document.getElementById('geo_preloader_text');            // Preloader text DIV
		this._oContainer = document.getElementById('geo_preloader_container');  // Preloader container
		this._sLoadstring = oSettings._sLoadString;                             // String for when loading ( before counter )
		this._iOperations = 0;
		this._iCurrent = 0;
	};
	

	/**
	*	Start preloader
    *   @param int iOperations Counter for the amount of operations that will be executed.
	**/
	this.start = function(iOperations) {
		this._iOperations = iOperations || 0;
		this._iCurrent = 0;
        this._oText.style.color = "#111";
		this._oText.innerHTML = this._sLoadstring;
		this._oContainer.style.display = "block";
	};


	/**
	*	Set preloader info.
    *   @param int iStep Add number of operations to preloader.
	**/
	this.updateLoader = function( iStep ){
		this._iCurrent += iStep;
		if ( this._iCurrent > 0){
			var percentage = Math.ceil((this._iCurrent / this._iOperations) * 100);
			if ( percentage > 100 ) { percentage = 100; }
            this._oDiv.style.width = percentage + '%'; 
            this._oText.innerHTML = this._iCurrent + ' / ' + this._iOperations;
        } 
	};
	
	/**
	*	Remove preloader. Well, hide actually.
	**/
	this.remove = function() {
		this._oContainer.style.display = 'none';
	};


	/**
	*	Custom preloader control.
	*	Possibly extendable with other styles later on?
    *   @class
	**/	
	var LoaderControl = function(oMap, iWidth) { this.oMap = oMap; this.iWidth = iWidth; };
		LoaderControl.prototype = new GControl(true, false);
		LoaderControl.prototype.initialize = function () {
				var oContainer = document.createElement("div");
				oContainer.innerHTML     	= "<div style='position:absolute;width:100%;border:5px;text-align:center;vertical-align:bottom;' id='geo_preloader_text'></div><div style='height:100%;' id='geo_preloader'></div>";
				oContainer.id 				= "geo_preloader_container";
				oContainer.style.display   	= "none";
				oContainer.style.width   	= this.iWidth + "px";
				oContainer.style.fontSize	= "0.8em";
				oContainer.style.height		= "1.3em";
				oContainer.style.border  	= "1px solid #555"; 
				oContainer.style.backgroundColor = "white";
				oContainer.style.textAlign 	= "left";
				this.oMap.getContainer().appendChild(oContainer);			
				
				return oContainer;
			};
		LoaderControl.prototype.getDefaultPosition = function () {
                return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(10,10));
			};
};/**
*   GeoStart routes functionaliteit
*   @param Id of route element.
*   @class Route klasse. Routes zijn lijnen met tussenpunten. 
**/
function cRoutes(sRouteElement){

    /**
    *   Initlialize, loads data into object.
    **/
    this.init = function(){
        this.getData();
    };

    // Get route information DOm element.
    this.oEle = document.getElementById(sRouteElement);
    this.aHtml = [];    
    
    /**
    *   Ajax request for routes data
    **/
    this.getData = function(){
        GDownloadUrl("GeoStart/ajax/getRouteData.php", oGeoStart.oRoutes.loadData);
    };
        
    /**
    *   Parse JSON and call load functions.
    *   @param sJson JSON string from GeoStart/ajax/getRouteData.php
    *   @private
    **/
    this.loadData = function(sJson) {    
        var oData = eval('('+sJson+')');        
        oGeoStart.oRoutes.oRouteData = oData;
        oGeoStart.oRoutes.initialize();       
        oGeoStart.oRoutes.show(); 
    };
    
    /**
    *   Toggle all routes
    *   @param bState Show/hide
    **/    
    this.toggleAll = function(bState){
        if ( bState ) {
            oGeoStart.oRoutes.show();
        } else {
            oGeoStart.oRoutes.hide();
        }
    };
    
    /**
    *   Create Routes from this.oRouteData
    **/
    this.initialize = function(){
        for ( var k in this.oRouteData ) {
            this.oRouteData[k].oPoly = oGeoStart.createPolyline(this.oRouteData[k]);
            
            //oGeoStart.oMap.addOverlay(this.oRouteData[k].oPoly);
            
            this.oRouteData[k]._PoiSort = Array();
            for ( var p in this.oRouteData[k]._PoiInfo ) {
                this.oRouteData[k]._PoiInfo[p].sg_id = "poi"+this.oRouteData[k].polykleur;
                this.createPoint(this.oRouteData[k]._PoiInfo[p], k);
                this.oRouteData[k]._PoiSort[this.oRouteData[k]._PoiInfo[p].sorteer] = this.oRouteData[k]._PoiInfo[p].id;
            }
            this.createStartEnd(k);            
        }            
    };
    
    /**
    *   Create start and end point of route
    *   @param sRouteId Id of route
    *   @private
    **/
    this.createStartEnd = function(sRouteId){
        this.oRouteData[sRouteId].oPoints['end'] = new GMarker(this.oRouteData[sRouteId].oPoly.getVertex(0), oIconmanager.get('route_end'));
        this.oRouteData[sRouteId].oPoints['start'] = new GMarker(this.oRouteData[sRouteId].oPoly.getVertex(this.oRouteData[sRouteId].oPoly.getVertexCount()-1), oIconmanager.get('route_start'));
        
        
        oGeoStart.oMap.addOverlay(this.oRouteData[sRouteId].oPoints['start']);
        this.oRouteData[sRouteId].oPoints['start'].hide();
        
        oGeoStart.oMap.addOverlay(this.oRouteData[sRouteId].oPoints['end']);
        this.oRouteData[sRouteId].oPoints['end'].hide();
    };
    
    /**
    *   Load/show routes
    **/
    this.show = function(){
        for ( var k in this.oRouteData ) {
            if ( !this.oRouteData[k].shows || this.oRouteData[k].shows == false ) {
                this.oRouteData[k].shows = true;
                oGeoStart.oMap.addOverlay(this.oRouteData[k].oPoly);
                            
                for ( var p in this.oRouteData[k].oPoints ) { 
                    oGeoStart.oMap.addOverlay(this.oRouteData[k].oPoints[p]);
                    if ( p == 'start' || p == 'end' ) {
                        this.oRouteData[k].oPoints[p].hide();
                    }
                }
            }
        }        
    };
    
    /**
    *   Remove/hide routes
    **/
    this.hide = function(){
        for ( var k in this.oRouteData ) {
            if ( this.oRouteData[k].shows || this.oRouteData[k].shows == true ) {
                this.oRouteData[k].shows = false;
                oGeoStart.oMap.removeOverlay(this.oRouteData[k].oPoly);
                            
                for ( var p in this.oRouteData[k].oPoints ) { 
                    oGeoStart.oMap.removeOverlay(this.oRouteData[k].oPoints[p]);
                }
            }
        }        
    };
    
    /**
    *   Check menu for updates on routes.
    *   @private
    **/
    this.update = function(){
        if ( $('GeoMenu_hg_cb_route').checked ) {
            this.show();
        } else {
            this.hide();
        }
        for ( var k in this.oRouteData ) {
            if ( this.oRouteData[k].shows || this.oRouteData[k].shows == true ) {
            
                if ( document.getElementById('GeoMenu_routes_' + k).className.indexOf("_open") != -1  ) {
                    this.highlight(k);
                } else {
                    this.unhighlight(k);
                }
                
            }
        }
    };
    
    /**
    *   Close routes in menu.
    **/    
    this.closeAll = function(sRoute) {
        var aInfo = document.getElementById('GeoMenu_hg_route').getElementsByTagName('li');
        var i = aInfo.length;
        while ( i-- ) {
            if ( aInfo[i].id.indexOf("GeoMenu_routes_") != -1 && aInfo[i].id != "GeoMenu_routes_"+sRoute ) {
                aInfo[i].className = 'GeoMenu_closed';
            }
        }
    };
    
    /**
    *   Direct link for POI ( meer informatie for POI, scrolls to the item ).
    **/
    this.gotoPoiAnchor = function(iPoi){
        $('tab').scrollTop = 0;
        //window.location.hash = '#poi_' + iPoi;
    };
    
    /**
    *   Highlight the route
    **/
    this.highlight = function(k){
        this.oRouteData[k].oPoly.color = "#FF0000";
        oGeoStart.oMap.addOverlay(this.oRouteData[k].oPoly);
                                        
        for ( var p in this.oRouteData[k].oPoints ) {
            if ( p == 'start' || p == 'end' ){
                this.oRouteData[k].oPoints[p].show();
            } else {
                this.oRouteData[k].oPoints[p].setImage(oIconmanager.get('route', 'FF0000').image);
            }
        }
    };
    
    /**
    *   Remove highlight for route
    *   @param sId Id of route
    **/
    this.unhighlight = function(sId){
        this.oRouteData[sId].oPoly.color = "#" + this.oRouteData[sId].polykleur;
        oGeoStart.oMap.addOverlay(this.oRouteData[sId].oPoly);
        for ( var k in this.oRouteData[sId].oPoints ) {
            if ( k == 'start' || k == 'end' ){
                this.oRouteData[sId].oPoints[k].hide();
            } else {
                this.oRouteData[sId].oPoints[k].setImage(oIconmanager.get('route', this.oRouteData[sId].polykleur).image);
            }
        }
    };
    
    /**
    *   Create a single point
    *   @param aInfo array with data
    *   @param sRouteId route id
    *   @private
    **/
    this.createPoint = function(aInfo, sRouteId){
        if ( !this.oRouteData[sRouteId].oPoints ) {
            this.oRouteData[sRouteId].oPoints = {};
        }
        
        var oIcon = oIconmanager.get('route', this.oRouteData[sRouteId].polykleur);
        var point = new GMarker( new GLatLng( parseFloat(aInfo.lat), parseFloat(aInfo.lng) ), oIcon);    // Create object
        var id = aInfo.id;
        
        point.title     = aInfo.titel;          // Define title
        point.tooltip   = aInfo[oSettings._sTooltipField];
        point.type      = "point";            // Set geometry type. Not used yet in 1.0
        point._GeoInfo  = aInfo;                // All information given by cGeoData(PHP!)

        this.pointListeners(point);

        this.oRouteData[sRouteId].oPoints[id] = point;               // Add object to factory
                
        /** Add the overlay to the map **/
        // oGeoStart.oMap.addOverlay(this.oRouteData[sRouteId].oPoints[id]);
        
    };

    
    /**
    *   Show more information in route element.
    *   @param sRoute route id
    **/    
    this.showTabInfo = function(sRoute){
        
        this.oEle.innerHTML = this.getHtml(sRoute);
        
        setTabContent('route');
        
        document.getElementById('tabTitleText').innerHTML = 'Route: ' + this.oRouteData[sRoute].titel;
        
        swap('tab', true);
    };
    
    /**
    *   Generate Meerinfo HTML
    *   @param sRoute route id
    *   @private
    **/
    this.getHtml = function(sRoute){
        if ( !this.oRouteTemplate ) {
            this.oRouteTemplate = new cTemplate();
            this.oRouteTemplate.sTemplateDir = sBaseUrl + 'GeoStart/templates/';
        }
    
        this.oRouteTemplate.loadTemplate('routes/route_meerinfo.js.tpl');
        
        this.oRouteTemplate.assign('sTitle', this.oRouteData[sRoute].titel);
        
        var sRoutePoints = '';
        for ( var i = 0; i < this.oRouteData[sRoute].aGeometry.length; i++ ) {
            if ( i < 49 ) {
                sRoutePoints += '|' + this.oRouteData[sRoute].aGeometry[i].lat + ',' + this.oRouteData[sRoute].aGeometry[i].lng;
            }
        }
        
        this.oRouteTemplate.assign('sGoogleMapsKey', oSettings.sGoogleMapsKey);
        this.oRouteTemplate.assign('sRoutePoints', sRoutePoints);
        if ( this.oRouteData[sRoute].omschrijving.length > 0 ) {
            this.oRouteTemplate.assign('sOmschrijving', this.oRouteData[sRoute].omschrijving);
        }
        
        this.oRouteTemplate.assign('sStatsHtml', this.getStatsHtml(sRoute));
        
        
        var aPoiHtml = [];
        for ( var k in this.oRouteData[sRoute].oPoints ) {
            if ( typeof(this.oRouteData[sRoute].oPoints[k]._GeoInfo) != 'undefined') {
                aPoiHtml.push(this.getPointHtml(this.oRouteData[sRoute].oPoints[k]));
            }
        }
        
        this.oRouteTemplate.assign('sPoiHtml', aPoiHtml.join(''));
        
        return this.oRouteTemplate.fetch();
    };

    /**
    *   Generate single POI html.
    *   @param oPoint GPoint
    *   @private
    **/
    this.getPointHtml = function(oPoint){
        if ( !this.oPoiTemplate ) {
            this.oPoiTemplate = new cTemplate();
            this.oPoiTemplate.sTemplateDir = sBaseUrl + 'GeoStart/templates/';
        }                
        this.oPoiTemplate.loadTemplate('routes/route_poi.js.tpl');
        
        if ( oPoint._GeoInfo.afbeelding != '' ) {
            this.oPoiTemplate.assign('sAfbeelding', sBaseUrl + oPoint._GeoInfo.afbeelding);
        } else {
            this.oPoiTemplate.assign('sAfbeelding', 'http://maps.google.com/staticmap?size=242x180&markers=tinyred|' + oPoint._GeoInfo.lat + ',' + oPoint._GeoInfo.lng +'&key=' + oSettings.sGoogleMapsKey);
        }
        
        this.oPoiTemplate.assign('iRoutePoiId', oPoint._GeoInfo.route_poi_id);
        this.oPoiTemplate.assign('iRouteId', oPoint._GeoInfo.route_id);
        this.oPoiTemplate.assign('sTitle', oPoint.title);
        this.oPoiTemplate.assign('sOmschrijving', oPoint._GeoInfo.omschrijving);

        return this.oPoiTemplate.fetch();
    };
    
    /**
    *   Generate Statistics HTML
    *   @param sRoute Route id
    *   @private
    **/
    this.getStatsHtml =function(sRoute){
        if ( !this.oStatsTemplate ) {
            this.oStatsTemplate = new cTemplate();
            this.oStatsTemplate.sTemplateDir = sBaseUrl + 'GeoStart/templates/';
        }                
        this.oStatsTemplate.loadTemplate('routes/route_stats.js.tpl');
        
        var iMeters = Math.round(this.oRouteData[sRoute].oPoly.getLength());
        var iPoiCount = 0;
        for ( var x in this.oRouteData[sRoute].oPoints ) { 
            iPoiCount++;
        }
        
        this.oStatsTemplate.assign('iMeters', iMeters);
        this.oStatsTemplate.assign('iPoiCount', iPoiCount);
        
        return this.oStatsTemplate.fetch();
    };
    
    
    /**
    *   Listeners for POI marker
    *   @param point GPoint
    *   @private
    **/
    this.pointListeners = function(oRef){
        GEvent.addListener(oRef, "mouseover", function() {
            if ( oRef.type == "point" ) {                
                oGeoStart.oRoutes.highlight('route_' + oRef._GeoInfo.route_id);
                
                if ( oGeoStart._bEnableHover ) {
                    oGeoStart._hoverListener.remove();
                
                    if ( oGeoStart._oTooltip.markerOnScreen(oRef.getPoint()) ) {                // Check if marker is onscreen
                        oGeoStart._oTooltip.checkAlign(oRef.g_type);
                        oGeoStart._oTooltip.setText(oRef.title);
                        oGeoStart._oTooltip.addCat('poi');
                        
                        oGeoStart._oTooltip.show(oRef.getPoint());
                    }
                }
            }
            
        });
        
        GEvent.addListener(oRef, 'mouseout', function(){ oGeoStart.oRoutes.update(); });
        
        GEvent.addListener(oRef, 'click', function(){            
            oRef.openInfoWindowHtml(oGeoStart.oRoutes.getInfoWindowHtml(oRef._GeoInfo['route_id'], oRef._GeoInfo['route_poi_id']));
        });
    };
    
    /**
    *   Trigger event on poi of route
    *   @param sRoute Route id
    *   @param sPoi Poi id
    *   @param sEvent Event to trigger here
    **/
    this.trigger = function(sRoute, sPoi, sEvent){
        if ( this.oRouteData[sRoute].shows && this.oRouteData[sRoute].shows == true ) {
            GEvent.trigger(oGeoStart.oRoutes.oRouteData[sRoute].oPoints[sPoi], sEvent);
        }
    };
    
    
    /**
    *   Generate Infowindow HTML
    *   @param iRouteId route id
    *   @param iPoiId POI id
    *   @private
    **/
    this.getInfoWindowHtml = function(iRouteId, iPoiId){
        if ( !oGeoStart.oTemplate ) {
            oGeoStart.oTemplate = new cTemplate();
            oGeoStart.oTemplate.sTemplateDir = sBaseUrl + 'GeoStart/templates/';
        }                
        
    
        oGeoStart.oTemplate.loadTemplate('routes/route_infowindow.js.tpl');
        oGeoStart.oTemplate.assign('sTitel', this.oRouteData['route_' + iRouteId].oPoints['routep'+iPoiId]._GeoInfo.titel);
        oGeoStart.oTemplate.assign('iPoiId', iPoiId);
        oGeoStart.oTemplate.assign('iRouteId', iRouteId);
        oGeoStart.oTemplate.assign('iSorteer', this.oRouteData['route_' + iRouteId].oPoints['routep'+iPoiId]._GeoInfo.sorteer);
        oGeoStart.oTemplate.assign('iRouteId', iRouteId);
        
        return oGeoStart.oTemplate.fetch();        
    };
    
    
    /**
    *   Bereken volgende poi en trigger een click erop
    *   @param iRoute Route id
    *   @param iSorteer Current poi sorteer value
    *   @private
    **/
    this.nextPoi = function(iRoute, iSorteer){
        if ( iSorteer != this.oRouteData['route_' + iRoute]._PoiSort.length - 1 ) {
            this.trigger('route_' + iRoute, this.oRouteData['route_' + iRoute]._PoiSort[iSorteer + 1], 'click');
        } else {
            this.trigger('route_' + iRoute, this.oRouteData['route_' + iRoute]._PoiSort[1], 'click');
        }
    };
    
    /**
    *   Bereken vorige poi en trigger een click erop
    *   @param iRoute Route id
    *   @param iSorteer Current poi sorteer value
    *   @private
    **/
    this.prevPoi = function(iRoute, iSorteer){
        if ( iSorteer != this.oRouteData['route_' + iRoute]._PoiSort.length - 1 ) {
            this.trigger('route_' + iRoute, this.oRouteData['route_' + iRoute]._PoiSort[iSorteer - 1], 'click');
        } else {
            this.trigger('route_' + iRoute, this.oRouteData['route_' + iRoute]._PoiSort[this.oRouteData['route_' + iRoute]._PoiSort-1], 'click');
        }
    };
};/**
*   @desc   State machine class for geostart. First draft version. 
*           Saves state of current GeoStart.
*            
*            Version history:
*               0.1:    Primary skeleton
*               1.0:    Productie versie                
*
*   @author Bjorn Brala - Swis BV
*   @class cStateMachine Sla je huidige locatie/zoom/menu up in een cookie en laad deze eventueel later weer
**/
function cStateMachine() {
    this.aCookie = Array();
    
    /**
    *   @desc Initiliaze
    **/
    this.init = function(){
        this.loadCurrentState();
        if ( this.oState ) {
            this.changeToDelete();
            this.loadMapState();        
            this.loadMenuState();
        }
    };
    
    
    /**
    *   @desc Save current state
    **/
    this.saveCurrentState = function(){
        this.changeToDelete();
        this.saveCookie();
    };
    
    
    this.deleteCurrentState = function(){
        this.changeToSave();
        this.deleteCookieVars();
    };
    
    /**
    *   Change icon to delete state
    *   @private
    **/
    this.changeToDelete = function(){
        if ( !oGeoStart.oStateMachine.oImage ) {
            oGeoStart.oStateMachine.oImage = document.getElementById('save_settings_image');
        }
        if ( !this.oLink ) {
            oGeoStart.oStateMachine.oLink =  document.getElementById('save_settings_link');
        }
        oGeoStart.oStateMachine.oImage.src = "GeoStart/images/controls/icon_save_loading.gif";
        oGeoStart.oStateMachine.oLink.innerHTML = "Startpagina wordt opgeslagen...";
                
        setTimeout('oGeoStart.oStateMachine.oImage.src = "GeoStart/images/controls/icon_save_delete.gif";oGeoStart.oStateMachine.oLink.innerHTML = "Verwijder uw startpagina";oGeoStart.oStateMachine.oLink.onclick=function(){oGeoStart.oStateMachine.deleteCurrentState();return false;}', 1000);
    };
    
    /**
    *   @private
    **/
    this.changeToSave = function(){
        if ( !oGeoStart.oStateMachine.oImage ) {
            oGeoStart.oStateMachine.oImage = document.getElementById('save_settings_image');
        }
        if ( !oGeoStart.oStateMachine.oLink ) {
            oGeoStart.oStateMachine.oLink =  document.getElementById('save_settings_link');
        }
        
        oGeoStart.oStateMachine.oImage.src = "GeoStart/images/controls/icon_save_loading.gif";
        oGeoStart.oStateMachine.oLink.innerHTML = "Startpagina wordt verwijderd...";
        
        setTimeout('oGeoStart.oStateMachine.oImage.src = "GeoStart/images/controls/icon_save_as.gif";oGeoStart.oStateMachine.oLink.innerHTML = "Stel in als startpagina";oGeoStart.oStateMachine.oLink.onclick=function(){oGeoStart.oStateMachine.saveCurrentState();return false;}', 1000);        
    };
    
    /**
    *   @desc Load current state
    **/
    this.loadCurrentState = function(){
        // Load cookie information into state variable.
        this.oState = this.readCookie();               
    };
    

    /**
    *   @desc Get and save menu state
    *   @private
    **/
    this.getMenuState = function(){    
        
        // Menu CheckBox State (oStateCB)
        var oStateCB = "";
        for ( var key in oMenu.oStateCB ) {
            oStateCB += key + ":" + oMenu.oStateCB[key] + "|";
        }    
        
        // Menu cat state ( oStateCategory
        var oStateCategory = "";
        for ( var key in oMenu.oStateCategory ) {
            oStateCategory += key + ":" + oMenu.oStateCategory[key] + "|";  
            
        }    
        
        
        // Menu category classname (oStateMenu)
        var oStateMenu = "";
        for ( var key in oMenu.oStateMenu ) {
            oStateMenu += key + ":" + oMenu.oStateMenu[key] + "|";
        }
        
        var aCookie = Array();        
        aCookie.push("GeoStart_oStateCB="       + oStateCB + ";"        + this.expires);
        aCookie.push("GeoStart_oStateMenu="     + oStateMenu + ";"      + this.expires);
        aCookie.push("GeoStart_oStateCategory=" + oStateCategory + ";"  + this.expires);
        
        return aCookie;
    };
    
    /**
    *   @desc Get and save current map view
    *   @private
    **/
    this.getMapState = function(){
        var aCookie = Array();
        
        aCookie.push("GeoStart_lng=" + oGeoStart.oMap.getCenter().lng() + ";" + this.expires);
        aCookie.push("GeoStart_lat=" + oGeoStart.oMap.getCenter().lat() + ";" + this.expires);
        aCookie.push("GeoStart_zoom=" + oGeoStart.oMap.getZoom() + ";" + this.expires);
        
        return aCookie;
    
        // Get Center
        // Get Zoom
        // Get maptype
    };
    
    /**
    *   @desc Load Map State
    *   @private
    **/
    this.loadMapState = function(){
        setTimeout('oGeoStart.oMap.setZoom(parseInt(' + this.oState.GeoStart_zoom + '))', 1);
        
        setTimeout('oGeoStart.oMap.setCenter(new GLatLng(parseFloat(' + this.oState.GeoStart_lat + '), parseFloat(' + this.oState.GeoStart_lng + ')))', 100);
    };
    
    
    /**
    *   @desc   Load menu state from the cookie
    *           Helaas heel custom, kreeg JSON niet in 2 min aan de praat.
    *   @private
    **/
    this.loadMenuState = function(){
        if ( this.oState.GeoStart_oStateCB && this.oState.GeoStart_oStateCB.length > 0 ) {
            var aResult = this.oState.GeoStart_oStateCB.split("|");
            var i = aResult.length;
            while ( i-- ) {
                if ( aResult[i].length > 0 ) {
                    var aItem = aResult[i].split(":");
                    oMenu.oStateCB[aItem[0]] = aItem[1];
                }
            }
        }        

        
        if ( this.oState.GeoStart_oStateCategory && this.oState.GeoStart_oStateCategory.length > 0 ) {
            var aResult = this.oState.GeoStart_oStateCategory.split("|");
            var i = aResult.length;
            while ( i-- ) {
                if ( aResult[i].length > 0 ) {
                    var aItem = aResult[i].split(":");
                    oMenu.oStateCategory[aItem[0]] = aItem[1];
                }
            }
        }        
        
        
        if ( this.oState.GeoStart_oStateMenu && this.oState.GeoStart_oStateMenu.length > 0 ) {
            var aResult = this.oState.GeoStart_oStateMenu.split("|");
            var i = aResult.length;
            while ( i-- ) {
                if ( aResult[i].length > 0 ) {
                    var aItem = aResult[i].split(":");
                    oMenu.oStateMenu[aItem[0]] = aItem[1];
                }
            }
        }        

    };
    
    /**
    *   @desc Write information to a cookie
    *   @param days Days to save the cookie
    **/
    this.saveCookie = function(days){
        this.aCookie = Array();
    
        var days = days || 365;
        var date = new Date();
        date.setTime(date.getTime()+(days*24*60*60*1000));
        this.expires = " expires="+date.toGMTString();
    
        this.createCookie();
        
        var i = this.aCookie.length;
        
        while ( i-- ) {
            document.cookie = this.aCookie[i];
        }
    };
  
    /**
    *   @desc Create cookie string from saved variabled.
    **/  
    this.createCookie =function(){
        var aMapState = this.getMapState();
        var i = aMapState.length;
        while ( i-- ) {
            this.aCookie.push(aMapState[i]);
        }        

        var aMenuState = this.getMenuState();
        var i = aMenuState.length;
        while ( i-- ) {
            this.aCookie.push(aMenuState[i]);
        }        
        return;
    }
    ;
    /**
    *   @desc Read information from cookie
    *   @private
    **/
    this.readCookie = function(){
        var ca = document.cookie.split(';');
        var oReturn = false;
        
        for(var i=0;i < ca.length;i++) {
            var c = ca[i];
            while (c.charAt(0)==' ') c = c.substring(1,c.length);
                if ( c.indexOf("GeoStart_") != -1 ) {
                    if ( !oReturn ) {
                        oReturn = {};
                    }
                    oReturn[c.substring(0, c.indexOf("="))] = c.substring(c.indexOf("=")+1, c.length);
                }
        }
        return oReturn;
    };
    
    
    /**
    *   @desc Delete current cookie
    *   @private
    **/
    this.deleteCookieVars = function(){
        this.saveCookie(-1);
    };
    
    
};/**
*   @desc   State machine class for geostart. First draft version. 
*           Saves state of current GeoStart.
*            
*            Version history:
*               0.1:    Primary skeleton
*               1.0:    First implementation        1-5-2008
*
*   @author Bjorn Brala - Swis BV
*   @class cStateMachineMapOnly Sla je huidige locatie op in een cookie en laadt deze eventueel weer. Te gebruiken om bijvoorbeeld een kaart op dezelfde plek te houden als je naar een andere pagina doorklikt.
**/
function cStateMachineMapOnly() {
    this.aCookie = Array();
    this.bDisabled = false;
    
    /**
    *   @desc Initiliaze
    **/
    this.init = function(){
        if ( oGeoStart.oMap.isLoaded() ) {
            var days = days || 365;
            var date = new Date();
            date.setTime(date.getTime()+(days*24*60*60*1000));
            this.expires = " expires="+date.toGMTString()+"; path=/";
        
            this.loadCurrentState();
            if ( this.oState && this.bDisabled == false ) {
                this.loadMapState();        
            }        
        } else {
            setTimeout('oState.init()', 100);
        }
    };
    
    
    /**
    *   @desc Update cookie information and write it ( mapmove etc )
    **/
    this.update = function(){
        this.createCookie();
        this.saveCookie();
    };
    
    /**
    *   @desc Save current state
    **/
    this.saveCurrentState = function(){
        this.saveCookie();
    };

    
    /**
    *   @desc Load current state
    **/
    this.loadCurrentState = function(){
        // Load cookie information into state variable.
        this.oState = this.readCookie();               
    };
    

    /**
    *   @desc Get and save current map view
    *   @private
    **/
    this.getMapState = function(){
        var aCookie = Array();
        
        aCookie.push("GeoStart_lng=" + oGeoStart.oMap.getCenter().lng() + ";" + this.expires);
        aCookie.push("GeoStart_lat=" + oGeoStart.oMap.getCenter().lat() + ";" + this.expires);
        aCookie.push("GeoStart_zoom=" + oGeoStart.oMap.getZoom() + ";" + this.expires);
        
        return aCookie;
    
        // Get Center
        // Get Zoom
        // Get maptype
    };
    
    /**
    *   @desc Load Map State
    *   @private
    **/
    this.loadMapState = function(){
        setTimeout('oGeoStart.oMap.setZoom(parseInt(' + this.oState.GeoStart_zoom + '))', 1);
        setTimeout('oGeoStart.oMap.setCenter(new GLatLng(parseFloat(' + this.oState.GeoStart_lat + '), parseFloat(' + this.oState.GeoStart_lng + ')))', 100);
    };
    
    /**
    *   @desc Write information to a cookie
    **/
    this.saveCookie = function(days){
        this.aCookie = Array();
    
        this.createCookie();
        
        var i = this.aCookie.length;
        
        while ( i-- ) {
            document.cookie = this.aCookie[i];
        }
    };
  
    /**
    *   @desc Create cookie string from saved variabled.
    **/  
    this.createCookie =function(){
        var aMapState = this.getMapState();
        var i = aMapState.length;
        while ( i-- ) {
            this.aCookie.push(aMapState[i]);
        }        

        return;
    };
    
    /**
    *   @desc Read information from cookie
    *   @private
    **/
    this.readCookie = function(){
        var ca = document.cookie.split(';');
        var oReturn = false;
        
        for(var i=0;i < ca.length;i++) {
            var c = ca[i];
            while (c.charAt(0)==' ') c = c.substring(1,c.length);
                if ( c.indexOf("GeoStart_") != -1 ) {
                    if ( !oReturn ) {
                        oReturn = {};
                    }
                    oReturn[c.substring(0, c.indexOf("="))] = c.substring(c.indexOf("=")+1, c.length);
                }
        }
        return oReturn;
    };
    
    
    /**
    *   @desc Delete current cookie
    *   @private
    **/
    this.deleteCookieVars = function(){
        this.saveCookie(-1);
    };
    
    
};/**
*   cTemplate.class.js
*
*   Javascript smarty
* @class cTemplate Javascript smarty templates. if en section zijn ondersteund.
**/
function cTemplate(){

    this.oRequest = new cRequest();     
    this.sCurrentTemplate = null;
    this.sTemplateDir = '';
    this.sTemplate = [];

    /**
    *   @Desc Haal template op en cache deze
    *   @param tempalte name
    */
    this.loadTemplate = function(sName){
        // cache
        if (!this.sTemplate[sName]){
            this.oRequest.sUrl    = this.sTemplateDir + sName; 
            this.sTemplate[sName] = this.oRequest.getContent().responseText; 
        }
        this.sCurrentTemplate = this.sTemplate[sName];

        if ( typeof(sBaseUrl) != 'undefined' ) {
            this.assign('sBaseUrl', sBaseUrl);        
        }
    };

    /**
    *   @Desc assign een variabele in de template
    *   @param sFind Variable name
    *   @param mReplace Value
    */
    this.assign = function(sFind, mReplace){
        if ( typeof(mReplace) != 'object' ) {
            mReplace = mReplace+"";
            if ( mReplace.length > 0 ) {
                this.doReplace(sFind, mReplace);
            }
        } else {
            this.doReplace(sFind, mReplace);
        }
        
    };    
    
    /**
    *   Do the replace action
    *   @param sFind Variable name
    *   @param mReplace Value
    **/
    this.doReplace = function(sFind, mReplace){

        var self = this;  
        var oRegex = new RegExp('\\{if \\$' + sFind + '\\}(.|[\r\n])*?\\{\\/if\\}');
        this.sCurrentTemplate = this.sCurrentTemplate.replace(oRegex, function($0, $1){ return self.parseIf($0, $1, sFind, mReplace)});
        var result = oRegex.exec(this.sCurrentTemplate);
        if ( result != null ) {
            this.doReplace(sFind, mReplace);
        }
        
        switch(typeof(mReplace)){
            case 'string':                                              
                var oRegex = new RegExp('\\{\\$' + sFind + '\\}', 'gi');                
                this.sCurrentTemplate = this.sCurrentTemplate.replace(oRegex, mReplace);
                break;
            case 'object':
                var oRegex = new RegExp('\\{section name=(.*) loop=\\$' + sFind + '\\}(.|[\r\n])*?\\{\\/section\\}');
                this.sCurrentTemplate = this.sCurrentTemplate.replace(oRegex, function($0, $1){ return self.parseSection($0, $1, sFind, mReplace)});
            break;    
        }
        
        var result = oRegex.exec(this.sCurrentTemplate);
        if ( result != null ) {
            this.doReplace(sFind, mReplace);
        }
    };
        
    /**
    * Parse a section and replace what is needed
    *   @param sSection Sectio nanme
    *   @param sCycler name
    *   @param sFind Variable name
    *   @param mReplace Value
    **/
    this.parseSection = function(sSection, sCycler, sFind, mReplace){

        // section tags eruit strippen
        var oRegex = new RegExp('\\{section name=(.*) loop=\\$(.*)\\}', 'g');  
        sSection = sSection.replace(oRegex, ''); 
        var oRegex = new RegExp('\\{\\/section\\}', 'g');  
        sSection = sSection.replace(oRegex, ''); 

        // loopen en vervangen
        var iMax    =  mReplace.length;
        var self    = this;
        var sReturn = '';

        for(var i=0; i < iMax; i++){
            var sHtml = '';
            var oRegex = new RegExp('\\{\\$' + sFind + '\\[' + sCycler + '\\]\\.([a-z0-9_]+)\\}', 'gi');   
            sHtml += sSection.replace(oRegex, function($0, $1){ return self.parseSectionVar($0, $1, i, sFind, mReplace)});
            sReturn += sHtml;
        }

        return sReturn;
    };

    /**
    *   @desc Parse and eval section variable.
    *   @param sSection Sectio nanme
    *   @param sVarName Variable name
    *   @param i Iteration
    *   @param sFind Variable name
    *   @param mReplace Value
    **/
    this.parseSectionVar = function(sSection, sVarName, i, sFind, mReplace){
        return eval( 'mReplace[' + i + '].' + sVarName);
    };

    /**
    *   @desc If vars eruit strippen en kale string terug geven
    **/
    this.parseIf = function(sIf, sCycler, sFind, mReplace){

        // IF tags eruit strippen
        var oRegex = new RegExp('\\{if \\$' + sFind + '\\}', 'g');  
        sIf = sIf.replace(oRegex, ''); 
        
        var oRegex = new RegExp('\\{\\/if\\}', 'g');  
        sIf = sIf.replace(oRegex, ''); 

        return sIf;
        
    };

    /*
    // test om IF statement te vinden. Lukt even niet :(

    var oRegex = new RegExp('\\{if (\\$' + sFind + '.*)\\}(.|[\r\n])*?\\{\\/if\\}');
    console.log('\\{if \\$' + sFind + '(.)*\\}(.|[\r\n])*?\\{\\/if\\}');
    console.log(oRegex.exec(this.sCurrentTemplate));


    this.parseIfExpression = function(sIf, sCycler, sFind, mReplace){

    console.log(sIf);

    // section tags eruit strippen
    var oRegex = new RegExp('\\{if \\$' + sFind + '(.^\\{)*\\}', 'g');  

    sIf = sIf.replace(oRegex, ''); 

    console.log(sIf);

    var oRegex = new RegExp('\\{\\/if\\}', 'g');  
    sIf = sIf.replace(oRegex, ''); 

    console.log(sIf);

    return sIf;
    }


    */

    /**
    *   Clean up wrapper
    **/
    this.cleanUp = function(){
        this.cleanSections();
        this.cleanIfs();
        this.cleanVars();
    };
        

    /**
    *   Ongebruikte IF statements eruit halen.
    **/
    this.cleanIfs = function(){
    
        // Zonder word boundry, dus {if $VAR}, alvast voor IF statements.
        var oRegex = new RegExp('\\{if \\$(.)*\\}(.|[\r\n](^\\{\\/if\\}))*\\{\\/if\\}', 'g');
        this.sCurrentTemplate = this.sCurrentTemplate.replace(oRegex, '');        

        // Kijken of er nog meer IF statements over zijn.
        var result = oRegex.exec(this.sCurrentTemplate);
        if ( result != null ) {
            this.cleanIfs();
        }

        //Met geneste sectie. Wellicht overbodig... Nog ff testen.
        var oRegex = new RegExp('\\{if \\$(.)*\\}(.|[\r\n])*?(\\{\\/section\\}|\\{\\/if\\})\\{\\/if\\}', 'g');
        this.sCurrentTemplate = this.sCurrentTemplate.replace(oRegex, '');        
        
        // Kijken of er nog meer if statements over zijn.
        var result = oRegex.exec(this.sCurrentTemplate);
        if ( result != null ) {
            this.cleanIfs();
        }
        
    };
    
    
    
    /**
    *   Ongebruikte vars weghalen.
    **/
    this.cleanVars = function(){
        var oRegex = new RegExp('\\{\\$[a-z0-9]*\\}', 'gi');    
        
        this.sCurrentTemplate = this.sCurrentTemplate.replace(oRegex, '');        
        
        // Kijken of er nog meer variabelen over zijn.
        var result = oRegex.exec(this.sCurrentTemplate);
        if ( result != null ) {
            this.cleanVars();
        }
    };
    
    
    
    /**
    *   Clean ongebruikte sections
    **/
    this.cleanSections = function(){
    
        // Clean unused sections
        var oRegex = new RegExp('\\{section name=(.*) loop=\\$(.)*\\}(.|[\r\n])*?\\{\\/section\\}');
        
        this.sCurrentTemplate = this.sCurrentTemplate.replace(oRegex, '');
        
        var result = oRegex.exec(this.sCurrentTemplate);
        if ( result != null ) {
            this.cleanSections();
        }
        
        
        
    };

    /** 
    *  @Desc Return de template
    *
    */
    this.fetch = function(){
        this.cleanUp();
        return this.sCurrentTemplate;
    };
};/**
*   @class cTooltip v. 2.0
    Class showing / hiding a tooltip at certain 
    point on the map. Tooltip can contain any 
    information.
*
*   Björn Brala - Swis BV
**/
function cTooltip(oMap, sDiv, iTargetWidth, iTargetHeight, iOffsetX, iOffsetY) {
    this._oMap = oMap;                              // GMap2 object
    this._eDiv = $(sDiv);                           // Tooltip element
    this._iTargetWidth = iTargetWidth || 0;         // Width in pixels of target element
    this._iTargetHeight = iTargetHeight || 0;       // Heigth in pixels of target element
    this._iOffsetX = iOffsetX || 0;                 // Offset X in pixels - Tweaking x position
    this._iOffsetY = iOffsetY || 0;                 // Offset Y in pixels - Tweaking y position
    this._bCenter = false;
    var self = this;
    
    //GEvent.addDomListener(self._eDiv, 'mouseover', function(){self.hide();});
    
    /** 
    *   Determine if tooltip should center itself or align to the right/left
    *   @private
    **/
    this.checkAlign = function(sType){
        this._current = sType;
        switch ( sType ) {
            case "POINT":                
                this._bCenter = false;
                break;
            case "LINESTRING":
                this._bCenter = true;
                break;
            case "POLYGON":
                this._bCenter = true;
                break;
            case "MULTIPOLYGON":
                this._bCenter = true;
                break;
        }
    };
        
    
    /**
    *   Crossbrowser find position voor DOM object
    *   @param obj DOM object
    *   @private
    **/
    this.findPos = function(obj) {
        var curleft = curtop = 0;
        if (obj.offsetParent) {
            curleft = obj.offsetLeft;
            curtop = obj.offsetTop;
            while (obj = obj.offsetParent) {
                curleft += obj.offsetLeft;
                curtop += obj.offsetTop;
            }
        }
        return [curleft,curtop];
    };
    
    /**
    *   Function used by getPosition. Results in a and b difference (in coordignates)
    *   @private
    **/
    this.subGPoints = function (a,b) {
        return new GPoint(a.x - b.x, a.y - b.y);
    };
   
    /**
    *   Get position for the tooltip. Checks of right side is out of bounds. If so, display left.
    *   @return object with x and y ( object.x, object.y )
    *   @param point GPOint
    **/
    this.getPixelPosition = function(point){ 
                
        //var mapOffsetTop        = this._oMap.getContainer().offsetTop;
        //var mapOffsetLeft       = this._oMap.getContainer().offsetLeft;

        //var oMapPos             = this.findPos(this._oMap.getContainer());
        
        // Bug: Bij een map met een offset aan de linker kant IE telt te 
        // offset op bij het totaal hetgeen resulteerd in een positie die te ver naar rechts is.
        
        var mapOffsetTop        = this._oMap.getContainer().offsetTop;
        var mapOffsetLeft       = this._oMap.getContainer().offsetLeft;
        
        var TlcLatLng           = this._oMap.fromContainerPixelToLatLng(new GPoint(0,0),true);
        var TlcDivPixel         = this._oMap.fromLatLngToDivPixel(TlcLatLng);
        var pointDivPixel       = this._oMap.fromLatLngToDivPixel(point);
        var pointContainerPixel = this.subGPoints(pointDivPixel, TlcDivPixel);     

        // Get bounds information for the map
        var bounds          = this._oMap.getBounds();
        var boundsSpan      = bounds.toSpan();
        var longSpan        = boundsSpan.lng();
        var latSpan        = boundsSpan.lat();
        var mapWidth        = this._oMap.getSize().width;
        var mapHeight        = this._oMap.getSize().height;
        
        // Convert pixel width to degrees ( map width )
        this._eDiv.style.width = "500px";
        document.getElementById('middle').style.width = "500px";
        
        if ( this._eImg.offsetWidth > this._eText.offsetWidth ) {
            this._eDiv.style.width = ( this._eImg.offsetWidth + 50 ) + "px";
            document.getElementById('middle').style.width = oGeoStart._oTooltip._eDiv.style.width
        } else {
            this._eDiv.style.width = ( this._eText.offsetWidth + 50 ) + "px";
            document.getElementById('middle').style.width = oGeoStart._oTooltip._eDiv.style.width
        }
        
        var tooltipWidthInDeg = ( this._eDiv.offsetWidth ) / mapWidth * longSpan;
        var tooltipHeightInDeg = ( this._eDiv.offsetHeight ) / mapHeight * latSpan;

        // Offset tooltip to align to center of point. Used for polygones etc.
        if ( this._bCenter ) { 
            iCenterOffsetY = 0;
            iCenterOffsetX = ( this._eDiv.offsetWidth / 2 ) + (this._iTargetWidth/2);            
        } else { 
            iCenterOffsetX = 0; 
            iCenterOffsetY = 0; 
        }
        
        
        if ( !this._leftImage ) {
            this._leftImage = document.getElementById("tooltip_topleft");
        }
        if ( !this._rightImage ) {
            this._rightImage = document.getElementById("tooltip_topright");
        }            
        
        if ( !this._leftBottomImage ) {
            this._leftBottomImage = document.getElementById("tooltip_bottomleft");
        }
        if ( !this._rightBottomImage ) {
            this._rightBottomImage = document.getElementById("tooltip_bottomright");
        }            
        
        
        // Check for X position.        
        if ( ( point.lng() + tooltipWidthInDeg ) > bounds.getNorthEast().lng() ) {      
            pointContainerPixel.x = pointContainerPixel.x - this._eDiv.offsetWidth - (Math.round(this._iTargetWidth/2)) + mapOffsetLeft +  this._iOffsetX;
            this._leftImage.src = "GeoStart/images/tooltip/top_left_flip.png";
            this._rightImage.src = "GeoStart/images/tooltip/top_right_flip.png";
        } else {                                                                        
            pointContainerPixel.x = pointContainerPixel.x + (Math.round(this._iTargetWidth/2)) + this._iOffsetX + mapOffsetLeft - iCenterOffsetX;
            this._leftImage.src = "GeoStart/images/tooltip/top_left.png";
            this._rightImage.src = "GeoStart/images/tooltip/top_right.png";
        }       
        
        // Check for Y position
        if ( ( point.lat() - tooltipHeightInDeg ) < bounds.getSouthWest().lat() ) {
            pointContainerPixel.y = pointContainerPixel.y - this._eDiv.offsetHeight + ( this._iTargetHeight / 2 ) + this._iOffsetY + mapOffsetTop;
   
            //this._leftBottomImage.src = "GeoStart/images/tooltip/bottom_left_flip.png"
            //this._rightBottomImage.src = "GeoStart/images/tooltip/bottom_right_flip.png"
   
        } else {
            pointContainerPixel.y = pointContainerPixel.y - (this._iTargetWidth/2) + this._iOffsetY + mapOffsetTop;

            //this._leftBottomImage.src = "GeoStart/images/tooltip/bottom_left.png"
            //this._rightBottomImage.src = "GeoStart/images/tooltip/bottom_right.png"
        }
        
        //GLog.write(pointContainerPixel.x + 'x' + pointContainerPixel.y + ' - pointpixelcontainer');
        
        return pointContainerPixel;
    };
    
    
    /**
    *   check if tooltip is onscreen
    *   @param point GPoint
    *   @return boolean True/false
    **/
    this.markerOnScreen = function (point) {
        var bounds = this._oMap.getBounds();
        // check for onscreen.
        if ( bounds.contains(point) ) {
            return true;
        } else {
            return false;    
        }
    };


    /** 
    *   Show tooltip on object
    *   @param point GPoint
    **/
    this.show = function(point){
        this._bIsHidden = false;
        var oCoordinates = this.getPixelPosition(point);
        this._eDiv.style.top = oCoordinates.y + 'px';
        this._eDiv.style.left = oCoordinates.x + 'px';                                                
    };
    
    /**
    *   Helper, show tooltip at pixel position
    *   @private
    **/
    this.showPixels = function(oPixels){
        var point = this._oMap.fromContainerPixelToLatLng(oPixels);
        this.show(point);
    };
    
    /*
    this.setText = function(sText){
        this._eDiv.innerHTML = sText;
    }*/
    
    /**
    *   Hides the tooltip div.
    **/
    this.hide = function () {
        this._bIsHidden = true;
        this._current = false;
        this._eDiv.style.left = '-5000px';
        this._eDiv.style.top = '0px';
    };
    
    /**
    *   Hides the tooltip div.
    *   @private
    **/
    this.hideTooltip  = function () {
        this._eDiv.style.left = '-500px';
        this._eDiv.style.top = '0px';
    };
    
    /**
    *   Pas tooltip titel aan
    *   @param sText titel
    **/
    this.setText = function(sText) {
        if ( !this._eText ) {
            this._eText = document.getElementById('tooltip_title');        
        }
        this._eText.innerHTML = sText;
    };
    
    /**
    *   Category met mId invoegen. 
    *   @param {number|object} Nummer = cat id, object = 'array' met subgroepen.
    **/
    this.addCat = function(mId) {
        if ( !this._eImg ) {
            this._eImg = document.getElementById('tooltip_content');        
        }
        if ( typeof(mId) == 'number' ||  typeof(mId) == "string") {
            this._eImg.innerHTML = '<span><img class="icon" src="'+ oIconmanager.get(mId).image +'">'+oIconmanager.get(mId).sg_titel+'</span><br />';
        } else if ( typeof(mId) == 'object' ) {
            var sImageSet = '';
            var bFirst = true;
            for ( var key in mId ) {
                if ( bFirst ) {
                    bFirst = false;
                    sImageSet += '<span><img class="icon" src="'+ oIconmanager.get(mId[parseInt(key)]).image +'">'+oIconmanager.get(mId[parseInt(key)]).sg_titel+'</span><br />';
                } else {
                    sImageSet += '<span style="margin-left:20px;padding-top:2px;"><img class="icon" src="'+ oIconmanager.get(mId[parseInt(key)]).image +'">'+oIconmanager.get(mId[parseInt(key)]).sg_titel+'</span><br />';
                }
            }   
            this._eImg.innerHTML = sImageSet;
        }        
    };  
}/**
*   @desc cZones - Handler for zones. Hide / show on zoom and such.
*   @desc todo Optimize drag, hide zones when dragging
*   @class cZones Zone functionliteit, zone is een polygoon met een label. De zone kan veranderen in een lijn bij een bepaald zoomniveau en verdwijnen bij een bepaald zoomniveau.
**/
function cZones(oMap){
    this.oMap = oMap;
    this.aZones = [];
    this.sCurrentlyLoaded = "none";
    this.aLoadedOverlays = [];
    
    /**
    *   @desc initialize zone data
    **/
    this.init = function(){
        this.loadSettings();
        
        this.loadData();
        
        this.loadMapListeners();
        
        return this;
    };
    
    
    
    /**
    *   Example optimisation for dragging
    
    GEvent.addListener(oMapObjects.oMap, 'dragstart', function(){oVergunningen.setVisibility(false);});
    GEvent.addListener(oMapObjects.oMap, 'dragend', function(){ oVergunningen.setVisibility(true);});
    
    **/
    
    
    /**
    *   @desc Load settings for zones.
    **/
    this.loadSettings = function(){
        
        this._sDataUrl      = this._sDataUrl        || "GeoStart/ajax/getZoneData.php";
        
        this._iZoomVisible  = this._iZoomVisible    || 12;
        this._iZoomFilled   = this._iZoomFilled     || 14;
        this._iZoomHidden   = this._iZoomHidden     || 19;
        this._sColor        = this._sColor          || "#4C1664";
        this._iOpacity      = this._iOpacity        || "0.5";
        this._iBorderWidth  = this._iBorderWidth    || 3;
        this.bFirstLoad     = this.bFirstLoad       || true;
        this.bVisible       = this.bVisible         || true;
        
        if ( this.bStartInvisble === true ) {
            this.bVisible = false;
        }        
    };
    
    /**
    *   Enable balloon for data field
    *   @param sField field with data for in the balloon
    **/
    this.enableBalloon = function(sField){
        var i = this.aZones.length;
        if ( i > 0 ) {
            while ( i-- ) {
                this.aZones[i].text.enableBalloon(sField);
            }
        } else {
            this.sEnableBalloon = sField;
        }
    };
    
    /**
    *   Do an ajax call with callback
    **/
    this.loadData = function(){
        if ( !sUser ) {
            var sUser = null; 
        }   
        GDownloadUrl( this._sDataUrl + "?sUser=" + sUser, GEvent.callback(this, this.loadZoneData));
    };
    
    
    /**
    *   load the data gotten from the data url.
    *   @private
    *   @param oJson Jason string
    **/
    this.loadZoneData = function(oJson){
        var aData = eval('(' + oJson + ')');
        
        var i = aData.length;
        
        while ( i-- ) {
            // Poly data
            this.aZones[i] = {  "polyline": this.createPolyline(aData[i]),
                                "polygon":  this.createPolygon(aData[i]),
                                "text":     this.createZoneLabel(aData[i]),
                                "id":       aData[i].id
                                };                                
            this.aZones[i].bounds = this.aZones[i].polyline.getBounds();
            this.aZones[i].text['_bounds'] = this.aZones[i].polyline.getBounds();
            
            
            if ( aData[i].kleur.length == 6 ) {
                this.aZones[i].kleur = "#" + aData[i].kleur;
            } else {
                this.aZones[i].kleur = this._sColor;
            }
            
        }
        
        // First load logic
        if ( this.bFirstLoad && this.bStartInvisble != true ) {
            this.bStartInvisble = false;
            this.bFirstLoad = false;
            
            if ( this.sEnableBalloon ) {
                this.enableBalloon(this.sEnableBalloon);
            }            
            this.updateZones();
        } else if ( this.bFirstLoad ) {
            if ( this.sEnableBalloon ) {
                this.enableBalloon(this.sEnableBalloon);
            }
        }
    };
    
    
    /**
    *   Map listener to handle map chenges
    *   @private
    **/   
    this.loadMapListeners = function(){
        var oThis = this;
        GEvent.addListener(oThis.oMap, 'moveend', GEvent.callback(this, this.updateZones));
    };
    /**
    *   Toggle visibility
    *   @return boolean
    **/
    this.toggle = function(){
        if ( this.bFirstLoad ) {
            this.bFirstLoad = false;
            this.updateZones();
        }
    
        this.bVisible = !this.bVisible;
        this.visibility(this.bVisible); 
        return this.bVisible;       
    }
    
    /**
    *   Optimezed hide/show function
    **/
    this.setVisibility = function(bState) {
        if ( this.bFirstLoad ) {
            this.bFirstLoad = false;
            this.updateZones();
        }
        if ( this.bVisible !== bState ) {
            this.bVisible = bState;
            this.visibility(this.bVisible);
        }
    };

    /**
    *   Generate click on zone
    *   @param iId Zone id
    **/
    this.clickZone = function(iId){
        var i = this.aZones.length;
        while ( i-- ) {
            if ( parseInt(this.aZones[i].id) == parseInt(iId) ) {
                this.aZones[i].text.clickHandler();
                return;
            }
        }
    };
    
    
    /**
    *   Show / Hide all
    *   @param bState true/false
    **/
    this.visibility = function(bState){
        var i = this.aLoadedOverlays.length;
        if ( i > 0 ) {
            while ( i-- ) {
                if ( bState ) {
                    this.aLoadedOverlays[i].show();
                } else {
                    this.aLoadedOverlays[i].hide();
                }
            }
        }
    };
    
    /**
    *   Adding/removing zones and changing opacity.
    *   @private
    **/
    this.updateZones = function(){
        var state = this.checkForStateChange();
        if ( state ) {
            this.removeAll();            
            this.updateDisplay(state);
            this.sCurrentlyLoaded = state;
        }
    };
    
    
    /**
    *   remove old overlays
    *   @private
    **/
    this.removeAll = function(){
        var i = this.aLoadedOverlays.length;
        if ( i > 0 ) {
            while(i--){
                this.oMap.removeOverlay(this.aLoadedOverlays[i]);
            }
            this.aLoadedOverlays = Array();
        }
    };
    
    /**
    *   Update the display of zones. Depending on state it will be displayed.
    *   @private
    *   @param sState polygon/none/polyline
    **/
    this.updateDisplay = function(sState){
        switch ( sState ) {
            case "none":
                break;
            case "polygon":
                var i = this.aZones.length;
                while ( i-- ) {
                    this.oMap.addOverlay(this.aZones[i].polygon);
                    this.aLoadedOverlays.push(this.aZones[i].polygon);                    
                    this.oMap.addOverlay(this.aZones[i].text);
                    this.aLoadedOverlays.push(this.aZones[i].text);                    
                }
                break;
            case "polyline":
                var i = this.aZones.length;
                while ( i-- ) {
                    this.oMap.addOverlay(this.aZones[i].polyline);
                    this.aLoadedOverlays.push(this.aZones[i].polyline);                    
                }
                break;        
        }
        this.visibility(this.bVisible);
    };
    
    /**
    *   Check what should be loaded at this time.
    *   @private
    **/
    this.checkForStateChange = function(){
        var iZoom   = this.oMap.getZoom();        
        var sNewState;

        if ( iZoom < this._iZoomVisible ) {
            sNewState = "none";
        } else if ( iZoom >= this._iZoomVisible && iZoom <= this._iZoomFilled ) {
            sNewState = "polygon";
        } else if ( iZoom >= this._iZoomFilled && iZoom <= this._iZoomHidden ) {
            sNewState = "polyline";
        } else if ( iZoom < this._iZoomHidden ) {
            sNewState = "none";
        }
        if ( sNewState == this.sCurrentlyLoaded ) {
            return false;
        } else {
            return sNewState;
        }
    };
    
    /**
    *   Create a polyline
    *   @param aInfo Default information from ajax/getZoneData.php
    *   @private
    **/   
    this.createPolyline = function(aInfo){
        var aPoints = this.createPoints(aInfo);
        if ( aInfo.kleur && aInfo.kleur.length == 6 ) {
            var sKleur  = "#"+aInfo.kleur;
        } else { 
            var sKleur = this._sColor;
        }
        var oPoly = new GPolyline(aPoints, sKleur, this._iBorderWidth, 1);

        
        oPoly._GeoInfo = aInfo;
        return oPoly;
    };
    
    /**
    *   Create a polyline
    *   @param aInfo Default information from ajax/getZoneData.php
    *   @private
    **/   
    this.createPolygon = function(aInfo){        
        var aPoints = this.createPoints(aInfo);
        
        if ( aInfo.kleur && aInfo.kleur.length == 6 ) {
            var sKleur  = "#"+aInfo.kleur;
        }else{ 
            var sKleur = this._sColor;
        }

        var oPoly = new GPolygon(aPoints, sKleur, this._iBorderWidth, parseFloat(0.8), sKleur, parseFloat(this._iOpacity));
        oPoly._GeoInfo = aInfo;
        return oPoly;
    };
    
    /**
    *   Create the center label for the polygone.
    *   @param aInfo Default information from ajax/getZoneData.php
    *   @private
    **/
    this.createZoneLabel = function(aInfo){
        var sTitel  = aInfo.titel;
        var point   = new GLatLng(parseFloat(aInfo.lat), parseFloat(aInfo.lng));
        var oLabel  = new ZoneLabel(point, sTitel);
        oLabel._Data = aInfo;
        return oLabel;
    };
    
    
    /**
    *   Convert array of lat's and lng's to real GPoints()
    *   @param aInfo Default information from ajax/getZoneData.php
    *   @private
    **/
    this.createPoints = function(aInfo){
        var aPoints = aInfo['aGeometry'];
        var i = aPoints.length;
        var aGPoints = new Array();
        aPoints.reverse;
        while ( i -- ) {
            point = new GLatLng( parseFloat(aPoints[i].lat), parseFloat(aPoints[i].lng) );
            aGPoints.push(point);
        }
        return aGPoints;
    };
};

/**
*   Zone label. sText 5 times superimposed with a small offset to sumilate a white glow
*   @param point GPoin
*   @param sText Label text
*   @contructor
**/
function ZoneLabel(point, sText) {
    this._sText = sText;
    this._point = point;
};
ZoneLabel.prototype = new GOverlay();



/**
*   Create the label HTML
**/
ZoneLabel.prototype.initialize = function(map) {

    var oElement = document.createElement('div');
    
    oElement.style.position     = "absolute";
    oElement.style.textAlign    = "center";
    oElement.style.width        = "50px";
    oElement.style.height       = "20px";
    oElement.style.cursor       = "pointer";
    
    var aText = Array();
    
    aText.push("<span style='position:absolute;top:1px;left:1px;z-index:1000000000;color:black;'>"+this._sText+"</span>");
    aText.push("<span style='position:absolute;top:0px;left:0px;color:white;'>"+this._sText+"</span>");
    aText.push("<span style='position:absolute;top:2px;left:2px;color:white;'>"+this._sText+"</span>");
    aText.push("<span style='position:absolute;top:2px;left:0px;color:white;'>"+this._sText+"</span>");
    aText.push("<span style='position:absolute;top:0px;left:2px;color:white;'>"+this._sText+"</span>");
    var sText = aText.join('');
    
    oElement.innerHTML = sText;
    
    // Our rectangle is flat against the map, so we add our selves to the
    // MAP_PANE pane, which is at the same z-index as the map itself (i.e.,
    // below the marker shadows)
    map.getPane(G_MAP_MARKER_SHADOW_PANE).appendChild(oElement);
    
    this.map_ = map;
    this.div_ = oElement;
    var self = this;
    GEvent.addDomListener(oElement, 'click', function(){
        self.clickHandler();
    });
    
};


/**
*   You can enable the ballon for zone labels.
*   @param sField which field of aData to use
**/
ZoneLabel.prototype.enableBalloon = function(sField){
    this.balloonEnabled = true;
    this.balloonField = sField;
};

/**
*   Generate balloon HTML, should actually be a template.
*   @todo MOVE TO TEMPLATE
**/
ZoneLabel.prototype.getBalloonHtml = function(){    
    var oElement = document.createElement("div");
    oElement.className = "infoWindow";
    var aHtml = new Array();
    
    aHtml.push("<strong>"+this._Data['titel']+"</strong>");
    aHtml.push("<p>"+this._Data[this.balloonField]+"</p>");
    oElement.innerHTML = aHtml.join('');
        
    var oLink = document.createElement("a");
    oLink.className = "zoomAnchor";
    oLink.innerHTML = "<img alt='+' src='GeoStart/images/controls/grey/small_plus.gif'/> Zoom in naar de zone";
    var href = document.createAttribute('href');
    href.nodeValue = "#";
    oLink.setAttributeNode(href);
    
    var oLinkDiv = document.createElement("div");
    oLinkDiv.className = "ballonButton";
    oLinkDiv.appendChild(oLink);
    oLinkDiv.style.paddingTop = "20px";
    
    var self = this;
    GEvent.addDomListener(oLink, 'click', function(){
        self.zoomToZone();
        self.map_.closeInfoWindow();
    });
    oElement.appendChild(oLinkDiv);
    return oElement;
};
/**
*   What to do when zone label is clicked.
**/
ZoneLabel.prototype.clickHandler = function(){
    if ( this.balloonEnabled ) {
        this.map_.openInfoWindowHtml(this._point, this.getBalloonHtml());
    } else {
        this.zoomToZone();
    }
};


/**
*   Zoom to the zone
**/
ZoneLabel.prototype.zoomToZone = function(){
    this.map_.setCenter(this._point, this.map_.getBoundsZoomLevel(this._bounds));
};
/**
*   Hide the main DIV on the map pane
**/
ZoneLabel.prototype.hide = function() {
  this.div_.style.display = "none";
};

/**
*   Show the main DIV on the map pane
**/
ZoneLabel.prototype.show = function() {
  this.div_.style.display = "block";
};

/**
* Remove the main DIV from the map pane
**/
ZoneLabel.prototype.remove = function() {
  this.div_.parentNode.removeChild(this.div_);
};

/**
*   Copy our data to a new Rectangle
**/
ZoneLabel.prototype.copy = function() {
  return new ZoneLabel(this._point, this._sText);
};

// Redraw the rectangle based on the current projection and zoom level
ZoneLabel.prototype.redraw = function(force) {
  // We only need to redraw if the coordinate system has changed
  if (!force) return;
  
  // Calculate the DIV coordinates of two opposite corners of our bounds to
  // get the size and position of our rectangle
  var coords = this.map_.fromLatLngToDivPixel(this._point);
  
  this.div_.style.left = ( coords.x - 25 ) + "px";
  this.div_.style.top = ( coords.y - 10 ) + "px";
  
};
var reasons=[];
 reasons[200]   = "Success";
 reasons[601]   = "Het adres mist.";
 reasons[602]   = "Onbekend adres:  Controleer de ingevulde adressen.";
 reasons[603]   = "Onmogelijk adres:  Helaas kan om contractuele redenen het adres niet worden weergegeven.";
 reasons[610]   = "Foute Key: Neem contact op met de systeem beheerder.";
 reasons[500]   = "Server fout: De aanvraag kan op dit moment niet worden behandeld. Probeer het later nog eens.";

 
/**
*   Placeholder direction function.
*   Directions should be integrated with GeoStart
**/
function getDirections(sFrom, sTo){
    m_activate('route');    
    
    
    oDir.load('from: ' + sFrom + ' to: ' + sTo );
    
}

function checkStatus(iCode){
    if ( iCode != 200 ){
        routeError(reasons[iCode]);
    }
}

function showDirForm(sDirection, sTitel){
    m_activate('route');
    if ( sTitel != '' ) { $('routeHead').innerHTML = sTitel+":";  }
    $('dest').value = sDirection;
    cleanInput('Straat, postcode, stad', 'source');
    $('source').focus();
}

function loadDirections(oForm) {
    sLocation   = oForm.dest.value;
    sHome       = oForm.source.value;
    
    if ( sLocation == '' || sHome == '' ) {
        routeError('U heeft niet alle velden ingevuld.');
    } else {
        $('routeInner').innerHTML = '';
        getDirections(sHome, sLocation);
    }
}

function routeError(sText){
    $('routeInner').innerHTML = '<span style="color:red;font-weight:bold;">' + sText + '</span>';
}


function swapRouteInput(){
    var source  = $('source').value;
    var dest    = $('dest').value;
    
    $('source').value   = dest;
    $('dest').value     = source;   
}

function openPrintRoute(){
    var source  = $('source').value.replace(' ', '+');
    var dest    = $('dest').value.replace(' ', '+');
    
    var printLink = "http://maps.google.com/maps?f=d&hl=nl&geocode=&saddr=__SOURCE__&daddr=__DEST__&ie=UTF8&cd=1&om=1&pw=2";
    
    printLink = printLink.replace(/__SOURCE__/g, source);
    printLink = printLink.replace(/__DEST__/g, dest);
    
    window.open(printLink);
}

function routeClear(){
    oDir.clear();
    $('source').value = 'Straat, postcode, plaats';
    $('dest').value = '';
    $('routeInner').innerHTML = '';
}function vergunningenkaart(){
    this.width = 475;
    this.height = 400;
    
    this.display = function(sPlaatsnaam){
    
        var p = escape(document.location.href);
        var rfr = escape(document.referrer);
        if (rfr == "undefined"){ 
            rfr = "";
        }
        var sHTML    = '<iframe style="float:none;margin:2px;" frameborder="0" ';
        sHTML       += 'src="http://www.vergunningenkaart.nl/MapMaker/' + sPlaatsnaam +'&location=' + p + '&rfr=' + rfr + '" ';
        sHTML       += 'width="' + this.width + 'px" height="' + this.height + 'px"></iframe>';
        document.writeln(sHTML);
        
    }
}
vergunningenkaart = new vergunningenkaart();/*
* ExtInfoWindow Class, v1.0 
*  Copyright (c) 2007, Joe Monahan (http://www.seejoecode.com)
* 
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* 
*       http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This class lets you add an info window to the map which mimics GInfoWindow
* and allows for users to skin it via CSS.  Additionally it has options to
* pull in HTML content from an ajax request, triggered when a user clicks on
* the associated marker.
*/


/**
 * Creates a new ExtInfoWindow that will initialize by reading styles from css
 *
 * @constructor
 * @param {GMarker} marker The marker associated with the info window
 * @param {String} windowId The DOM Id we will use to reference the info window
 * @param {String} html The HTML contents
 * @param {Object} opt_opts A contianer for optional arguments:
 *    {String} ajaxUrl The Url to hit on the server to request some contents 
 *    {Number} paddingX The padding size in pixels that the info window will leave on 
 *                    the left and right sides of the map when panning is involved.
 *    {Number} paddingY The padding size in pixels that the info window will leave on 
 *                    the top and bottom sides of the map when panning is involved.
 *    {Number} beakOffset The repositioning offset for when aligning the beak element. 
 *                    This is used to make sure the beak lines up correcting if the 
 *                    info window styling containers a border.
 */
function ExtInfoWindow(marker, windowId, html, opt_opts) {
  this.html_ = html;
  this.marker_ = marker;
  this.infoWindowId_ = windowId;

  this.options_ = opt_opts == null ? {} : opt_opts;
  this.ajaxUrl_ = this.options_.ajaxUrl == null ? null : this.options_.ajaxUrl;
  this.callback_ = this.options_.ajaxCallback == null ? null : this.options_.ajaxCallback;
  
  this.maxContent_ = this.options_.maxContent == null ? null : this.options_.maxContent;
  this.maximizeEnabled_ = this.maxContent_ == null ? false : true;
  this.isMaximized_ = false;

  this.borderSize_ = this.options_.beakOffset == null ? 0 : this.options_.beakOffset;
  this.paddingX_ = this.options_.paddingX == null ? 0 + this.borderSize_ : this.options_.paddingX + this.borderSize_;
  this.paddingY_ = this.options_.paddingY == null ? 0 + this.borderSize_ : this.options_.paddingY + this.borderSize_;

  this.map_ = null;

  this.container_ = document.createElement('div');
  this.container_.style.position = 'relative';
  this.container_.style.display = 'none';

  this.contentDiv_ = document.createElement('div');
  this.contentDiv_.id = this.infoWindowId_ + '_contents';
  this.contentDiv_.innerHTML = this.html_;
  this.contentDiv_.style.display = 'block';
  this.contentDiv_.style.visibility = 'hidden';

  this.wrapperDiv_ = document.createElement('div');
};

//use the GOverlay class
ExtInfoWindow.prototype = new GOverlay();

/**
 * Called by GMap2's addOverlay method.  Creates the wrapping div for our info window and adds
 * it to the relevant map pane.  Also binds mousedown event to a private function so that they
 * are not passed to the underlying map.  Finally, performs ajax request if set up to use ajax
 * in the constructor.
 * @param {GMap2} map The map that has had this extInfoWindow is added to it.
 */
ExtInfoWindow.prototype.initialize = function(map) {
  this.map_ = map;

  if( this.maximizeEnabled_ ){
    this.maxWidth_ = this.map_.getSize().width * 0.9;
    this.maxHeight_ = this.map_.getSize().height * 0.9;
  }

  this.defaultStyles = {
    containerWidth: this.map_.getSize().width / 2,
    borderSize: 1
  };

  this.wrapperParts = {
    tl:{t:0, l:0, w:0, h:0, domElement: null},
    t:{t:0, l:0, w:0, h:0, domElement: null},
    tr:{t:0, l:0, w:0, h:0, domElement: null},
    l:{t:0, l:0, w:0, h:0, domElement: null},
    r:{t:0, l:0, w:0, h:0, domElement: null},
    bl:{t:0, l:0, w:0, h:0, domElement: null},
    b:{t:0, l:0, w:0, h:0, domElement: null},
    br:{t:0, l:0, w:0, h:0, domElement: null},
    beak:{t:0, l:0, w:0, h:0, domElement: null},
    close:{t:0, l:0, w:0, h:0, domElement: null}
  };
  if( this.maximizeEnabled_ ){
    this.wrapperParts.max = {t:0, l:0, w:0, h:0, domElement: null}
    this.wrapperParts.min = {t:0, l:0, w:0, h:0, domElement: null}
  }

  for (var i in this.wrapperParts ) {
    var tempElement = document.createElement('div');
    tempElement.id = this.infoWindowId_ + '_' + i;
    tempElement.style.visibility = 'hidden';
    document.body.appendChild(tempElement);
    tempElement = document.getElementById(this.infoWindowId_ + '_' + i);
    var tempWrapperPart = this.wrapperParts[i];    
    tempWrapperPart.w = parseInt(this.getStyle_(tempElement, 'width'), 10);
    tempWrapperPart.h = parseInt(this.getStyle_(tempElement, 'height'), 10);
    document.body.removeChild(tempElement);
  }
  for (var i in this.wrapperParts) {
    if (i == 'close' ) {
      //first append the content so the close button is layered above it
      this.wrapperDiv_.appendChild(this.contentDiv_);
    }
    var wrapperPartsDiv = null;
    if (this.wrapperParts[i].domElement == null) {
      wrapperPartsDiv = document.createElement('div');
      this.wrapperDiv_.appendChild(wrapperPartsDiv);
    } else {
      wrapperPartsDiv = this.wrapperParts[i].domElement;
    }
    wrapperPartsDiv.id = this.infoWindowId_ + '_' + i;
    wrapperPartsDiv.style.position = 'absolute';
    wrapperPartsDiv.style.width = this.wrapperParts[i].w + 'px';
    wrapperPartsDiv.style.height = this.wrapperParts[i].h + 'px';
    wrapperPartsDiv.style.top = this.wrapperParts[i].t + 'px';
    wrapperPartsDiv.style.left = this.wrapperParts[i].l + 'px';
    this.wrapperParts[i].domElement = wrapperPartsDiv;
  }
  
  this.map_.getPane(G_MAP_FLOAT_PANE).appendChild(this.container_);
  this.container_.id = this.infoWindowId_;
  var containerWidth  = this.getStyle_(document.getElementById(this.infoWindowId_), 'width');
  this.container_.style.width = (containerWidth == null ? this.defaultStyles.containerWidth : containerWidth);

  this.map_.getContainer().appendChild(this.contentDiv_);
  this.contentWidth = this.getDimensions_(this.container_).width;
  this.contentDiv_.style.width = this.contentWidth + 'px';
  this.contentDiv_.style.position = 'absolute';

  this.container_.appendChild(this.wrapperDiv_);
  
  if( this.maximizeEnabled_ ){
    this.minWidth_ = this.getDimensions_(this.container_).width;
    console.log(this.minWidth_);
  }
  
  if (this.maximizeEnabled_) {
    thisMap = this.map_;
    thisMaxWidth = this.maxWidth_;
    thisMaxHeight = this.maxHeight_;
    thisContainer = this.container_;
    thisMaxContent = this.maxContent_;
    if(this.marker_) {
      GEvent.trigger(this.marker_, 'extinfowindowbeforeclose'); 
    }

    thisMinWidth = this.container_.style.width;
    thisMinHeight = this.container_.style.height;
    //add event handler for maximize and minimize icons
    GEvent.addDomListener(this.wrapperParts.max.domElement, 'click', 
      function() {
        var infoWindow = thisMap.getExtInfoWindow();
        infoWindow.container_.style.width = thisMaxWidth + 'px';
        infoWindow.ajaxRequest_(thisMaxContent);

    if(this.marker_) {
      GEvent.trigger(this.marker_, 'extinfowindowclose');
    }
        infoWindow.isMaximized_ = true;
        infoWindow.redraw(true);
      
        //swap min/max icons
        infoWindow.toggleMaxMin_();
      }
    );
    GEvent.addDomListener(this.wrapperParts.min.domElement, 'click', 
      function() {
        var infoWindow = thisMap.getExtInfoWindow();
        infoWindow.container_.style.width = thisMinWidth;
        infoWindow.container_.style.height = thisMinHeight;
        if (infoWindow.ajaxUrl_ != null ) {
           infoWindow.ajaxRequest_(this.ajaxUrl_);
        }else{
          infoWindow.contentDiv_.innerHTML = infoWindow.html_;
        }
        
        infoWindow.isMaximized_ = false;
        infoWindow.redraw(true);
        infoWindow.resize();

        //swap min/max icons
        infoWindow.toggleMaxMin_();
      }
    );
    
    this.toggleMaxMin_();
    
  }

  var stealEvents = ['mousedown', 'dblclick', 'DOMMouseScroll'];
  for( i=0; i < stealEvents.length; i++ ){
    GEvent.bindDom(this.container_, stealEvents[i], this, this.onClick_);
  }

  GEvent.trigger(this.map_, 'extinfowindowopen');
  if (this.ajaxUrl_ != null ) {
    this.ajaxRequest_(this.ajaxUrl_);
  }
};

/**
 * Private function to steal mouse click events to prevent it from returning to the map.
 * Without this links in the ExtInfoWindow would not work, and you could click to zoom or drag 
 * the map behind it.
 * @private
 * @param {MouseEvent} e The mouse event caught by this function
 */
ExtInfoWindow.prototype.onClick_ = function(e) {
  if(navigator.userAgent.toLowerCase().indexOf('msie') != -1 && document.all) {
    window.event.cancelBubble = true;
    window.event.returnValue = false;
  } else {
    //e.preventDefault();
    e.stopPropagation();
  }
};

/**
 * Remove the extInfoWindow container from the map pane. 
 */
ExtInfoWindow.prototype.remove = function() {
  if (this.map_.getExtInfoWindow() != null) {
    GEvent.trigger(this.map_, 'extinfowindowbeforeclose');
    
    GEvent.clearInstanceListeners(this.container_);
    if (this.container_.outerHTML) {
      this.container_.outerHTML = ''; //prevent pseudo-leak in IE
    }
    if (this.container_.parentNode) {
      this.container_.parentNode.removeChild(this.container_);
    }
    this.container_ = null;
    GEvent.trigger(this.map_, 'extinfowindowclose');
    this.map_.setExtInfoWindow_(null);
  }
};

/**
 * Return a copy of this overlay, for the parent Map to duplicate itself in full. This
 * is part of the Overlay interface and is used, for example, to copy everything in the 
 * main view into the mini-map.
 * @return {GOverlay}
 */
ExtInfoWindow.prototype.copy = function() {
  return new ExtInfoWindow(this.marker_, this.infoWindowId_, this.html_, this.options_);
};

/**
 * Draw extInfoWindow and wrapping decorators onto the map.  Resize and reposition
 * the map as necessary. 
 * @param {Boolean} force Will be true when pixel coordinates need to be recomputed.
 */
ExtInfoWindow.prototype.redraw = function(force) {
  if (!force || this.container_ == null) return;
  
  //set the content section's height, needed so  browser font resizing does not affect the window's dimensions
  var contentHeight = this.contentDiv_.offsetHeight;
  this.contentDiv_.style.height = contentHeight + 'px';
  
  this.contentWidth = this.getDimensions_(this.container_).width;
  this.contentDiv_.style.width = this.container_.style.width;

  //reposition contents depending on wrapper parts.
  //this is necessary for content that is pulled in via ajax
  this.contentDiv_.style.left = this.wrapperParts.l.w + 'px';
  this.contentDiv_.style.top = this.wrapperParts.tl.h + 'px';
  this.contentDiv_.style.visibility = 'visible';

  //Finish configuring wrapper parts that were not set in initialization
  this.wrapperParts.tl.t = 0;
  this.wrapperParts.tl.l = 0;
  this.wrapperParts.t.l = this.wrapperParts.tl.w;
  this.wrapperParts.t.w = (this.wrapperParts.l.w + this.contentWidth + this.wrapperParts.r.w) - this.wrapperParts.tl.w - this.wrapperParts.tr.w;
  this.wrapperParts.t.h = this.wrapperParts.tl.h;
  this.wrapperParts.tr.l = this.wrapperParts.t.w + this.wrapperParts.tl.w;
  this.wrapperParts.l.t = this.wrapperParts.tl.h;
  this.wrapperParts.l.h = contentHeight;
  this.wrapperParts.r.l = this.contentWidth + this.wrapperParts.l.w;
  this.wrapperParts.r.t = this.wrapperParts.tr.h;
  this.wrapperParts.r.h = contentHeight;
  this.wrapperParts.bl.t = contentHeight + this.wrapperParts.tl.h;
  this.wrapperParts.b.l = this.wrapperParts.bl.w;
  this.wrapperParts.b.t = contentHeight + this.wrapperParts.tl.h;
  this.wrapperParts.b.w = (this.wrapperParts.l.w + this.contentWidth + this.wrapperParts.r.w) - this.wrapperParts.bl.w - this.wrapperParts.br.w;
  this.wrapperParts.b.h = this.wrapperParts.bl.h;
  this.wrapperParts.br.l = this.wrapperParts.b.w + this.wrapperParts.bl.w;
  this.wrapperParts.br.t = contentHeight + this.wrapperParts.tr.h;
  this.wrapperParts.beak.l = this.borderSize_ + (this.contentWidth / 2) - (this.wrapperParts.beak.w / 2);
  this.wrapperParts.beak.t = this.wrapperParts.bl.t + this.wrapperParts.bl.h - this.borderSize_;
  this.wrapperParts.close.l = this.wrapperParts.tr.l +this.wrapperParts.tr.w - this.wrapperParts.close.w - this.borderSize_;
  this.wrapperParts.close.t = this.borderSize_;
  if( this.maximizeEnabled_ ){
    this.wrapperParts.max.l = this.wrapperParts.close.l - this.wrapperParts.max.w - 5;
    this.wrapperParts.max.t = this.wrapperParts.close.t;
    this.wrapperParts.min.l = this.wrapperParts.max.l;
    this.wrapperParts.min.t = this.wrapperParts.max.t;
  }

  //create the decoration wrapper DOM objects
  //append the styled info window to the container
  for (var i in this.wrapperParts) {
    if (i == 'close' ) {
      //first append the content so the close button is layered above it
      this.wrapperDiv_.insertBefore(this.contentDiv_, this.wrapperParts[i].domElement);
    }
    var wrapperPartsDiv = null;
    if (this.wrapperParts[i].domElement == null) {
      wrapperPartsDiv = document.createElement('div');
      this.wrapperDiv_.appendChild(wrapperPartsDiv);
    } else {
      wrapperPartsDiv = this.wrapperParts[i].domElement;
    }
    wrapperPartsDiv.id = this.infoWindowId_ + '_' + i;
    wrapperPartsDiv.style.position='absolute';
    wrapperPartsDiv.style.width = this.wrapperParts[i].w + 'px';
    wrapperPartsDiv.style.height = this.wrapperParts[i].h + 'px';
    wrapperPartsDiv.style.top = this.wrapperParts[i].t + 'px';
    wrapperPartsDiv.style.left = this.wrapperParts[i].l + 'px';
    this.wrapperParts[i].domElement = wrapperPartsDiv;
  }

  //add event handler for the close icon
  var currentMarker = this.marker_;
  var thisMap = this.map_;
  GEvent.addDomListener(this.wrapperParts.close.domElement, 'click', 
    function() {
      thisMap.closeExtInfoWindow();
    }
  );
  
  
  
  //position the container on the map, over the marker
  var pixelLocation = this.map_.fromLatLngToDivPixel(this.marker_.getPoint());
  this.container_.style.position = 'absolute';
  var markerIcon = this.marker_.getIcon();
  this.container_.style.left = (pixelLocation.x 
    - (this.contentWidth / 2) 
    - markerIcon.iconAnchor.x 
    + markerIcon.infoWindowAnchor.x
  ) + 'px';

  this.container_.style.top = (pixelLocation.y
    - this.wrapperParts.bl.h
    - contentHeight
    - this.wrapperParts.tl.h
    - this.wrapperParts.beak.h
    - markerIcon.iconAnchor.y
    + markerIcon.infoWindowAnchor.y
    + this.borderSize_
  ) + 'px';

  this.container_.style.display = 'block';

  if(this.map_.getExtInfoWindow() != null) {
    this.repositionMap_();
  }
};

ExtInfoWindow.prototype.toggleMaxMin_ = function(){
  if( this.wrapperParts.max.domElement != null && this.wrapperParts.min.domElement != null ){
    if (this.isMaximized_) {
      this.wrapperParts.max.domElement.style.display = 'none';
      this.wrapperParts.min.domElement.style.display = 'block';
    }else{
      this.wrapperParts.max.domElement.style.display = 'block';
      this.wrapperParts.min.domElement.style.display = 'none';
    }
  }
}

/**
 * Determine the dimensions of the contents to recalculate and reposition the 
 * wrapping decorator elements accordingly.
 */
ExtInfoWindow.prototype.resize = function(){
  
  //Create temporary DOM node for new contents to get new height
  //This is done because if you manipulate this.contentDiv_ directly it causes visual errors in IE6
  var tempElement = this.contentDiv_.cloneNode(true);
  tempElement.id = this.infoWindowId_ + '_tempContents';
  tempElement.style.visibility = 'hidden';    
  tempElement.style.height = 'auto';
  document.body.appendChild(tempElement);
  tempElement = document.getElementById(this.infoWindowId_ + '_tempContents');
  var contentHeight = tempElement.offsetHeight;
  document.body.removeChild(tempElement);

  //Set the new height to eliminate visual defects that can be caused by font resizing in browser
  this.contentDiv_.style.height = contentHeight + 'px';

  var contentWidth = this.container_.offsetWidth;
  var pixelLocation = this.map_.fromLatLngToDivPixel(this.marker_.getPoint());

  var oldWindowHeight = this.wrapperParts.t.domElement.offsetHeight + this.wrapperParts.l.domElement.offsetHeight + this.wrapperParts.b.domElement.offsetHeight;    
  var oldWindowPosTop = this.wrapperParts.t.domElement.offsetTop;

  //resize info window to look correct for new height
  this.wrapperParts.l.domElement.style.height = contentHeight + 'px';
  this.wrapperParts.r.domElement.style.height = contentHeight + 'px';
  var newPosTop = this.wrapperParts.b.domElement.offsetTop - contentHeight;
  this.wrapperParts.l.domElement.style.top = newPosTop + 'px';
  this.wrapperParts.r.domElement.style.top = newPosTop + 'px';
  this.contentDiv_.style.top = newPosTop + 'px';
  windowTHeight = parseInt(this.wrapperParts.t.domElement.style.height, 10);
  newPosTop -= windowTHeight;
  this.wrapperParts.close.domElement.style.top = newPosTop + this.borderSize_ + 'px';
  this.wrapperParts.tl.domElement.style.top = newPosTop + 'px';
  this.wrapperParts.t.domElement.style.top = newPosTop + 'px';
  this.wrapperParts.tr.domElement.style.top = newPosTop + 'px';

  this.repositionMap_();
};

/**
 * Check to see if the displayed extInfoWindow is positioned off the viewable 
 * map region and by how much.  Use that information to pan the map so that 
 * the extInfoWindow is completely displayed.
 * @private
 */
ExtInfoWindow.prototype.repositionMap_ = function(){
  //pan if necessary so it shows on the screen
  var mapNE = this.map_.fromLatLngToDivPixel(
    this.map_.getBounds().getNorthEast()
  );
  var mapSW = this.map_.fromLatLngToDivPixel(
    this.map_.getBounds().getSouthWest()
  );
  var markerPosition = this.map_.fromLatLngToDivPixel(
    this.marker_.getPoint()
  );

  var panX = 0;
  var panY = 0;
  var paddingX = this.paddingX_;
  var paddingY = this.paddingY_;
  var infoWindowAnchor = this.marker_.getIcon().infoWindowAnchor;
  var iconAnchor = this.marker_.getIcon().iconAnchor;

  //test top of screen    
  var windowT = this.wrapperParts.t.domElement;
  var windowL = this.wrapperParts.l.domElement;
  var windowB = this.wrapperParts.b.domElement;
  var windowR = this.wrapperParts.r.domElement;
  var windowBeak = this.wrapperParts.beak.domElement;

  var offsetTop = markerPosition.y - ( -infoWindowAnchor.y + iconAnchor.y +  this.getDimensions_(windowBeak).height + this.getDimensions_(windowB).height + this.getDimensions_(windowL).height + this.getDimensions_(windowT).height + this.paddingY_);
  if (offsetTop < mapNE.y) {
    panY = mapNE.y - offsetTop;
  } else {
    //test bottom of screen
    var offsetBottom = markerPosition.y + this.paddingY_;
    if (offsetBottom >= mapSW.y) {
      panY = -(offsetBottom - mapSW.y);
    }
  }

  //test right of screen
  var offsetRight = Math.round(markerPosition.x + this.getDimensions_(this.container_).width/2 + this.getDimensions_(windowR).width + this.paddingX_ + infoWindowAnchor.x - iconAnchor.x);
  if (offsetRight > mapNE.x) {
    panX = -( offsetRight - mapNE.x);
  } else {
    //test left of screen
    var offsetLeft = - (Math.round( (this.getDimensions_(this.container_).width/2 - this.marker_.getIcon().iconSize.width/2) + this.getDimensions_(windowL).width + this.borderSize_ + this.paddingX_) - markerPosition.x - infoWindowAnchor.x + iconAnchor.x);
    if( offsetLeft < mapSW.x) {
      panX = mapSW.x - offsetLeft;
    }
  }

  if (panX != 0 || panY != 0 && this.map_.getExtInfoWindow() != null ) {
    this.map_.panBy(new GSize(panX,panY));
  }
};

/**
 * Private function that handles performing an ajax request to the server.  The response
 * information is assumed to be HTML and is placed inside this extInfoWindow's contents region.
 * Last, check to see if the height has changed, and resize the extInfoWindow accordingly.
 * @private
 * @param {String} url The Url of where to make the ajax request on the server
 */
ExtInfoWindow.prototype.ajaxRequest_ = function(url){
  var thisMap = this.map_;
  var thisCallback = this.callback_;
  GDownloadUrl(url, function(response, status){
    if (thisMap.getExtInfoWindow() !== null) {
      var infoWindow = document.getElementById(thisMap.getExtInfoWindow().infoWindowId_ + '_contents');
      if (response == null || status == -1 ) {
        infoWindow.innerHTML = '<span class="error">ERROR: The Ajax request failed to get HTML content from "' + url + '"</span>';
      } else {
        infoWindow.innerHTML = response;
      }
      if (thisCallback != null ) {
        thisCallback();
      }
      thisMap.getExtInfoWindow().resize();
    }
    GEvent.trigger(thisMap, 'extinfowindowupdate');
  });
};

/**
 * Private function derived from Prototype.js to get a given element's
 * height and width
 * @private
 * @param {Object} element The DOM element that will have height and 
 *                    width will be calculated for it.
 * @return {Object} Object with keys: width, height
 */
ExtInfoWindow.prototype.getDimensions_ = function(element) {
  var display = this.getStyle_(element, 'display');
  if (display != 'none' && display != null) { // Safari bug
    return {width: element.offsetWidth, height: element.offsetHeight};
  }

  // All *Width and *Height properties give 0 on elements with display none,
  // so enable the element temporarily
  var els = element.style;
  var originalVisibility = els.visibility;
  var originalPosition = els.position;
  var originalDisplay = els.display;
  els.visibility = 'hidden';
  els.position = 'absolute';
  els.display = 'block';
  var originalWidth = element.clientWidth;
  var originalHeight = element.clientHeight;
  els.display = originalDisplay;
  els.position = originalPosition;
  els.visibility = originalVisibility;
  return {width: originalWidth, height: originalHeight};
};

/**
 * Private function derived from Prototype.js to get a given element's
 * value that is associated with the passed style
 * @private
 * @param {Object} element The DOM element that will be checked.
 * @param {String} style The style name that will be have it's value returned.
 * @return {Object}
 */
ExtInfoWindow.prototype.getStyle_ = function(element, style) {
  var found = false;
  style = this.camelize_(style);
  if (element.id == this.infoWindowId_ && style == 'width' && element.style.display == 'none') {
      element.style.visibility = 'hidden';
      element.style.display = '';
  }
  var value = element.style[style];
  if (!value) {
    if (document.defaultView && document.defaultView.getComputedStyle) {
      var css = document.defaultView.getComputedStyle(element, null);
      value = css ? css[style] : null;
    } else if (element.currentStyle) {
      value = element.currentStyle[style];
    }
  }
  if((value == 'auto') && (style == 'width' || style == 'height') && (this.getStyle_(element, 'display') != 'none')) {
    if( style == 'width' ) {
      value = element.offsetWidth;
    }else {
      value = element.offsetHeight;
    }
  }
  if (element.id == this.infoWindowId_ && style == 'width' && element.style.display != 'none') {
      element.style.display = 'none';
      element.style.visibility = 'visible';    
  }
  return (value == 'auto') ? null : value;
};

/**
 * Private function pulled from Prototype.js that will change a hyphened
 * style name into camel case.
 * @private
 * @param {String} element The string that will be parsed and made into camel case
 * @return {String}
 */
ExtInfoWindow.prototype.camelize_ = function(element) {
  var parts = element.split('-'), len = parts.length;
  if (len == 1) return parts[0];
  var camelized = element.charAt(0) == '-'
    ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
    : parts[0];

  for (var i = 1; i < len; i++) {
    camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
  }
  return camelized;
};

GMap.prototype.ExtInfoWindowInstance_ = null;
GMap.prototype.ClickListener_ = null;
GMap.prototype.InfoWindowListener_ = null;

/**
 * Creates a new instance of ExtInfoWindow for the GMarker.  Register the newly created 
 * instance with the map, ensuring only one window is open at a time. If this is the first
 * ExtInfoWindow ever opened, add event listeners to the map to close the ExtInfoWindow on 
 * zoom and click, to mimic the default GInfoWindow behavior.
 *
 * @param {GMap} map The GMap2 object where the ExtInfoWindow will open
 * @param {String} cssId The id we will use to reference the info window
 * @param {String} html The HTML contents
 * @param {Object} opt_opts A contianer for optional arguments:
 *    {String} ajaxUrl The Url to hit on the server to request some contents 
 *    {Number} paddingX The padding size in pixels that the info window will leave on 
 *                    the left and right sides of the map when panning is involved.
 *    {Number} paddingX The padding size in pixels that the info window will leave on 
 *                    the top and bottom sides of the map when panning is involved.
 *    {Number} beakOffset The repositioning offset for when aligning the beak element. 
 *                    This is used to make sure the beak lines up correcting if the 
 *                    info window styling containers a border.
 */
GMarker.prototype.openExtInfoWindow = function(map, cssId, html, opt_opts) {
  if (map == null) {
    throw 'Error in GMarker.openExtInfoWindow: map cannot be null';
    return false;
  }
  if (cssId == null || cssId == '') {
    throw 'Error in GMarker.openExtInfoWindow: must specify a cssId';
    return false;
  }
  
  map.closeInfoWindow();
  if (map.getExtInfoWindow() != null) {
    map.closeExtInfoWindow();
  }
  if (map.getExtInfoWindow() == null) {
    map.setExtInfoWindow_( new ExtInfoWindow(
      this,
      cssId,
      html,
      opt_opts
    ) );
    if (map.ClickListener_ == null) {
      //listen for map click, close ExtInfoWindow if open
      map.ClickListener_ = GEvent.addListener(map, 'click',
      function(event) {
          if( !event && map.getExtInfoWindow() != null ){
            map.closeExtInfoWindow();
          }
        }
      );
    }
    if (map.InfoWindowListener_ == null) {
      //listen for default info window open, close ExtInfoWindow if open
      map.InfoWindowListener_ = GEvent.addListener(map, 'infowindowopen', 
      function(event) {
          if (map.getExtInfoWindow() != null) {
            map.closeExtInfoWindow();
          }
        }
      );
    }
    map.addOverlay(map.getExtInfoWindow());
  }
};

/**
 * Remove the ExtInfoWindow instance
 * @param {GMap2} map The map where the GMarker and ExtInfoWindow exist
 */
GMarker.prototype.closeExtInfoWindow = function(map) {
  if( map.getExtInfoWindow() != null ){
    map.closeExtInfoWindow();
  }
};

/**
 * Get the ExtInfoWindow instance from the map
 */
GMap2.prototype.getExtInfoWindow = function(){
  return this.ExtInfoWindowInstance_;
};
/**
 * Set the ExtInfoWindow instance for the map
 * @private
 */
GMap2.prototype.setExtInfoWindow_ = function( extInfoWindow ){
  this.ExtInfoWindowInstance_ = extInfoWindow;
}
/**
 * Remove the ExtInfoWindow from the map
 */
GMap2.prototype.closeExtInfoWindow = function(){
  if( this.getExtInfoWindow() != null ){
    this.ExtInfoWindowInstance_.remove();
  }
};
/**********************************************************************
Deze functie kijkt of de enter knop is ingedrukt in het trefwoord veld.
**********************************************************************/

function handleKeyPress(e, sEle){
    
    if ( typeof(e.keyCode) != 'undefined' ) {
        var key=e.keyCode;
    } else {
        e.which;
    }
    if (key==13){
        activate('tabSearch');
        oGeoStart.html.showSearch();
        oGeoStart.html.showSearch($(sEle).value);
    }
};


/**
*   @desc Make pages function. Dynamicly generated pages and callbackfunction
*   @note Currently hard coded limit to 20 pages
*
*   @param int iCurrent Current page number
*   @param int iTotal Total count of pages
*   @param string sCallPageFucntion string function to initiate change of page. Add __PAGENR__ to place the vairable page number
*   @param string sTop Element name of pagecounter container
*   @param string sBottom Element name of pagecounter container 2
**/
function makePages(iCurrent, iTotal, sCallPageFunction, sTop, sBottom){
    var sPages = '';
    var sClass = '';
    if ( iTotal > 20 )  { iTotal = 20; }
    
    if ( iTotal > 1 ) {
    
        iPrevious = iCurrent - 1;
        if ( iPrevious == 0 ) { iPrevious = 1; }
        sPages += '<a href="#" onclick="' + sCallPageFunction.replace("__PAGENR__", ( iCurrent - 1)) + '"><</a>';
        
        for ( var i=1; i<=iTotal; i++ ) {
            if ( i == iCurrent ) { sClass = 'class="current"' } else { sClass = ''; }
            sPages += '<a href="#" ' + sClass + ' onclick="' + sCallPageFunction.replace("__PAGENR__", ( i )) + ';return false;">' + i + '</a>';
        }
        
        iNext = iCurrent + 1;
        if ( iNext > iTotal ) { iNext = iTotal; }
        sPages += '<a href="#" onclick="' + sCallPageFunction.replace("__PAGENR__", iNext ) + ';return false;">></a>';
    }
        
    document.getElementById(sTop).innerHTML = sPages;
    document.getElementById(sBottom).innerHTML = sPages;
};




/**********************************************************************
Stop teh click event from passing throught the dom object
**********************************************************************/
function stopClick(e){
    if (!e){
        var e = window.event;
    }
    e.cancelBubble = true;
    if (e.stopPropagation){
        e.stopPropagation();
    }
};



/**********************************************************************
You can use the checkForTag method to check whether specific tags exist.
**********************************************************************/
function checkForTag(tag){
    if(tag != undefined){
        return true;
    } else {
        return false;
    }
};

/**
*   Return document.getElementById() without the typing.
**/
function $(id){
    return document.getElementById(id);
};


/**********************************************************************
Statistieken teller. De stats zijn in webbeheer uit te lezen.
Je kan een pagina adres opgeven (handig voor ajax requests).
Als je geen pagina opgeeft wordt document.location.href gebruikt. 
**********************************************************************/
function pageHit(pagina){
    
    if(pagina != null){
        p = escape(pagina);
    } else {
        p = escape(document.location.href);
    }
        
    rfr = escape(document.referrer);
    if (rfr == "undefined"){ rfr = "";}
    sx = screen.width;
    sy = screen.height;
    sc = (navigator.appName.indexOf("Microsoft") > -1) ? screen.colorDepth : screen.pixelDepth;
    src = 'stats.php?p=' + p + '&rfr=' + rfr + '&sx=' + sx + '&sy=' + sy + '&sc=' + sc;
    //src = '<img style="position:absolute;left:-10px;top:-10px;" src="' + src + '" width="1" height="1" border="0" alt="" />';
    src = '<img src="' + src + '" width="1" height="1" border="0" alt="" />';
    
    document.getElementById('counter').innerHTML = src;
};

function cleanInput(sValue, sInputId){
    el = $(sInputId);
    
    if ( el.value == sValue ) {
        el.value='';
    }
};

        
        

/**********************************************************************
Twee functies om van een thumb plaatje een large versie in een popup te tonen
**********************************************************************/
imagename = '';
var popup = null;

function enlarge(fullimg){
    if(popup && !popup.closed){
        popup.close();
    }
    
    popup = window.open("about:blank","","width=155,height=116,status=no,toolbar=no,scrollbars=no,menubar=no,location=no,resizable=no");
    imagename = fullimg;
    
    setTimeout('updatePopup()',500)
};

function updatePopup(){
    doc = popup.document;
    doc.open('text/html');
    doc.write('<html><head><title>Uitvergroting</title><meta http-equiv="imagetoolbar" content="no" /><base href="' + sBaseUrl + '" /><link type="text/css" rel="stylesheet" href="css/popup.css" /></head><body>');
    doc.write('<a href="javascript:;" onClick="window.close()"><img name="FullImage" src="' + imagename + '" onLoad="window.resizeTo(FullImage.offsetWidth+25, FullImage.offsetHeight+80);"></a>');
    doc.write('</body></html>');
    doc.close();
};


/**********************************************************************
Drie functie om cookies te gebruiken binnen javascript
**********************************************************************/
function createCookie(name,value,days) {
    if (days) {
        var date = new Date();
        date.setTime(date.getTime()+(days*24*60*60*1000));
        var expires = "; expires="+date.toGMTString();
    }
    else var expires = "";
    document.cookie = name+"="+value+expires+"; path=/";
};

function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
            if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
};

function eraseCookie(name) {
    createCookie(name,"",-1);
};

function cookieHandler(){
    if ( document.getElementById('setcookie').checked ) {        
        createCookie('hideHelp', true, 31);        
    } else {        
        eraseCookie('hideHelp');        
    }
};

function gotoAddress(){
    
    oGeoStart.oMap.closeExtInfoWindow();
    var sZoekVar = document.getElementById("zoek_geocode").value;
    if(sZoekVar !="postcode of plaats" && sZoekVar !="") {
        oGeoStart.oSearch.oCoder.getLatLng(sZoekVar+", Nederland", function(oPoint){
            if(oPoint!=null) {
                oGeoStart.oMap.setCenter(oPoint);
                oGeoStart.oMap.setZoom(12);
            } else {
                alert("Er is geen locatie gevonden met deze gegevens...");
            }
        });
    }
}if ( typeof(document.attachEvent) != 'function' ) {

    document.events = [];
    document.attachEvent = function(type, reference) {
        var evt = this.events;
        if(!evt[type]){ evt[type] = []; }
        evt[type][evt[type].length] = reference;

        document[type] = function(e) { 
            document.executeEvents(type, e);        
        };
    };

    document.executeEvents = function(type, e) {
        for(var i in this.events[type]) {
            this.events[type][i](e);
        }    
    };
    window.onunload = function() { document.executeEvents('onunload'); };
    window.onload = function() { document.executeEvents('onload'); };
    window.onresize = function() { document.executeEvents('onresize'); };

};

/**
*   Swap color and background color
**/
function swapColors(oEle){
    return;
    var sFg     = oEle.style.color;
    var sBg     = oEle.style.backgroundColor;
    
    if ( sColor.length == 0 ) {
        sFg = "white";
    }
    if ( sBg.length == 0 ) {
        sBg = "#"+sColor;
    }
        
    oEle.style.color = sBg;
    oEle.style.backgroundColor  = sFg;
};


/**
*   Function for fluid design. 
**/               
function resizer() {
    /*
      var iHeaderHeight = parseInt(oSettings._HeaderHeight);

      var size = checkSize();      
      myWidth  = size[0];
      myHeight = size[1];
      
      if ( ( myWidth < 500 || myHeight < 500 ) && oSettings._bMenu !== false ) { 
        
        var size = checkSize();
        myWidth = size[0];
        myHeight= size[1];        
      }
      
      
      if ( myWidth < 914 ) {
        document.getElementById('tabMap').style.width = ( 20 ) + 'px';
      } else {
        document.getElementById('tabMap').style.width = ( myWidth  - 904 ) + 'px';
      }
            
      document.getElementById('container').style.marginTop = (iHeaderHeight)+'px';
      document.getElementById('GeoMenu').style.top = (iHeaderHeight+22)+'px';
      
      
      //document.getElementById('GeoMap').style.height =  ( myHeight  - 25 - iHeaderHeight ) + 'px';
      
      if ( oSettings._bMenu !== false ) {
          document.getElementById('tabMenu').style.top = (iHeaderHeight)+'px';
          document.getElementById('GeoMenu').style.height = ( myHeight  - 25 - iHeaderHeight ) + 'px';
          document.getElementById('GeoMenu_items').style.height = ( myHeight  - 164 - iHeaderHeight ) + 'px';
          document.getElementById('GeoDirections').style.height = ( myHeight  - 93 - iHeaderHeight ) + 'px';
          document.getElementById('GeoMap').style.width =   ( myWidth   - 307 ) + 'px';
          
          document.getElementById('GeoMap').style.height =  ( myHeight  - 25 - iHeaderHeight ) + 'px';
          
          document.getElementById('closeTab').style.height = ( myHeight  - 25 - iHeaderHeight ) + 'px';
          document.getElementById('closeTab').style.width = ( myWidth   - 307 - 595 ) + 'px';
          
      } else {
            document.getElementById('container').style.right = 0;
            document.getElementById('tabMenu').style.display = 'none';
            document.getElementById('GeoMenu').style.display = 'none';
            document.getElementById('GeoMap').style.width =   ( myWidth - 3 ) + 'px';      
            
            document.getElementById('GeoMap').style.height =  ( myHeight  - 25 - iHeaderHeight ) + 'px';
            
            document.getElementById('tabMap').style.width = ( document.getElementById('tabMap').offsetWidth + 304 ) + "px";
            
      }
      //document.getElementById('GeoMap').style.height =  ( myHeight  - 25 - iHeaderHeight ) + 'px';
      document.getElementById('tab').style.height =     ( myHeight  - 25 - iHeaderHeight ) + 'px';
      
      
      

      positionHelp();

      /** Try/catch because this function is called before the creation of the map object **/
      /*
      try {
        oGeoStart.oMap.checkResize();
      } catch(e) { }
      
      
      if ( document.getElementById('Loading_mapMaker') != null ) {
        document.getElementById('Loading_mapMaker').style.display = 'none';
      }
      */
      
};

/** Call the function on resize **/
//onresize = resizer;

var counter = 0;
function positionHelp(myHeight){
    var eHelp = document.getElementById('help_draggable');
    

    counter++;
    iHeaderHeight = parseInt(oSettings._HeaderHeight);
    iHeight = checkSize()[1];
    if ( eHelp ) {
        var aPosition = findPos($('help_draggable'));

        //var iTop = ( 0 - iHeaderHeight + ( ( iHeight - 579 - aPosition[1] ) / 2 ) );

        var currentTop = parseInt(eHelp.style.top.replace('px', ''));
        
        if ( iHeight > 600 ) {
            eHelp.style.top = ( ( ( iHeight - 579 ) / 2 ) - findPos(document.getElementById("help_container"))[1] ) + "px";            
        } else {
            eHelp.style.top = ( 0 - findPos(document.getElementById("help_container"))[1] ) + "px";
        }
    } else {
        setTimeout('positionHelp(' + myHeight + ')', 100);
    }
};





/**
*   Show / Hide the overlay tab for extra info/search etc.
**/
function swap(div, bDisplay){

    if ( bDisplay ) {
        $('help').style.display = 'none';
        $('tab').scrollTop = 0;
        $('closeTab').style.display = "block";
    } else {
        activate('tabMap');
        $('closeTab').style.display = "none";
        oGeoStart.oMap.getContainer().className = 'active';
    }
    
    $(div).style.display = bDisplay ? 'block' : 'none';
    
    oGeoStart._bEnableHover = !bDisplay;    
    
    
};

          
/**
*   Change classname for sTab.
*   Used to color the tab.
**/
function activate(sTab){
    var aTabs = $('tabs').getElementsByTagName('div');
    for ( var sCurTab in aTabs ) {
        if ( sTab == aTabs[sCurTab].id ) {
            aTabs[sCurTab].className = 'active';
        } else if ( aTabs[sCurTab].className == 'active' ) {
            aTabs[sCurTab].className = '';
        }
    }
};

/**
*   Handle the menu tabs.
**/
function m_activate(sTab){
    if(sTab == 'route'){
        $('button').className='';
        $('route').className='active';
        $('GeoMenu_items').style.display = 'none';
        $('GeoDirections').style.display = 'block';
    } else {
        $('button').className='active';
        $('route').className='';
        $('GeoMenu_items').style.display = 'block';
        $('GeoDirections').style.display = 'none';
    }
};

/**
*   In the main info tab, there are 3 divs. Use this to activate the correct div.
**/
function setTabContent(sBlock){
    var aBlocks = new Object();
    aBlocks['search'] = document.getElementById('tab_contents_search');
    aBlocks['info'] = document.getElementById('tab_contents_info');
    aBlocks['list'] = document.getElementById('tab_contents_list');
    aBlocks['route'] = document.getElementById('tab_contents_route');
    
    if ( sBlock != 'search' ) {
        var eCurTab = $('sCurTab');
        eCurTab.value = sBlock;
    }
    for ( var sId in aBlocks ) {
        aBlocks[sId].style.display = 'none';
    }    
    aBlocks[sBlock].style.display = 'block';
    
};

/**
*   Toggle help display on the map. 
*   eHC: Help Control element.
**/
function toggleHelp(){
    var eH = $('help');
    var eHC = $('Control_grey_help');
    if ( eH.style.display != 'block' ){
        eH.style.display = 'block';  
        eHC.style.fontWeight = 'bold';      
        pageHit('Google_Maps_Help');
    } else {
        eH.style.display = 'none';
        eHC.style.fontWeight = 'normal';
    }    
};

    /**
    *   Crossbrowser find position voor DOM object
    **/
    function findPos(obj) {
        var curleft = curtop = 0;
        if (obj.offsetParent) {
            curleft = obj.offsetLeft;
            curtop = obj.offsetTop;
            while (obj = obj.offsetParent) {
                curleft += obj.offsetLeft;
                curtop += obj.offsetTop;
            }
        }
        return [curleft,curtop];
    };




function checkSize() {
      var myWidth = 0, myHeight = 0;
      if( typeof( window.innerWidth ) == 'number' ) {
        //Non-IE
        myWidth = window.innerWidth;
        myHeight = window.innerHeight;
        
      } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
        //IE 6+ in 'standards compliant mode'
        myWidth = document.documentElement.clientWidth;
        myHeight = document.documentElement.clientHeight;
      } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
        //IE 4 compatible
        myWidth = document.body.clientWidth;
        myHeight = document.body.clientHeight;
      }      
      var retVal = [myWidth, myHeight];
      //console.log(retVal);
      return retVal;
}


/** 
*   The tab title is dynamic and can contain 'Detail pagina' and 'Locatie overzicht' 
*   This function reads input#sCurTab.value to check what was loaded last.
**/
function tabTitleClick(){
    var sCurTab = $('sCurTab').value;
    
    setTabContent(sCurTab);
    activate('tabTitle');
    swap('tab', true);
};

function stopClick(e){
    if (!e){
        var e = window.event;
    }
    e.cancelBubble = true;
    if (e.stopPropagation){
        e.stopPropagation();
    }
};
    /**
    *   Custom map controls.
    *   Middle control ( best fit: Kaart )
    *   @param oMap Map object
    *   @param sText Text on the button
    **/    
    var Control_grey_center = function(oMap, sText) { this.oMap = oMap; this.sText = sText; };
        Control_grey_center.prototype = new GControl(true, false);
        Control_grey_center.prototype.initialize = function () {
                var oContainer = document.createElement("div");
                oContainer.innerHTML           = "<span style='padding-top:5px;display:block;height:25px;'>" + this.sText + "</span>";
                oContainer.id                  = "Control_grey_kaart";
                oContainer.style.width         = "56px";
                oContainer.style.verticalAlign = "middle";
                oContainer.style.fontSize      = "12px";
                oContainer.style.height        = "25px";
                oContainer.style.textAlign     = "center";
                oContainer.style.cursor        = "pointer";
                oContainer.style.fontWeight    = "bold";
                oContainer.style.overflow      = "hidden";
                oContainer.style.backgroundImage = "url('"+ sBaseUrl + "GeoStart/images/controls/grey/center_btn.gif')";

                /** Make bold when clicked **/
                GEvent.addDomListener(oContainer, 'click', function(){ 
                    oGeoStart.oMap.enableContinuousZoom();
                    oGeoStart.oMap.setMapType(G_NORMAL_MAP);
                    oContainer.style.fontWeight = 'bold'; 
                    document.getElementById('Control_grey_satelliet').style.fontWeight = 'normal';
                    document.getElementById('Control_grey_history').style.fontWeight = 'normal';
                });

                
                
                this.oMap.getContainer().appendChild(oContainer);
                
                return oContainer;
            }
            Control_grey_center.prototype.getDefaultPosition = function () {
                return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(100,10));
            };

            
    var Control_grey_center_left = function(oMap, sText) { this.oMap = oMap; this.sText = sText; };
        Control_grey_center_left.prototype = new GControl(true, false);
        Control_grey_center_left.prototype.initialize = function () {
                var oContainer = document.createElement("div");
                oContainer.innerHTML           = "<span style='padding-top:5px;display:block;height:25px;'>" + this.sText + "</span>";
                oContainer.id                  = "Control_grey_history";
                oContainer.style.width         = "70px";
                oContainer.style.verticalAlign = "middle";
                oContainer.style.fontSize      = "12px";
                oContainer.style.height        = "25px";
                oContainer.style.textAlign     = "center";
                oContainer.style.overflow      = "hidden";
                oContainer.style.cursor        = "pointer";
                oContainer.style.fontWeight    = "normal";
                oContainer.style.borderRight   = "1px solid #666";
                oContainer.style.backgroundImage = "url('"+ sBaseUrl + "GeoStart/images/controls/grey/center_btn.gif')";

                /** Make bold when clicked **/
                GEvent.addDomListener(oContainer, 'click', function(){ 
                    //oGeoStart.oMap.disableContinuousZoom();
                    oGeoStart.oMap.setMapType(G_PHYSICAL_MAP);
                    //oGeoStart.oMap.setCenter(new GLatLng('52.076710232834756', '4.313077926635742'), 14);
                    //oMenu.toggleAll(false);
                    
                    oContainer.style.fontWeight = 'bold'; 
                    document.getElementById('Control_grey_satelliet').style.fontWeight = 'normal';
                    document.getElementById('Control_grey_kaart').style.fontWeight = 'normal';
                });

                
                
                this.oMap.getContainer().appendChild(oContainer);
                
                return oContainer;
            }
            Control_grey_center_left.prototype.getDefaultPosition = function () {
                return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(156,10));
            };

            
    /**
    *   Custom map controls.
    *   Right control ( best fit Satelliet )
    *   @param oMap Map object
    *   @param sText Text on the button
    **/    
    var Control_grey_right = function(oMap, sText) { this.oMap = oMap; this.sText = sText; };
        Control_grey_right.prototype = new GControl(true, false);
        Control_grey_right.prototype.initialize = function () {
                var oContainer = document.createElement("div");
                oContainer.innerHTML         = "<span style='padding-top:5px;display:block;height:25px;'>" + this.sText + "</span>";
                oContainer.id                 = "Control_grey_satelliet";
                oContainer.style.width       = "70px";
                oContainer.style.verticalAlign = "middle";
                oContainer.style.fontSize    = "12px";
                oContainer.style.height        = "25px";
                oContainer.style.textAlign     = "center";
                oContainer.style.overflow      = "hidden";
                oContainer.style.cursor        = "pointer";
                oContainer.style.backgroundImage = "url('"+ sBaseUrl + "GeoStart/images/controls/grey/right_btn.gif')";

                /** Make bold when clicked **/
                GEvent.addDomListener(oContainer, 'click', function(){ 
                    oGeoStart.oMap.enableContinuousZoom();
                    oGeoStart.oMap.setMapType(G_SATELLITE_MAP);
                    oContainer.style.fontWeight = 'bold';
                    document.getElementById('Control_grey_kaart').style.fontWeight = 'normal'; 
                    document.getElementById('Control_grey_history').style.fontWeight = 'normal'; 
                });            
            
                this.oMap.getContainer().appendChild(oContainer);
                                
                return oContainer;
            }
            Control_grey_right.prototype.getDefaultPosition = function () {
                return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(30,10));
            };

            
    /**
    *   Custom map controls.
    *   Left control ( Created for: "Help" )
    *   @param oMap Map object
    *   @param sText Text on the button
    **/    
    var Control_grey_left = function(oMap, sText) { this.oMap = oMap; this.sText = sText; };
        Control_grey_left.prototype = new GControl(true, false);
        Control_grey_left.prototype.initialize = function () {
                var oContainer = document.createElement("div");
                oContainer.innerHTML         = "<span style='padding-top:5px;display:block;height:25px;'>" + this.sText + "</span>";
                oContainer.id                 = "Control_grey_help";
                oContainer.style.width       = "54px";
                oContainer.style.overflow      = "hidden";
                oContainer.style.verticalAlign = "middle";
                oContainer.style.fontSize    = "12px";
                oContainer.style.height        = "25px";
                oContainer.style.textAlign     = "center";
                oContainer.style.cursor        = "pointer";
                oContainer.style.backgroundImage = "url('"+ sBaseUrl + "GeoStart/images/controls/grey/left_btn.gif')";
                
                /** Onclick function **/
                GEvent.addDomListener(oContainer, 'click', function(){ oHelp.show();});            
                
                this.oMap.getContainer().appendChild(oContainer);
                                
                return oContainer;
            }
            Control_grey_left.prototype.getDefaultPosition = function () {
                return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(226,10));
            };
            
            
    /**
    *   Custom map controls.
    *   Zoom and Pan controls
    **/    
    var Control_grey_panzoom = function(oMap, sText) { this.oMap = oMap;};
        Control_grey_panzoom.prototype = new GControl(true, false);
        Control_grey_panzoom.prototype.initialize = function () {
                var oContainer = document.createElement("div");
                oContainer.id                   = "Control_grey_pan";
                oContainer.style.width          = '56px';
                oContainer.style.height         = '100px';
                oContainer.style.backgroundImage= "url('"+ sBaseUrl + "GeoStart/images/controls/greycenter/zoom_control.gif')";
                
                var oUp = document.createElement("div");
                var oRight = document.createElement("div");
                var oDown = document.createElement("div");
                var oLeft = document.createElement("div");
                var oZoomin = document.createElement("div");
                var oZoomout = document.createElement("div");
                var oCenter = document.createElement("div");

                oUp.style.cssText = 'display:block;width:16px;height:16px;cursor:pointer;margin-left:19px;';
                oLeft.style.cssText = 'display:block;width:16px;height:16px;cursor:pointer;margin-top:3px;float:left;';
                oCenter.style.cssText = 'display:block;width:16px;height:16px;cursor:pointer;float:left;margin:3px 0 0 3px;';
                oRight.style.cssText = 'display:block;width:16px;height:16px;cursor:pointer;float:left;margin:3px 0 0 3px';
                oDown.style.cssText = 'display:block;width:16px;height:18px;cursor:pointer;clear: both;margin: 3px 0 0 19px;';
                oZoomin.style.cssText = 'display:block;width:16px;height:16px;cursor:pointer;margin: 10px 0 0 19px;';
                oZoomout.style.cssText = 'display:block;width:16px;height:16px;cursor:pointer;margin: 3px 0 0 19px;'; 
                

                
                GEvent.addDomListener(oUp, 'click', function(){ oGeoStart.oMap.panDirection(0,1)});            
                GEvent.addDomListener(oLeft, 'click', function(){ oGeoStart.oMap.panDirection(1,0);});            
                GEvent.addDomListener(oRight, 'click', function(){ oGeoStart.oMap.panDirection(-1,0);});            
                GEvent.addDomListener(oDown, 'click', function(){ oGeoStart.oMap.panDirection(0,-1);});            
                GEvent.addDomListener(oZoomin, 'click', function(){ oGeoStart.oMap.zoomIn();});            
                GEvent.addDomListener(oZoomout, 'click', function(){ oGeoStart.oMap.zoomOut();});            
                GEvent.addDomListener(oCenter, 'click', function(){ 
                    oGeoStart.oMap.setCenter( new GLatLng(parseFloat(oSettings.map_default_center_lat), parseFloat(oSettings.map_default_center_lng)), parseInt(oSettings.map_default_zoom));
                });            
                
                oContainer.appendChild(oUp);
                oContainer.appendChild(oLeft);
                oContainer.appendChild(oCenter);
                oContainer.appendChild(oRight);
                oContainer.appendChild(oDown);
                oContainer.appendChild(oZoomin);
                oContainer.appendChild(oZoomout);                
                
                this.oMap.getContainer().appendChild(oContainer);
                                
                return oContainer;
            }
            Control_grey_panzoom.prototype.getDefaultPosition = function () {
                return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(10,10));
            };
    /**
    *   Custom map controls.
    *   @param oMap Map object
    *   @param sText Text on the button
    **/    
    var Mini_control_grey_left = function(oMap) { this.oMap = oMap; };
        Mini_control_grey_left.prototype = new GControl(true, false);
        Mini_control_grey_left.prototype.initialize = function () {
                var oContainer = document.createElement("div");
                oContainer.innerHTML           = "<span style='padding-top:1px;display:block;height:16px;'>map</span>";
                oContainer.id                  = "Mini_control_grey_left";
                oContainer.style.width         = "29px";
                oContainer.style.verticalAlign = "middle";
                oContainer.style.fontSize      = "9px";
                oContainer.style.height        = "17px";
                oContainer.style.textAlign     = "center";
                oContainer.style.cursor        = "pointer";
                oContainer.style.fontWeight    = "bold";
                oContainer.style.backgroundImage = "url('"+ sBaseUrl + "GeoStart/images/controls/minigrey/mini_map_sat.gif')";

                /** Make bold when clicked **/
                GEvent.addDomListener(oContainer, 'click', function(){ 
                    oGeoStart.oMap.setMapType(G_NORMAL_MAP);
                    oContainer.style.fontWeight = 'bold'; 
                    document.getElementById('Mini_control_grey_right').style.fontWeight = 'normal';
                });

                
                
                this.oMap.getContainer().appendChild(oContainer);
                
                return oContainer;
            }
            Mini_control_grey_left.prototype.getDefaultPosition = function () {
                return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(51,10));
            };

    /**
    *   Custom map controls.
    *   Right control ( best fit Satelliet )
    *   @param oMap Map object
    *   @param sText Text on the button
    **/    
    var Mini_control_grey_right = function(oMap) { this.oMap = oMap; };
        Mini_control_grey_right.prototype = new GControl(true, false);
        Mini_control_grey_right.prototype.initialize = function () {
                var oContainer = document.createElement("div");
                oContainer.innerHTML         = "<span style='padding-top:1px;display:block;height:16px;'>sat</span>";
                oContainer.id                 = "Mini_control_grey_right";
                oContainer.style.width       = "29px";
                oContainer.style.verticalAlign = "middle";
                oContainer.style.fontSize    = "9px";
                oContainer.style.height        = "17px";
                oContainer.style.textAlign     = "center";
                oContainer.style.cursor        = "pointer";
                oContainer.style.backgroundImage = "url('"+ sBaseUrl + "GeoStart/images/controls/minigrey/mini_map_sat.gif')";

                /** Make bold when clicked **/
                GEvent.addDomListener(oContainer, 'click', function(){ 
                    oGeoStart.oMap.setMapType(G_SATELLITE_MAP); 
                    oContainer.style.fontWeight = 'bold';
                    document.getElementById('Mini_control_grey_left').style.fontWeight = 'normal'; 
                });            
            
                this.oMap.getContainer().appendChild(oContainer);
                                
                return oContainer;
            }
            Mini_control_grey_right.prototype.getDefaultPosition = function () {
                return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(20,10));
            };

            
    /**
    *   Custom map controls.
    *   Zoom and Pan controls
    **/    
    var Mini_control_grey_zoom = function(oMap) { this.oMap = oMap;};
        Mini_control_grey_zoom.prototype = new GControl(true, false);
        Mini_control_grey_zoom.prototype.initialize = function () {
                var oContainer = document.createElement("div");
                oContainer.id                   = "Control_grey_pan";
                oContainer.style.width          = '16px';
                oContainer.style.height         = '36px';
                oContainer.style.backgroundImage= "url('"+ sBaseUrl + "GeoStart/images/controls/minigrey/mini_zoom_control.gif')";
                
                var oZoomin = document.createElement("div");
                var oZoomout = document.createElement("div");

                oZoomin.style.cssText = 'display:block;width:15px;height:15px;cursor:pointer;margin: 0 ;';
                oZoomout.style.cssText = 'display:block;width:15px;height:15px;cursor:pointer;margin: 3px 0 0 0px;';

                GEvent.addDomListener(oZoomin, 'click', function(){ oGeoStart.oMap.zoomIn();});            
                GEvent.addDomListener(oZoomout, 'click', function(){ oGeoStart.oMap.zoomOut();});            
                
                oContainer.appendChild(oZoomin);
                oContainer.appendChild(oZoomout);
                
                this.oMap.getContainer().appendChild(oContainer);
                                
                return oContainer;
            }
            Mini_control_grey_zoom.prototype.getDefaultPosition = function () {
                return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(10,10));
            };

            
            
            
    /**
    *   Custom copyright for GeoStart
    **/    
    var powered_by_geostart = function(oMap) { this.oMap = oMap; };
        powered_by_geostart.prototype = new GControl(true, false);
        powered_by_geostart.prototype.initialize = function () {
                var oContainer = document.createElement("div");
                oContainer.innerHTML    = "<a target='_blank' href='http://www.geostart.nl' style='display:block;height:29px;width:90px;'><img class='png' style='border:0;' src='"+sBaseUrl+"GeoStart/images/controls/powered_by_geostart.png'></a>";
                
                oContainer.id           = "powered_by_geostart";
                oContainer.style.cssText= "width:89px;text-decoration:none;border:none;height:29px;cursor:pointer;padding-bottom:2px;_padding-bottom:0px;";

                this.oMap.getContainer().appendChild(oContainer);
                
                return oContainer;
            }
        powered_by_geostart.prototype.getDefaultPosition = function () {
                return new GControlPosition(G_ANCHOR_BOTTOM_LEFT, new GSize(67,1));
            };
    /**
    *   Custom overlay for GreenMaps
    *   @param object oMap
    *   @param int x
    *   @param int y
    **/    
    var control_settings = function(oSettings, oMap, x, y) { this.oMap = oMap; this.oSettings = oSettings; this.x = x; this.y=y };
        control_settings.prototype = new GControl(true, false);
        control_settings.prototype.initialize = function () {
                var oContainer = document.createElement("div");
                oContainer.innerHTML    = "<img id='save_settings_image' src='"+sBaseUrl+"GeoStart/images/controls/icon_save_as.gif' style='margin:0px;margin-right:3px;display:block;float:left;padding:0px;'><a id='save_settings_link' target='_blank' onclick='oGeoStart.oStateMachine.saveCurrentState();return false;' href='#' style='margin:0; padding:0; font-size: 11px; text-align:left; font-family:verdana; background:#F1F1E9;display:block;padding:4px 0 0px 30px;color:#2eb000;'>Stel&nbsp;in&nbsp;als&nbsp;startpagina</a>";
                
                oContainer.id           = "save_settings";
                oContainer.style.cssText= "padding:0; margin:0; text-align:center;border:1px solid #6B6863;width:248px;text-decoration:none;cursor:pointer;background-color:#F1F1E9;";

                this.oMap.getContainer().appendChild(oContainer);
                
                return oContainer;
            }        
        control_settings.prototype.getDefaultPosition = function () {
                return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(this.x,this.y));
            };

if (!window.XMLHttpRequest) 
{ 
    window.XMLHttpRequest = function() 
    { 
        var types = [ 
            'Microsoft.XMLHTTP', 
            'MSXML2.XMLHTTP.5.0', 
            'MSXML2.XMLHTTP.4.0', 
            'MSXML2.XMLHTTP.3.0', 
            'MSXML2.XMLHTTP' 
        ]; 

        for (var i = 0; i < types.length; i++) 
        { 
            try 
            { 
                return new ActiveXObject(types[i]); 
            } 
            catch(e) {} 
        } 

        return undefined; 
    } 
}


function cRequest(){
	
	this.sArgs	= '';
	this.sUrl	= '';
	this.sType	= 'GET';
	var xmlhttp	= new XMLHttpRequest(); 
	
	
	this.addArgument = function (name, value){
		
		this.sArgs += escape(name) + '=' + escape(value) + '&';
	};
	this.clearArguments = function(){
		this.sArgs = '';
	};
	this.getContent = function(){
				
		if (this.sType.toUpperCase() == 'POST'){
			xmlhttp.open('POST', this.sUrl, false);
			xmlhttp.setRequestHeader('Content-type',	'application/x-www-form-urlencoded');	
			xmlhttp.setRequestHeader('Content-length',	this.sArgs.length);	
			xmlhttp.setRequestHeader('Connection',		'close');	
			xmlhttp.send(this.sArgs);
		} else {					
			var seperator = '?';
			if (this.sUrl.indexOf('?') > 0){
				seperator = '&';
			}
			xmlhttp.open('GET', this.sUrl + seperator + this.sArgs, false);
			xmlhttp.send(null);			
		}
		this.clearArguments();
		return xmlhttp;
	};
	
	
	this.sendForm = function(oForm){

		this.sUrl 	= oForm.action;
		this.sType	= oForm.method;

		var aInputs  = oForm.getElementsByTagName('input');	
		var i = aInputs.length;
		while (i--){
			if (aInputs[i].type == 'checkbox' || aInputs[i].type == 'radio'){
				if (aInputs[i].checked){
					this.addArgument(aInputs[i].name, aInputs[i].value);
				}
			} else {
				this.addArgument(aInputs[i].name, aInputs[i].value);
			}
		}
		var aSelects = oForm.getElementsByTagName('select');
		for (var i = 0; i < aSelects.length; i++){
			for (var j=0; j < aSelects[i].options.length; j++){
				if (aSelects[i].options[j].selected){
					this.addArgument(aSelects[i].name, aSelects[i].options[j].value);
				}
			}
		}
		var aTextareas  = oForm.getElementsByTagName('textarea');	
		var i = aTextareas.length;
		while (i--){
			this.addArgument(aTextareas[i].name, aTextareas[i].value);
		}		
		return this.getContent();		
	};
}