﻿CategorizedMarkers = {
    ///<summary>Object that holds the different marker categories along with their markers.</summary>

    _markerCategories: [],

    _category: function(name, visibility, markers, visibleIcon, hiddenIcon) {
        ///<summary>Marker category object</summary>
        ///<param name="name"></param>
        ///<param name="visibility"></param>
        ///<param name="markers"></param>
        this.name = name;
        this.visibility = visibility;
        this.visibleIcon = visibleIcon;
        this.hiddenIcon = hiddenIcon;

        if (markers == null) this.markers = [];
        else this.markers = markers;
    },

    getCategory: function(name) {
        ///<summary>Returns the marker category specified</summary>
        ///<param name="name"></param>
        var category = null;
        for (var a = 0; a < this._markerCategories.length; a++) {
            if (this._markerCategories[a].name == name) {
                category = this._markerCategories[a];
                break;
            }
        }
        return category;
    },

    getCategoryIcon: function(name) {
        ///<summary>
        /// Returns the visible-/hidden icon representing the
        /// marker category based on the value of the visibility property.
        ///</summary>
        ///<param name="name"></param>
        var category = this.getCategory(name);
        if ((category.visibleIcon == null) || (category.hiddenIcon == null)) {
            return '';
        } else {
            if (category.visibility == 0) return category.hiddenIcon;
            else return category.visibleIcon;
        }
    },

    addCategory: function(name, visibility, markers, visibleIcon, hiddenIcon) {
        ///<summary>Adds a marker category with markers</summary>
        ///<param name="name"></param>
        ///<param name="visibility">0 | 1</param>
        ///<param name="markers"></param>
        this._markerCategories.push(new this._category(name, visibility, markers, visibleIcon, hiddenIcon));
    },

    addCategory: function(name, visibility, visibleIcon, hiddenIcon) {
        ///<summary>Adds a marker category</summary>
        ///<param name="name"></param>
        ///<param name="visibility"></param>
        this._markerCategories.push(new this._category(name, visibility, null, visibleIcon, hiddenIcon));
    },

    toggleCategoryVisibility: function(categoryName) {
        ///<summary>Toggles the category's visibility property</summary>
        ///<param name="categoryName"></param>
        var category = this.getCategory(categoryName);
        category.visibility != category.visibility;
    },

    addMarker: function(marker, categoryName) {
        ///<summary>Adds a marker to the specified category</summary>
        ///<param name="marker">GMarker object</param>
        ///<param name="categoryName"></param>
        var category = this.getCategory(categoryName);
        if (category == null) {
            alert('User error, no category with the specified name exists.');
        }
        category.markers.push(marker);
    }
};

var RTMMap = {
    ///<summary>Object holding methods used when generating the RTM-map</summary>

    _map: null,         // GMap object
    _mgr: null,         // MarkerManager object
    _geocoder: null,    // GGeocoder object
    _zLevel: 4,         // Default zoom-level
    _zLevelArea: 7,     // Zoom-level used when an area is selected
    _evtExmlParsed: null,   // Handler for the ExmlParsed event
    _exml: null,            // EGeoXml object holding the RTMs
    _pKml: null,            // EGeoXml object holding the partner markers
    _bicycleStandsKml: null, // EGeoXml object holding the bicycle stands feed
    _centrePoint: null,     // Default centre-point of the map
    _rtMessages: [],        // Array holding the RTM messages
    _currentZoomLevel: null,    // Map's current zoom-level
    _currentCenter: null,       // Map's current center
    _geoLocations: null,  // Holds the area's coordinates
    _mapRefreshTimer: null,     // Holds the map refresh thread
    AllowMapRefresh: true,      // Turns automatic map-refresh on/off
    categorizedMarkers: null,
    homeLocationListener: null,

    _wheelevent: function(e) {
        ///<summary>Prevent page scrolling if the mouse-wheel is rolled when the pointer is above the map</summary>
        ///<param name="e">Event</param>
        if (!e) e = window.event;
        if (e.preventDefault) e.preventDefault();
        e.returnValue = false;
    },

    _setMapCenter: function(point, zoomLevel) {
        ///<summary>
        /// Sets the center of the map to the specified point (lat/lng) at
        /// the specified zoom level.
        ///</summary>
        ///<param name="point">Lat/Lng</param>
        ///<param name="zoomLevel">Zoom level</param>
        this._map.setCenter(point, zoomLevel);
    },

    _addP4Marker: function() {
        ///<summary>Adds the marker for the P4 Radio Hele Norge AS HQ to the map</summary>
        var _self = this;
        var icon = new GIcon();
        icon.iconSize = new GSize(10, 10);
        icon.iconAnchor = new GPoint(6, 20);
        icon.infoWindowAnchor = new GPoint(5, 1);
        icon.image = '/images/icons/rtm/circle.png';

        var infoWindowHTML = '<table><tr><td><img src="/images/p4.gif" alt="P4"/></td>' +
                '<td><a href="http://www.p4.no" target="_new">' +
                'P4 Radio Hele Norge AS</a><br/><br/>' +
                'Send "trafikk" til 1904 for trafikktips.<br/><br/>' +
                'E-mail: <a href="mailto:p4@p4.no">p4@p4.no</a><br/>' +
                '</td></tr></table>';

        var p4HQPosition = new GLatLng(61.12068232642678, 10.462117195129395);
        var marker = new GMarker(p4HQPosition, { icon: icon, title: "P4 Radio Hele Norge" });
        this._map.addOverlay(marker);

        GEvent.addListener(marker, "click",
            function() {
                currentCenter = _self._map.getCenter();
                currentZoomLevel = _self._map.getZoom();

                _self._map.setCenter(p4HQPosition, 15);
                marker.openInfoWindowHtml(infoWindowHTML)
            }
        );

        GEvent.addListener(marker, "infowindowclose", function() {
            _self._setMapCenter(currentCenter, currentZoomLevel);
        });
    },

    _setBaseIcon: function() {
        ///<summary>
        /// Method used to set the base icon. The icon used for the overlaymarkers,
        /// if an icon-style is not found in the KML-feed.
        /// NOTE: The size-setting also affects the icons read from the KML-feed.
        ///</summary>
        var icon = new GIcon();
        icon.iconSize = new GSize(20, 20);
        icon.iconAnchor = new GPoint(6, 20);
        icon.infoWindowAnchor = new GPoint(5, 1);
        return icon;
    },

    _addMarkersToMap: function(categoryName, minZoom, maxZoom) {
        ///<summary>
        /// Method used when parsing a KML-feed and adding markers
        /// from the specified marker-category to the map.
        ///<param name="categoryName">Marker category</param>
        ///<param name="minZoom">Minimum zoom-level the added markers should appear on</param>
        ///<param name="maxZoom">Maximum zoom-level the added markers should appear on</param>
        ///</summary>
        try {
            var category = this.categorizedMarkers.getCategory(categoryName);
            if (category.markers.length > 0)
                this._mgr.addMarkers(category.markers, minZoom, maxZoom);
        } catch (e) { }
    },

    _addMarkerOverlay: function() {
        ///<summary>Method used when parsing the different KML-feeds for the RTM- partner-, airport- and camera markers</summary>
        this._mgr = new MarkerManager(this._map);
        this._exml.parse();
        this._evtExmlParsed = GEvent.addListener(this._exml, 'parsed', this._handleExmlParsed);

        var _self = this;
        GEvent.addListener(this._cKml, 'parsed', function() {
            _self._addMarkersToMap('camera', 7, 17);
            _self._apKml.parse();
        });

        GEvent.addListener(this._apKml, 'parsed', function() {
            _self._addMarkersToMap('airport', 7, 17);
            _self._bicycleStandsKml.parse();
        });

        GEvent.addListener(this._bicycleStandsKml, 'parsed', function() {
            _self._addMarkersToMap('bicyclestand', 12, 17);
            _self._pKml.parse();
        });

        GEvent.addListener(this._pKml, 'parsed', function() {
            _self._addMarkersToMap('partner', 7, 17);
            _self._mgr.refresh();
            Effect.SwitchOff('mapLoader');

            _self._setMapCenter(_self._centrePoint, _self._zLevel);

            // Function only available if the site is requested
            // by an external source like "GuleSider" or similar.
            try {
                setTimeout(function() {
                    if (typeof openMarkerInfo == 'function') {
                        openMarkerInfo();
                    }
                }, 0);
            } catch (e) { }
        });
    },

    _handleExmlParsed: function() {
        ///<summary>Handler triggered when the RTM-markers are parsed.</summary>
        RTMMap._cKml.parse();
    },

    _set16By16Icon: function() {
        ///<summary>Method used to define a 16x16 pixels GIcon object</summary>
        var icon = new GIcon();
        icon.iconSize = new GSize(16, 16);
        icon.iconAnchor = new GPoint(6, 16);
        icon.infoWindowAnchor = new GPoint(5, 1);
        return icon;
    },

    _setVikingIcon: function() {
        ///<summary>
        /// Method used to create a new GIcon object 
        /// used for the "Viking Redning" logo found on the map.
        ///</summary>
        var icon = new GIcon();
        icon.iconSize = new GSize(38, 7);
        icon.iconAnchor = new GPoint(6, 16);
        icon.infoWindowAnchor = new GPoint(5, 1);
        return icon;
    },

    _setHomeLocationIcon: function() {
        ///<summary>
        /// Method used to create a new GIcon object for the
        /// icon appearing on the map when the user uses the 
        /// "Mitt hjemsted" functionality.
        ///</summary>
        var icon = new GIcon();
        icon.image = '/images/icons/user_red.png';
        icon.iconSize = new GSize(16, 16);
        icon.iconAnchor = new GPoint(6, 16);
        icon.infoWindowAnchor = new GPoint(5, 1);
        return icon;
    },

    _addCameraMarker: function(marker, name, desc, imagefile, n) {
        ///<summary>Method used when adding road-camera markers to the map</summary>
        ///<param name="marker">GMarker object</param>
        ///<param name="name">Title</param>
        ///<param name="desc">Description</param>
        ///<param name="imagefile">URL to the image to display upon click</param>
        ///<param name="n"></param>
        GEvent.clearListeners(marker, "click");
        GEvent.addListener(marker, "click", function() {
            var pattern = '<a href=".*">(.*)</a>';
            var re = new RegExp(pattern);
            var m = re.exec(desc);
            imageUrl = m[1];
            var elem = RTMMap._createImageDiv(imageUrl);
            LightBox.Show(elem, { top: 0, left: 0 });
        });
        RTMMap.categorizedMarkers.addMarker(marker, 'camera');
    },

    _createImageDiv: function(imageUrl) {
        ///<summary>
        /// Adds the contents of the KML-feed to the map
        /// and creates the DIV used to display the image from one
        //  of the road cameras.
        ///</summary>
        ///<param name="imageUrl">The URL to the image from the road camera</param>
        var leftPos = parseInt((document.viewport.getWidth() / 2) - 320);
        var topPos = parseInt((document.viewport.getHeight() / 2) - 240 + document.viewport.getScrollOffsets().top);

        var newDiv = new Element('div', {
            'id': 'roadImage',
            'style': 'position: absolute; left: ' + leftPos + 'px; top: ' + topPos + 'px;'
        });

        newDiv.innerHTML = '<img style="width: 640px; height: 480px; border: solid black 1px;" src="' + imageUrl + '" alt=""/>' +
            '<div style="width: 642px; background: black; float:left; color: #F96A28;">' +
            '<div style="margin-left: 5px; float:left;">Kilde: <a style="color: #F96A28;" href="http://www.vegvesen.no" target="_new">Statens Vegvesen</a></div>' +
            '<div class="button" style="float:right; margin-right: 0px;">' +
            '<a href="#" class="button" onclick="LightBox.Hide(\'roadImage\', null); $(\'roadImage\').remove(); return false;"><span>Lukk</span></a>' +
            '</div>' +
            '</div>';

        return newDiv;
    },

    _addThirdPartyMarker: function(marker, name, desc, imagefile, n) {
        ///<summary>Method used to push the third-party markers into the thirdpartyMarkers array</summary>
        ///<param name="marker">GMarker object</param>
        ///<param name="name"></param>
        ///<param name="desc"></param>
        ///<param name="imagefile"></param>
        ///<param name="n"></param>
        RTMMap.categorizedMarkers.addMarker(marker, 'partner');
    },

    _addBicycleStandMarker: function(marker, name, desc, imagefile, n) {
        ///<summary>Method for adding bicycle stand markers to the map</summary>
        ///<param name="marker">GMarker object</param>
        ///<param name="name"></param>
        ///<param name="desc"></param>
        ///<param name="imagefile"></param>
        ///<param name="n"></param>
        GEvent.clearListeners(marker, 'click');
        GEvent.addListener(marker, 'click', function() {
            var htmlContent = '<b>' + name + '</b><br/>' + desc;
            marker.openInfoWindowHtml(htmlContent, { maxwidth: 300 });
        });
        RTMMap.categorizedMarkers.addMarker(marker, 'bicyclestand');
    },

    _addAirportMarker: function(marker, name, desc, imagefile, n) {
        ///<summary>Method for adding the ariport markers to the map</summary>
        ///<param name="marker">GMarker object</param>
        ///<param name="name"></param>
        ///<param name="desc"></param>
        ///<param name="imagefile"></param>
        ///<param name="n"></param>
        var airportCode = desc;

        GEvent.clearListeners(marker, "click");

        GEvent.addListener(marker, "click", function() {
            var url = '/kml/feeds/airportinfo.ashx';

            new Ajax.Request(url, {
                method: 'get',
                parameters: { 'airportCode': airportCode, 'airportName': name },
                onSuccess: function(transport) {
                    var infoHTML = transport.responseText;
                    marker.openInfoWindowHtml(infoHTML, { maxwidth: 400 });
                },
                onFailure: function(transport) {
                    alert('Det har oppstått en feil.');
                }
            });
        });

        RTMMap.categorizedMarkers.addMarker(marker, 'airport');
    },

    _refreshMap: function() {
        ///<summary>Refreshes the map automatically every 10 minutes</summary>
        if (this.AllowMapRefresh) {
            this._mapRefreshTimer = setTimeout('GUnload();RTMMap.init()', 600000);
        }
    },

    RTM: function(latLng, title, description) {
        ///<summary>Object holding the RTM</summary>
        ///<param name="latLng">Lat/Lng position of the message</param>
        ///<param name="title">Message title</param>
        ///<param name="description">Message description</param>
        this.LatLng = latLng;
        this.Title = title;
        this.Description = description;
    },

    toggleMarkers: function(categoryName) {
        ///<summary>Toggles the visibility of the markers contained in the array markerArray</summary>
        ///<param name="categoryName">Marker category name</param>
        var iconDiv = $('toggle' + categoryName + 'Icon');
        var category = this.categorizedMarkers.getCategory(categoryName);
        var markers = category.markers;
        for (var a = 0; a < markers.length; a++) {
            var marker = markers[a];
            if (category.visibility == 0) marker.show();
            else marker.hide();
        }

        if (category.visibility == 0) {
            category.visibility = 1;
            if (category.visibleIcon && iconDiv) iconDiv.src = category.visibleIcon;
            if (categoryName == 'bicyclestand') {
                RTMMap._map.closeInfoWindow();
                RTMMap._map.setZoom(12);
                RTMMap._map.panTo(this._findGeoLocation('Oslo'));
            }
        }
        else {
            category.visibility = 0;
            //if (category.hiddenIcon) iconDiv.src = category.hiddenIcon;
        }
    },

    createAreaPanel: function(areaName) {
        ///<summary>
        /// Method used when creating the panel that appears
        /// once the user has clicked on an area name.
        ///</summary>
        var rtmIcon = this.categorizedMarkers.getCategoryIcon('rtm');
        var airportIcon = this.categorizedMarkers.getCategoryIcon('airport');
        var cameraIcon = this.categorizedMarkers.getCategoryIcon('camera');

        var html = '';
        html += '<div style="font-size: 10pt; font-weight: bold; margin-top: 5px; margin-bottom: 5px; text-align:center;">' + areaName;
        html += '<div style="color:#999999;font-size:8pt;font-weight:normal;"><a href="#" onclick="RTMMap.hideAreaPanel();return false;" class="mapregionselector">Velg fylke</a></div></div>';

        html += '<table>';
        html += '<tr><td><input type="checkbox" style="background-color:#ffffff;" id="togglertmCheckbox" onclick="RTMMap.toggleMarkers(\'rtm\');"' + RTMMap.getCategoryVisibility('rtm') + ' /><label for="togglertmCheckbox" style="position:relative;top:-2px;">Trafikkmeldinger</label></td>';
        html += '<td><img id="togglertmIcon" src="' + rtmIcon + '" alt=""/></td></tr>';
        html += '<tr><td><input type="checkbox" style="background-color:#ffffff;" id="toggleairportCheckbox" onclick="RTMMap.toggleMarkers(\'airport\');"' + RTMMap.getCategoryVisibility('airport') + ' /><label for="toggleairportCheckbox" style="position:relative;top:-2px;">Flyplasser</label></td>';
        html += '<td><img id="toggleairportIcon" src="' + airportIcon + '" alt=""/></td></tr>';
        html += '<tr><td><input type="checkbox" style="background-color:#ffffff;" id="togglecameraCheckbox" onclick="RTMMap.toggleMarkers(\'camera\');"' + RTMMap.getCategoryVisibility('camera') + ' /><label for="togglecameraCheckbox" style="position:relative;top:-2px;">Vegkameraer</label></td>';
        html += '<td><img id="togglecameraIcon" src="' + cameraIcon + '" alt=""/></td></tr>';

        // Display City-bikes for Oslo only
        if (areaName == 'Oslo') {
            var bicycleStandIcon = this.categorizedMarkers.getCategoryIcon('bicyclestand');
            html += '<tr><td><input type="checkbox" style="background-color:#ffffff;" id="togglebicyclestandCheckbox" onclick="RTMMap.toggleMarkers(\'bicyclestand\');"' + RTMMap.getCategoryVisibility('bicyclestand') + ' /><label for="togglebicyclestandCheckbox" style="position:relative;top:-2px;">Bysykler</label></td>';
            html += '<td><img id="togglebicyclestandIcon" src="' + bicycleStandIcon + '" alt=""/></td></tr>';

        }

        html += '</table>';

        var parnerIcon = this.categorizedMarkers.getCategoryIcon('partner');
        html += '<div style="padding-top:5px; margin-top:5px;">Partnere</div>';
        html += '<table style="width:100%;">'
        html += '<tr><td><input type="checkbox" style="background-color:#ffffff;" id="togglepartnerCheckbox" onclick="RTMMap.toggleMarkers(\'partner\');"' + RTMMap.getCategoryVisibility('partner') + ' /><label for="togglepartnerCheckbox" style="position:relative;top:-2px;">Viking</label></td>'
        html += '<td align="right"><img id="toggleparnerIcon" src="' + parnerIcon + '" alt="Viking Redningstjenester" /></td></tr>';
        html += '</table>'

        html += '<div style="font-size: 8pt; color: #999999; margin-top: 25px; margin-bottom: 5px;">';
        html += 'Velg hvilke markører som skal vises i kartet.';
        html += '</div>';

        $('areaList').hide();
        $('areaPanel').update(html);
        $('areaPanel').show();

        this.displayArea(areaName);
    },

    getCategoryVisibility: function(name) {
        ///<summary>
        /// Returns the string cheched='checked' if the category is visible
        ///</summary>
        ///<param name="name"></param>
        var category = CategorizedMarkers.getCategory(name);
        if (category.visibility == 1)
            return "checked='checked'";
    },

    hideAreaPanel: function() {
        ///<summary>Method called when hiding the area panel</summary
        $('areaPanel').hide();
        $('areaList').show();
    },

    SaveMapPoint: function(lat, lng, zoom) {
        ///<summary>
        /// Method called when the user decides to save the start point in the map.
        /// <param name="lat">Latitude</param>
        /// <param name="lng">Longitude</param>
        /// <param name="zoom">Current map zoom-level</param>
        ///</summary>
        var _self = this;
        if (Membership.CurrentUser.IsLoggedIn) {
            new Ajax.Request('homelocation.aspx', {
                method: 'post',
                parameters: {
                    mode: 'save',
                    userid: 'userid',
                    lat: lat,
                    lng: lng,
                    zoom: zoom
                },
                onSuccess: function() {
                    _self._map.closeInfoWindow();
                }
            });
        } else {
            alert('Punktet ble ikke lagret, du må være innlogget for å benytte deg av denne funksjonaliteten.');
        }
    },

    GetHomeLocation: function() {
        ///<summary>
        /// Method called when the user is logged in in order to set start point
        /// on the map to the user's default home location.
        ///</summary>
        var _self = this;
        if ((Membership.CurrentUser != null) && (Membership.CurrentUser.IsLoggedIn)) {
            new Ajax.Updater('testDiv',
                '/homelocation.aspx',
                {
                    method: 'post',
                    parameters: { mode: 'load' },
                    evalScripts: true
                });
        }
    },

    SetHomeLocation: function() {
        ///<summary>
        /// Method called when activating the "Mitt hjemsted" feature
        ///</summary>
        var _self = this;
        this.homeLocationListener = GEvent.addListener(this._map, 'click', function(overlay, latLng) {
            if (!overlay) {
                var marker = new GMarker(latLng, _self._setHomeLocationIcon());
                _self._map.addOverlay(marker);

                var lat = marker.getLatLng().lat();
                var lng = marker.getLatLng().lng();
                var zoom = _self._map.getZoom();

                var infoHtml = '<b>Mitt startpunkt</b>';
                infoHtml += '<br/>Dersom du ønsker at dette skal være ditt startpunkt<br/>';
                infoHtml += 'neste gang du logger deg på Trafikkflyt.no, klikk \"Lagre\" nedenfor.';
                infoHtml += '<br>';
                infoHtml += '<div onclick=\"RTMMap.SaveMapPoint(' + lat + ',' + lng + ',' + zoom + ');\" style="border: solid 1px black; padding: 2px; width: 50px;">';
                infoHtml += '<img src="/images/icons/disk.png" alt="Lagre"> Lagre';
                infoHtml += '</div>';
                marker.openInfoWindowHtml(infoHtml);

                GEvent.addListener(_self._map, 'infowindowclose', function() {
                    _self._map.removeOverlay(marker);
                });
            }
        });
    },

    init: function() {
        ///<summary>Initializes the RTM-map</summary>
        var _self = this;

        this._geoLocations = new GeoLocation();
        this._geoLocations.init();

        if (!this.AllowMapRefresh) clearTimeout(RTMMap._mapRefreshTimer);

        if (GBrowserIsCompatible()) {
            this._map = new GMap2(document.getElementById("map"));
            this._map.enableScrollWheelZoom();

            // Disable default page scroll
            var mapDiv = document.getElementById("map");
            GEvent.addDomListener(mapDiv, "DOMMouseScroll", this._wheelevent);
            mapDiv.onmousewheel = this._wheelevent;

            // Make sure all infowindows are closed if the
            // user drags the map.
            GEvent.addListener(this._map, 'dragstart', function() {
                _self._map.closeInfoWindow();
            });

            // Set map center to Hemnes, Norway  
            this._centrePoint = new GLatLng(this._geoLocations.coords[0].lattitude, this._geoLocations.coords[0].longitude);
            this._setMapCenter(this._centrePoint, this._zLevel);

            // Add different map types
            this._map.addMapType(G_SATELLITE_MAP);
            this._map.addMapType(G_HYBRID_MAP);
            this._map.addMapType(G_PHYSICAL_MAP);

            // Add zoom-/pan control
            this._map.addControl(new GLargeMapControl());

            // Add scale control
            this._map.addControl(new GScaleControl());

            // P4s Trafikkredaksjon Lillehammer
            this._addP4Marker();

            // Add marker categories
            CategorizedMarkers.addCategory('rtm', 1, '/images/icons/RTM/marker.png', '/images/icons/RTM/marker.png'); // RTM-markers
            CategorizedMarkers.addCategory('camera', 1, '/images/icons/camera.png', '/images/icons/camera.png'); // Traffic-cameras
            CategorizedMarkers.addCategory('airport', 1, '/images/icons/airports.png', '/images/icons/airports.png'); // Airports
            CategorizedMarkers.addCategory('partner', 1, '/images/partnericons/viking_logo.png', '/images/partnericons/viking_logo.png');   // Partners
            CategorizedMarkers.addCategory('bicyclestand', 0, '/images/icons/bicyclestand.png', '/images/icons/bicyclestand.png'); // City-bikes bicycle stands

            this.categorizedMarkers = CategorizedMarkers;

            // Read KML-feed with RTM-marker data.
            this._exml = new EGeoXml('exml', this._map, '/kml/feeds/roadmessages.ashx', {
                baseicon: _self._setBaseIcon(),
                icontype: 'style', // Use the icon styles defined in the KML-feed.
                noshadow: 'true', // Prevents icons to appear as "doubles" when no shadowicon has been defined in the KML
                createCustomMarker: function(point, name, description, style, icon) {
                    var marker = new GMarker(point, {
                        icon: icon,
                        title: name,
                        zIndexProcess: function() {
                            return 10000
                        }
                    });
                    _self._map.addOverlay(marker);
                    GEvent.addListener(marker, "click", function() {
                        var str = '';
                        str += '<center><div id="tabMap" style="width: 250px; height: 100px; border: 1px black solid;"></div></center>';
                        str += '<script type="text/javascript">';
                        str += 'var point = new GLatLng(' + point.lat() + ',' + point.lng() + '); ';
                        str += 'var marker = new GMarker(point); ';
                        str += 'var tabMap = new GMap2(document.getElementById(\'tabMap\')); ';
                        str += 'tabMap.setCenter(point,12); ';
                        str += 'tabMap.addOverlay(marker); ';
                        str += '</script>';

                        str = description + str;

                        // Hack: Map-details does not work in other browsers
                        // than Firefox, seems that script-tags are skipped..
                        var useragent = navigator.userAgent;
                        if (useragent.indexOf('Firefox') > -1) marker.openInfoWindow(str, { maxWidth: 350 });
                        else marker.openInfoWindow(description, { maxWidth: 350 });
                    });
                    GEvent.addListener(marker, "infowindowclose", function() {
                        _self._setMapCenter(_self.currentCenter, _self.currentZoomLevel);
                    });
                    _self.categorizedMarkers.addMarker(marker, 'rtm');
                    _self._rtMessages.push(new _self.RTM(marker.getLatLng(), name, description));
                }
            });

            // Read KML-feed with partner-marker data.
            this._pKml = new EGeoXml('pKml', this._map, '/kml/feeds/partners.kml', {
                baseicon: _self._setVikingIcon(),
                icontype: 'style',
                noshadow: 'true',
                createCustomMarker: function(point, name, description, style, icon) {
                    var marker = new GMarker(point, {
                        icon: icon,
                        title: name,
                        zIndexProcess: function() {
                            return 9000
                        }
                    });
                    GEvent.addListener(marker, 'click', function() {
                        marker.openInfoWindow('<b>' + name + '</b><br/>' + description, { maxWidth: 300 });
                    });
                    RTMMap.categorizedMarkers.addMarker(marker, 'partner');
                }
            });

            // Read KML-feed with camera info.
            this._cKml = new EGeoXml('cKml', this._map, '/kml/feeds/cameras.ashx', {
                baseicon: _self._set16By16Icon(),
                icontype: 'style',
                noshadow: 'true',
                useNameAsTitle: 'true',
                addmarker: _self._addCameraMarker
            });

            // Read KML-feed with airport & delay information.
            this._apKml = new EGeoXml('apKml', this._map, '/kml/feeds/airportsnorway.kml', {
                baseicon: _self._set16By16Icon(),
                icontype: 'style',
                noshadow: 'true',
                useNameAsTitle: 'true',
                zIndex: 9000,
                addmarker: _self._addAirportMarker
            });

            // Read KML-feed with bicyclestands in Oslo
            this._bicycleStandsKml = new EGeoXml('bStandsKml', this._map, '/kml/feeds/bicyclestands.ashx', {
                baseicon: _self._set16By16Icon(),
                icontype: 'style',
                noshadow: 'true',
                useNameAsTitle: 'true',
                addmarker: _self._addBicycleStandMarker
            });

            // Add marker overlay
            this._addMarkerOverlay();

            // Refresh map every 10 minutes.
            this._refreshMap();
        }
    },

    _findGeoLocation: function(areaName) {
        ///<summary>Get the Lat/Lng of the specified area from the list of predefined areas/points</summary>
        ///<param name="areaName"></param>
        var point = null;
        for (var i = 0; i < this._geoLocations.coords.length; i++) {
            if (this._geoLocations.coords[i].area == areaName) {
                point = new GLatLng(this._geoLocations.coords[i].lattitude, this._geoLocations.coords[i].longitude);
                break;
            }
        }
        return point;
    },

    displayArea: function(areaName) {
        ///<summary>Centers the map to the selected area</summary>
        ///<param name="areaName"></param>
        this._map.closeInfoWindow();
        this._map.setZoom(7);
        this._map.panTo(this._findGeoLocation(areaName));
    },

    _addRTMMarkers: function() {
        ///<summary>
        /// Method called after a route has been planned using 
        /// the route planner in order top add the missing RTM-markers.
        ///</summary>
        var _self = this;
        var oldHandle = evtExmlParsed;
        GEvent.clearListeners(this._exml);
        GEvent.addListener(this._exml, 'parsed', function() {
            GEvent.clearListeners(_self._exml);
            evtExmlParsed = GEvent.addListener(_self._exml, 'parsed', handleExmlParsed);
            _self._map.returnToSavedPosition();
        });
        _self._exml.parse();
    }
};

var MapTypeMenu = {
    ///<summary>Object-variable holding the methods used to handle the 'Karttyper' menu</summary>

    startMouseObserving: function(skipItem) {
        ///<summary>Method used when adding mouseover/mouseout observers to the menuitems</summary>
        ///<param name="skipItem">
        /// The selected element, skip adding mouseout observer for this
        /// in order to make it appear selected.
        ///</param>

        for (var i = 0; i < $('contents').childElements().length; i++) {
            var el = $('contents').childElements()[i];
            if (el.id == skipItem) {
                Event.stopObserving(el, 'mouseout');
            } else {
                el.style.textDecoration = 'none';
                Event.observe(el, 'mouseover', function(ev) { $(Event.element(ev)).style.textDecoration = 'underline'; });
                Event.observe(el, 'mouseout', function(ev) { $(Event.element(ev)).style.textDecoration = 'none'; });
            }
        }
    },

    startClickObserving: function() {
        ///<summary>Method used to append 'click' observing to the menuitems</summary>

        for (var i = 0; i < $('contents').childElements().length; i++) {
            Event.observe($('contents').childElements()[i], 'click', function(ev) {
                var map = RTMMap._map;
                var el = $(Event.element(ev));
                switch (el.id) {
                    case 'mapTypeNormal':
                        map.setMapType(G_NORMAL_MAP);
                        break;
                    case 'mapTypeSatellite':
                        map.setMapType(G_SATELLITE_MAP);
                        break;
                    case 'mapTypePhysical':
                        map.setMapType(G_PHYSICAL_MAP);
                        break;
                    case 'mapTypeHybrid':
                        map.setMapType(G_HYBRID_MAP);
                        break;
                }
                MapTypeMenu.startMouseObserving(el.id);
            });
        }
    }
}

function switchMap(id) {
    ///<summary>
    /// Method used when switching between the RTMs,
    /// the Routeplanner and the Trelocity map.
    ///</summary>
    ///<param name="id">ID of the clicked item</param>
    $('areaPanel').update();
    switch (id) {
        case 'mapTabAreas':
            RoutePlanner.end();
            RTMMap.AllowMapRefresh = true;
            RTMMap._refreshMap();
            $('trelocityMap').hide();
            $('areaList').show();
            $('map').show();
            break;
        case 'mapTabRoutePlanner':
            $('trelocityMap').hide();
            $('mapTabMapType').show();
            $('map').show();
            RTMMap.AllowMapRefresh = false;
            RoutePlanner.init(RTMMap._map);
            RoutePlanner.start();
            break;
           case 'mapTabTrelocity':
           	RoutePlanner.end();
           	RTMMap.AllowMapRefresh = false;
           	RTMMap._refreshMap();
           	frames['trelocityIFrame'].location.href = "http://oslo.trelocity.se/";
           	__LogWidgetHits('Trelocity');
           	$('areaList').hide();
           	$('map').hide();
           	$('trelocityMap').show();
           	break;
    }
    setButtonActive(id);
}

function setButtonActive(id) {
    ///<summary>Method used to set the active button's background orange</summary>
    ///<param name="id">ID of the clicked button</param>
    var obj = $(id);
    var child = obj.childElements()[0];

    // Remove event-listener added when the "Mitt hjemsted" button was clicked
    if ((RTMMap.homeLocationListener != null) && (id != 'mapTabHomeLocation')) {
        GEvent.removeListener(RTMMap.homeLocationListener);
    }

    if (id == 'mapTabRoutePlanner') {
        //$('mapTabAreas').style.background = 'transparent url(\'/images/gfx/map_tab_left.png\') no-repeat';
        //$('mapTabAreas').childElements()[0].style.background = 'transparent url(\'/images/gfx/map_tab.png\') no-repeat';
        $('mapTabAreas').className = "maptab";

        //$('mapTabTrelocity').style.background = 'transparent url(\'/images/gfx/map_tab_left.png\') no-repeat';
        //$('mapTabTrelocity').childElements()[0].style.background = 'transparent url(\'/images/gfx/map_tab.png\') no-repeat';
        $('mapTabTrelocity').className = "maptab";

        //obj.style.background = 'transparent url(\'/images/gfx/map_tab.png\') no-repeat scroll bottom left';
        //child.style.backgroundPosition = 'bottom left';
        obj.className = "maptabselect";
    } else if (id == 'mapTabAreas') {
        $('mapTabMapType').show();
        
        //$('mapTabRoutePlanner').style.background = 'transparent url(\'/images/gfx/map_tab.png\') no-repeat';
        //$('mapTabRoutePlanner').childElements()[0].style.background = 'transparent url(\'/images/gfx/map_tab.png\') no-repeat';
        $('mapTabRoutePlanner').className = "maptab";
        
        //$('mapTabTrelocity').style.background = 'transparent url(\'/images/gfx/map_tab_left.png\') no-repeat';
        //$('mapTabTrelocity').childElements()[0].style.background = 'transparent url(\'/images/gfx/map_tab.png\') no-repeat';
        $('mapTabTrelocity').className = "maptab";

        //obj.style.background = 'transparent url(\'/images/gfx/map_tab_left.png\') no-repeat scroll bottom left';
        //child.style.backgroundPosition = 'bottom left';
        obj.className = 'maptabselect';
    } else if (id == 'mapTabTrelocity') {
        //$('mapTabAreas').style.background = 'transparent url(\'/images/gfx/map_tab_left.png\') no-repeat';
        //$('mapTabAreas').childElements()[0].style.background = 'transparent url(\'/images/gfx/map_tab.png\') no-repeat';
        $('mapTabAreas').className = "maptab";

        //$('mapTabRoutePlanner').style.background = 'transparent url(\'/images/gfx/map_tab.png\') no-repeat';
        //$('mapTabRoutePlanner').childElements()[0].style.background = 'transparent url(\'/images/gfx/map_tab.png\') no-repeat';
        $('mapTabRoutePlanner').className = "maptab";

        $('mapTabMapType').hide();
        
        //obj.style.background = 'transparent url(\'/images/gfx/map_tab_left.png\') no-repeat scroll bottom left';
        //child.style.backgroundPosition = 'bottom left';
        obj.className = "maptabselect";
    }
}

function getLeftPos(obj) {
    ///<summary>Method used to get the left position of the menutab</summary>
    ///<param name="obj">Object to get the left position for</param>
    return (obj.style.left).replace('px', '');
}

