﻿// YPGMapControl.js
// This file contains a wrapper class for the VEMap class exposing 
// methods required by YPG for displaying maps and generating routes.
//
// To integrate this class include the following line of code in the head of
// the page that you want to add a VE Map to.
//
//<script type='text/javascript' src='<javascriptlibrary>/YPGMapControl.js'></script>
//
// where <javascriptlibrary> is the path of the directory containing the sites javascript.
//
// The following example shows an html page that displays a map, adds a customized pushpin
// indicating YPG's office, generates a route, and driving directions.  The MapResults Div holds the main
// map and the drivingDirections div displays the individual directions and maps specific to each direction.
//
//        <html xmlns="http://www.w3.org/1999/xhtml" >
//            <head>
//                <title>test.htm</title>
//                <link rel="stylesheet" type="text/css" href="http://www.yellowpages.ca/include/style.css" />
//                <script type='text/javascript' src='YPGMapControl.js'></script>
//                <script type='text/javascript'>
//                    
//                    function initMap()
//                    {
//                        var map = new YPGMapControl("MapResults");
//                        map.CreateAndLoadMap();
//                        map.HideVEControls();
//                        map.GetRoute("6 Chelton Drive, Richmond Hill, Ontario, L4E 4A9, Canada", "7 Beaverton Road North, Richmond Hill, Ontario, L4C 3J6, Canada");
//                        map.DrivingDirectionsArea = "drivingDirections";
//                        map.pushPinIcon = "questionLightYellow.gif";
//                        map.AddLocation(43.790269, -79.233737, "Yellow Pages Group", "325 Milner Avenue", "Toronto", "Ontario", "M1B 5S8", "416.412.5702");
//                            
//                    }
//                </script>
//            </head>
//            <body onload="initMap()">
//                <div id="MapResults" style="width:800px;height:400px; position:relative;"></div>
//                <div id="drivingDirections" style="width:800px;height:400px; position:relative;"></div>
//            </body>
//        </html>



//Inject the VE Map control tag into the page.
document.write("<script type='text/javascript' src='http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6'></script>");

// YPG VE Map Control 
// This class wraps the VE Control and exposes methods to create, load, navigate and 
// hide the VE Map controls.
// Constructor Parameter:   controlId   string  This is the id of the div element that
// the map is to be displayed in.
function YPGMapControl(controlId)
{
    //The map Id and the id of the div element that will hold the map.
    this.controlId = controlId;
    
    //This is the actual VEMap object.  It is accessable outside of the class but it is
    //preferrable to use the YPGMapControl methods as these are tailored to ypg's mapping
    //requirements.
    this.mapInstance = null;
    
    //This is the url of the image that will be used when a pushpin is added to the map
    //indicating a location of interest.
    this.pushPinIcon = null;
    
    //This is a VECustomIconSpecification to be applied to all pushpins being added
    //This can be overriden by passing the customIconSpecification parameter to AddLocation.
    this.customIconSpecification = null;
    
    //The unit of measure to be displayed on the map.
    this.distanceUnits = VEDistanceUnit.Kilometers;
    
    //This hides the intrinsic VE controls, displaying only the map.
    this.HideVEControls = function()
    {
        if (this.mapInstance != null)
        {
            this.mapInstance.HideDashboard();
        }
    }
    
    //This displays the intrinsic VE controls.
    this.ShowVEControls = function()
    {
        if (this.mapInstance != null)
        {
            this.mapInstance.ShowDashboard();
        }    
    }
    
    //Moves the map to be centered on the given latitude and longitude and then
    //adjusts the zoom to the given level.
    this.SetCenterAndZoom = function(latLong, zoomLevel){
        if (this.mapInstance != null)
        {
            this.mapInstance.SetCenterAndZoom(latLong, zoomLevel);
        }
    }
    
    
    //Initializes the internal map instance and requests the appropriate tile set to be
    //displayed.
    //Parameters:   latLong A VELatLong representing the center of the map.
    //              zoom    The zoom level at which the map is to be displayed.
    //              style   The type of map to display (VEMapStyle enumeration)
    //              fixed   Boolean value indicating whether the map is fixed (i.e. cannot
    //                      be navigated using the map control)
    //              mode    Indicates whether 3D is enabled (VEMapMode enumeration)
    //              showSwitch  Boolean value indicating whether the 2D/3D switch is visible
    this.CreateAndLoadMap = function(latLong, zoom, style, fixed, mode, showSwitch)
    {
        this.mapInstance = new VEMap(controlId);
        this.mapInstance.LoadMap(latLong, zoom, style, fixed, mode, showSwitch);
        this.mapInstance.SetScaleBarDistanceUnit(this.distanceUnits);
        this.AddCompassRose();
    }
    
    //Creates and injects the compass div that appears on the top right hand corner of the map
    //<div id="compass" style="background-color:transparent; z-index: 999; left: 720px; background-image: url(http://dev.cb.yp.ca/map/North_icon.gif); width: 40px; position: relative; top: 7px; height: 40px;"></div>
    this.AddCompassRose = function()
    {
        var targetMap = document.getElementById(controlId);
        var target = findPos(targetMap);
        var targetWidth = targetMap.style.width;
        
        
        var d = document.createElement( "DIV" );
        
        
        d.style.backgroundColor = 'transparent';
        d.style.zIndex = '999';
        d.style.right = '40px';
        d.style.top = '7px';
        d.style.backgroundImage = 'url(http://dev.cb.yp.ca/map/North_icon.gif)';
        d.style.width = '18px';
        d.style.height = '25px';
		d.style.backgroundRepeat = 'no-repeat';
        d.style.position = 'absolute';
        targetMap.appendChild( d );
    }
    //Creates a new instance of the map.  This needs to be followed by the LoadMap call 
    //to display a map.
    this.Create = function(){
        this.mapInstance = new VEMap(controlId);
    }
    
    //Loads the map and if provided sets the appropriate view.
     //Parameters:   latLong A VELatLong representing the center of the map.
    //              zoom    The zoom level at which the map is to be displayed.
    //              style   The type of map to display (VEMapStyle enumeration)
    //              fixed   Boolean value indicating whether the map is fixed (i.e. cannot
    //                      be navigated using the map control)
    //              mode    Indicates whether 3D is enabled (VEMapMode enumeration)
    //              showSwitch  Boolean value indicating whether the 2D/3D switch is visible
    this.LoadMap = function(latLong, zoom, style, fixed, mode, showSwitch){
        this.mapInstance.LoadMap(latLong, zoom, style, fixed, mode, showSwitch);
    }

    //Sets the Url to the image that is the custom Icon
    //Parameters:   shape   A VEShape for which the custom Icon is to be set
    //              imageUrl    A Url to the image file.
    
	//Translate the dashboard into French
	this.DashboardTranslateFR = function()
	{
		 document.getElementById('MSVE_navAction_FlatlandMapMode').title = 'Visualisez les cartes en 2D';
		 document.getElementById('MSVE_navAction_View3DMapMode').title = "Visualisez les cartes en 3D en utilisant le programme beta Virtual Earth 3D";
		 document.getElementById('MSVE_navAction_RoadMapStyle').title = 'Passez à la vue Route';
		 document.getElementById('MSVE_navAction_AerialMapStyle').title = 'Passez à la vue Aérienne';
		 document.getElementById('MSVE_navAction_HybridMapStyle').title = 'Passez à la vue Hybride';
		 document.getElementById('MSVE_navAction_ObliqueMapView').title = 'Passez à la vue de dessus';
		 document.getElementById('Compass').title = "Effectuez un panoramique dans n'importe quelle direction";
		 document.getElementById('MSVE_navAction_tinyZoomBar_plus').title = "Zoom avant. Pour zoomer sans interruption, cliquez sur le bouton de la souris et maintenez-le enfoncé. Le recadrage est possible dans tous les sens";
		 document.getElementById('MSVE_navAction_tinyZoomBar_minus').title = "Zoom arrière. Pour zoomer sans interruption, cliquez sur le bouton de la souris et maintenez-le enfoncé. Le recadrage est possible dans tous les sens.";
		 document.getElementById('MSVE_obliqueNotifyText').innerHTML = "Voyez cet emplacement au moyen de la vue de dessus";
		 document.getElementById('MSVE_navAction_toggleGlyphWrapper').title = "Masquez le contrôle de la vue";

		 document.getElementById('MSVE_navAction_RoadMapStyle').innerHTML = "Route";
		 document.getElementById('MSVE_navAction_AerialMapStyle').innerHTML = "A&eacute;rien";
		 document.getElementById('MSVE_navAction_HybridMapStyle').innerHTML = "Hybride";
		 document.getElementById('MSVE_navAction_ObliqueMapView').innerHTML = "Dessus";

		 //Disable 3D mode since Bird's eye text cannot be changed to enable 3D
		 document.getElementById('MSVE_navAction_View3DMapMode').style.display="none";
		 document.getElementById('MSVE_navAction_FlatlandMapMode').style.display="none";

		 //Translate Bird's eye images tooltips only when in oblique view
		 this.mapInstance.AttachEvent('onchangemapstyle',TranslateObliqueFR);
	}
	
	//Translate bird's eye tooltip text
	function TranslateObliqueFR(e)
	{
			//check if map is in oblique (birds eye) mode using the Map Event object
			if(e.mapStyle == "o")
			{
		 	document.getElementById('MSVE_obliqueCompassContainer').title = "Changez la direction de la vue"; 		 
			document.getElementById('MSVE_navAction_ccw').title = "Faites tourner l'angle de la caméra dans le sens contraire des aiguilles d'une montre";
		 	document.getElementById('MSVE_navAction_cw').title = "Faites tourner l'angle de la caméra dans le sens des aiguilles d'une montre";
			}
	}
	//Sets the Url to the image that is the custom Icon
	//Parameters:   shape   A VEShape for which the custom Icon is to be set
	//              imageUrl    A Url to the image file.	
	this.SetCustomIcon = function(shape, imageUrl)
    {
        if(shape != null)
        {
            if(imageUrl!=null &&imageUrl!='')
            {
                shape.SetCustomIcon(imageUrl);
            }
        }
    }
   
    
    //Adds a pushpin the the map
    //Parameter:    pushpin A VE shape to be added to the map.
    this.AddPushpin = function(pushPin)
    {
        if (this.mapInstance != null)
        {
            this.mapInstance.AddShape(pushPin);
        }
    }
    
    
    //Adds a location pushpin to the map with the details for the info box set
    //Parameters:   lat The latitude of the location
    //              lon The longitude of the location
    //              coyName The company name or a display name
    //              address The address
    //              city    The city
    //              prov    The province
    //              postalCode  The postal code
    //              phone   The phone
    //              customIconSpecification HTML or VECustomIconSpecification that overrides the customIcon and customIconSpecification properties of this class
    this.AddLocation = function(lat, lon, coyName, address, city, prov, postalCode, phone, customIconSpecification)
    {
        var newPin = null;
        if (this.mapInstance != null)
        {
            var newPin = new VEShape(VEShapeType.Pushpin, new VELatLong(lat, lon));
            newPin.SetTitle(coyName);
            var contactBlock = address + "<br/>" +
                                city + "<br/>" +
                                prov + "<br/>" +
                                postalCode + "<br/>" +
                                phone + "<br/>";
            newPin.SetDescription(contactBlock);
            if(customIconSpecification == null || customIconSpecification == 'undefined')
            {
                if(this.pushPinIcon != null)
                {
                    this.SetCustomIcon(newPin, this.pushPinIcon);
                }
                if(this.customIconSpecification != null)
                {
                   this.SetCustomIcon(newPin, this.customIconSpecification);
                }
            }
            else
            {
                this.SetCustomIcon(newPin, customIconSpecification);
            }        
            this.AddPushpin(newPin);
        }
        
    }
    
    //Adds multiple locations to the map
    //Parameter:    locations an array of locations.
    this.AddLocations = function(locations)
    {
        var lat; 
        var lon; 
        var coyName; 
        var address; 
        var city; 
        var prov; 
        var postalCode; 
        var phone;
        var customIconSpecification;
        var pointArray = new Array();
        if (this.mapInstance != null){
            for (var i = 0; i<locations.length; i++)
            {
                lat = locations[i][0];
                lon = locations[i][1];
                coyName = locations[i][2];
                address = locations[i][3];
                city = locations[i][4];
                prov = locations[i][5];
                postalCode = locations[i][6];
                phone = locations[i][7];
                customIconSpecification =locations[i][8];
                this.AddLocation(lat, lon, coyName, address, city, prov, postalCode, phone, customIconSpecification);
                pointArray.push(new VELatLong(lat,lon));
            }
            if (pointArray.length>0){
                this.mapInstance.SetMapView(this.mapInstance.GetShapeLayerByIndex(0).GetBoundingRectangle());
            }
        }   
     }       

	//Deletes all shapes in all layers, leaving empty layers behind
    this.DeleteAllShapes = function()
	{
			this.mapInstance.DeleteAllShapes();
	}	

	//Deletes a VEShape Class object from any layer, including the base map layer.
	//Parameter:  shape  The VEShape to remove
    this.DeleteShape = function(shape)
	{
			this.mapInstance.DeleteShape(shape);
	}
	
	//Gets the direction manager used for V5 routing
	//Returns: _dm  The direction manager containing the V5 route pushpins
	this.Get_dm = function()
	{
			return this.mapInstance._dm;
	}
    //Finds a location, not really used at this stage but here if necessary.
    this.FindLocation = function(address, city, prov, postalCode)
    {
        var searchAddress = '';
        var what = null;
        var findType = null;
        var shapeLayer = null;
        var startIndex = null;
        var numberOfResults = null; 
        var showResults = false;
        var createResults = false; 
        var useDefaultDisambiguation = false; 
        var setBestMapView = true;
        
        if (address != null && address != '')
        {
            searchAddress = searchAddress + address;
        }
        searchAddress = searchAddress + ', ';
        
        if (city != null && city != '')
        {
            searchAddress = searchAddress + city;
        }
        searchAddress = searchAddress + ', ';
        
        if (prov != null && prov != '')
        {
            searchAddress = searchAddress + prov;
        }
        searchAddress = searchAddress + ', ';
        
        if (postalCode != null && postalCode != '')
        {
            searchAddress = searchAddress + postalCode;
        }
        
        if (this.mapInstance!=null)
        {
            this.mapInstance.Find(what, searchAddress, findType, shapeLayer, startIndex, numberOfResults, showResults, createResults, useDefaultDisambiguation, setBestMapView, onGotFindResults);
        }
    }
    
    //Gets a route (V5)
    //Parameters:   start   VELatLong or string address of the starting location
    //              end     VELatLong or string address of the ending locations
    //              units   VEDistanceUnits enum    {kilometers|miles}
    //              routeType   VERouteType enum    {shortest|quickest}
    this.GetRoute = function(start, end, units, routeType, callback)
    {
        if (this.mapInstance != null)
        {
            if (callback == null) callback = onGotRoute;
            this.mapInstance.GetRoute(start, end, units, routeType, callback);
        }    
    }

    //Gets a route (V6)
    //Parameters:   locations   An array of objects specifying the points through which the route must pass. 
	//							The points can be either VELatLong Class objects or String objects.
    //              options     A VERouteOptions Class object specifying the routing options.
	this.GetDirections = function(locations, options)
	{
		options.DistanceUnit   = VERouteDistanceUnit.Kilometer;
		
        if (this.mapInstance != null)
        {
			this.mapInstance.GetDirections(locations,options);
		}
	}
	//Translates the route driving directions into French (V5)
	//Parameters:   route   A VERoute Class object returned from a V5 GetRoute call 
	//Returns:      route   A VERoute Class object returned from a V5 GetRoute call
	this.GetRouteTranslateFR = function(route)
	{
		var len = route.Itinerary.Segments.length;
            for(var i = 0; i < (len) ;i++)
            {
				route.Itinerary.Segments[i].Instruction = TranslateFR(route.Itinerary.Segments[i].Instruction);
			}
		return route;
	}
	//Translates the route driving directions into French (V6)
	//Parameters:   route   A VERoute Class object returned from a V6 GetDirections call 
	//Returns:      route   A VERoute Class object returned from a V6 GetDirections call 
this.GetDirectionsTranslateFR = function(route)
	{
	   //clear original route pushpins
		map.DeleteAllShapes();
		
	   // Unroll route
	   var routeinfo="";
	   var steps = "";
	   var legs = route.RouteLegs;
	   var leg = null;
	   var legCount = 0;
	   var shape = null;
	   
	   var	totalDistance = route.Distance;
	       	totalDistance = totalDistance.toFixed(1);
	   var	totalTime = route.Time;
	   		totalTime = totalTime*1000;
						
			//alert(time(totalTime));
			
			totalTime = time(totalTime);

	   // Get intermediate legs
		for(var i = 0; i < legs.length; i++)
		{
		   // Get this leg so we don't have to derefernce multiple times
		   leg = legs[i];  // Leg is a VERouteLeg object
			
		   // Unroll each intermediate leg
		   for(var j = 0; j < leg.Itinerary.Items.length; j ++)
		   {
			var turn = leg.Itinerary.Items[j];
			var turnDistance = turn.Distance;
			
			legCount = j+1;
			
			turnDistance = turnDistance.toFixed(1);
			
			turn = TranslateFR(turn.Text);  // turn is a VERouteItineraryItem object			
			
			shape = new VEShape(VEShapeType.Pushpin,leg.Itinerary.Items[j].LatLong )
			if(legCount == 1)
			{
				shape.SetDescription(turn);
				shape.SetCustomIcon("http://dev.virtualearth.net/mapcontrol/v6/i/bin/1.0.20070926140324.39/pins/mapicon_start.gif");
			}
			else if(legCount == leg.Itinerary.Items.length)
			{
				shape.SetDescription(turn);
				shape.SetCustomIcon("http://dev.virtualearth.net/mapcontrol/v6/i/bin/1.0.20070926140324.39/pins/mapicon_end.gif");
			}
			else
			{
				shape.SetDescription(turn);
				shape.SetCustomIcon("http://dev.virtualearth.net/mapcontrol/v6/i/bin/1.0.20070926140324.39/pins/RedCircle"+ legCount +".gif");
			}
			
			map.AddPushpin(shape);
			
			steps += GenerateResults([turn, turnDistance, totalDistance, totalTime], j, leg.Itinerary.Items.length);
		   }
		   
		}
		
		routeinfo = steps;
   
	   var ourDiv=document.getElementById('drivingDirections');
	   
	   	ourDiv.innerHTML = routeinfo;
	
		___lastRoute = route;
	//return route;
	}
	
	this.GetDirectionsEN = function(route)
	{
	   //clear original route pushpins
		map.DeleteAllShapes();
	   
	   // Unroll route
	   var routeinfo="";
	   var steps = "";
	   var legs = route.RouteLegs;
	   var leg = null;
	   var legCount = 0;
	   var shape = null;
	   
	   var	totalDistance = route.Distance;
	       	totalDistance = totalDistance.toFixed(1);
	   var	totalTime = route.Time;
	   		totalTime = totalTime*1000;
						
			//alert(time(totalTime));
			
			totalTime = time(totalTime);
			
	   // Get intermediate legs
		for(var i = 0; i < legs.length; i++)
		{
		   // Get this leg so we don't have to derefernce multiple times
		   leg = legs[i];  // Leg is a VERouteLeg object
			
		   // Unroll each intermediate leg
		   for(var j = 0; j < leg.Itinerary.Items.length; j ++)
		   {
			var turn = leg.Itinerary.Items[j];
			var turnDistance = turn.Distance;
			
			legCount = j+1;
			
			turnDistance = turnDistance.toFixed(1);
			
			shape = new VEShape(VEShapeType.Pushpin,leg.Itinerary.Items[j].LatLong )
			if(legCount == 1)
			{
				shape.SetDescription(turn.Text);
				shape.SetCustomIcon("http://dev.virtualearth.net/mapcontrol/v6/i/bin/1.0.20070926140324.39/pins/mapicon_start.gif");
			}
			else if(legCount == leg.Itinerary.Items.length)
			{
				shape.SetDescription(turn.Text);
				shape.SetCustomIcon("http://dev.virtualearth.net/mapcontrol/v6/i/bin/1.0.20070926140324.39/pins/mapicon_end.gif");
			}
			else
			{
				shape.SetDescription(turn.Text);
				shape.SetCustomIcon("http://dev.virtualearth.net/mapcontrol/v6/i/bin/1.0.20070926140324.39/pins/RedCircle"+ legCount +".gif");
			}
			
			map.AddPushpin(shape);
			
			
			steps += GenerateResults([turn.Text, turnDistance, totalDistance, totalTime], j, leg.Itinerary.Items.length);
		   }
		}
		
		routeinfo = steps;
   
	   var ourDiv=document.getElementById('drivingDirections');
	   
	   ourDiv.innerHTML = routeinfo;
	   
	   ___lastRoute = route;
		
	//return route;
	}

	//Translates directions into French
	//Parameters:   itineraryText   The driving itinerary directions that need to be translated
	//Returns:      itineraryText   The driving itinerary directions that need to be translated
	function TranslateFR(itineraryText)
	{
		itineraryText = itineraryText.replace(/At roundabout take exit number/gi, 'Au carrefour giratoire, prenez la sortie n&deg;');
		itineraryText = itineraryText.replace(/Exit roundabout at exit number/gi, 'Sortez du carrefour giratoire &agrave; la sortie n&deg;');
		
		itineraryText = itineraryText.replace(/Road name changes to/gi, 'Le nom de la rue devient');
		itineraryText = itineraryText.replace(/Turn is potentially restricted/gi, 'Il se peut que le virage soit interdit');
		itineraryText = itineraryText.replace(/Stop for toll booth/gi, 'Arr&ecirc;tez au poste de p&eacute;age');
		itineraryText = itineraryText.replace(/Check the time table/gi, 'Consultez l&rsquo;horaire');
		itineraryText = itineraryText.replace(/and then immediately bear/gi, 'et continuez imm&eacute;diatement vers');
		itineraryText = itineraryText.replace(/and then immediately turn/gi, 'et tournez imm&eacute;diatement');
		itineraryText = itineraryText.replace(/Enter roundabout and take/gi, 'Prenez le carrefour giratoire, puis prenez');
		itineraryText = itineraryText.replace(/Pass through 1 roundabout/gi, 'Traversez un carrefour giratoire');
		
		itineraryText = itineraryText.replace(/to stay on/gi, 'pour rester sur');
		itineraryText = itineraryText.replace(/on the right/gi, '&agrave; votre droite');
		itineraryText = itineraryText.replace(/on the left/gi, '&agrave; votre gauche');
		itineraryText = itineraryText.replace(/Gate access required/gi, 'Il vous faut un droit d&rsquo;acc&egrave;s');
		itineraryText = itineraryText.replace(/Road name changes/gi, 'Rue change de nom');
		itineraryText = itineraryText.replace(/and follow signs/gi, 'et suivez la signalisation');
		itineraryText = itineraryText.replace(/and then immediately/gi, 'puis imm&eacute;diatement');
		itineraryText = itineraryText.replace(/and then bear/gi, 'puis continuez');
		itineraryText = itineraryText.replace(/Take ramp toward/g, 'Prenez la bretelle vers');
		itineraryText = itineraryText.replace(/take ramp toward/g, 'prenez la bretelle vers');
		itineraryText = itineraryText.replace(/Exit roundabout at/gi, 'Sortez du carrefour giratoire &agrave;');
		itineraryText = itineraryText.replace(/Exit roundabout onto/gi, 'Sortez du carrefour giratoire vers');
		
		itineraryText = itineraryText.replace(/to stay/gi, 'pour rester');
		itineraryText = itineraryText.replace(/and then/gi, 'et ensuite');
		itineraryText = itineraryText.replace(/Keep straight/g, 'Continuez tout droit');
		itineraryText = itineraryText.replace(/keep straight/g, 'continuez tout droit');
		itineraryText = itineraryText.replace(/Keep left/g, 'Gardez la gauche');
		itineraryText = itineraryText.replace(/keep left/g, 'gardez la gauche');
		itineraryText = itineraryText.replace(/Keep right/g, 'Gardez la droite');
		itineraryText = itineraryText.replace(/keep right/g, 'gardez la droite');
		itineraryText = itineraryText.replace(/1st exit/gi, 'la 1<sup>re</sup> sortie');
		itineraryText = itineraryText.replace(/2nd exit/gi, 'la 2<sup>e</sup> sortie');
		itineraryText = itineraryText.replace(/3rd exit/gi, 'la 3<sup>e</sup> sortie');
		itineraryText = itineraryText.replace(/4th exit/gi, 'la 4<sup>e</sup> sortie');
		itineraryText = itineraryText.replace(/Local road\(s\)/gi, 'voie r&eacute;gionale');
		itineraryText = itineraryText.replace(/Toll road/gi, 'Route &agrave; p&eacute;age');
		itineraryText = itineraryText.replace(/Arrive At/gi, 'Arriv&eacute;e &agrave;');
		itineraryText = itineraryText.replace(/Depart from/gi, 'D&eacute;part de');
		itineraryText = itineraryText.replace(/and keep/gi, 'puis gardez');
		itineraryText = itineraryText.replace(/Turn back/gi, 'Faites demi-tour');
		itineraryText = itineraryText.replace(/Merge onto/gi, '&Agrave; la jonction, continuez sur / vers');
		itineraryText = itineraryText.replace(/Stay on/gi, 'Restez sur');
		itineraryText = itineraryText.replace(/At exit/gi, '&Agrave; la sortie n&deg;');
		itineraryText = itineraryText.replace(/Take ramp/g, 'Prenez la bretelle');
		itineraryText = itineraryText.replace(/take ramp/g, 'prenez la bretelle');
		itineraryText = itineraryText.replace(/Exit onto/gi, 'Sortez sur');
		itineraryText = itineraryText.replace(/Enter roundabout/gi, 'Prenez le carrefour giratoire');
		itineraryText = itineraryText.replace(/Pass through/gi, 'Traversez');
		itineraryText = itineraryText.replace(/At roundabout,/gi, 'Au carrefour giratoire,');
		
		itineraryText = itineraryText.replace(/\bnortheast\b/gi, 'nord-est');
		itineraryText = itineraryText.replace(/\bnorthwest\b/gi, 'nord-ouest');				  
		itineraryText = itineraryText.replace(/\bsoutheast\b/gi, 'sud-est');				  
		itineraryText = itineraryText.replace(/\bsouthwest\b/gi, 'sud-ouest');				  
		itineraryText = itineraryText.replace(/\bwest\b/gi, 'ouest');				  
		itineraryText = itineraryText.replace(/\bsouth\b/gi, 'sud');
		itineraryText = itineraryText.replace(/\beast\b/gi, 'est');
		itineraryText = itineraryText.replace(/\bnorth\b/gi, 'nord');
		itineraryText = itineraryText.replace(/LEFT/gi, '&agrave; gauche');				  
		itineraryText = itineraryText.replace(/RIGHT/gi, '&agrave; droite');
		itineraryText = itineraryText.replace(/STRAIGHT/gi, 'tout droit');				  
		itineraryText = itineraryText.replace(/Unknown/gi, 'Inconnu');
		itineraryText = itineraryText.replace(/Ferry/gi, 'Traversier');
		itineraryText = itineraryText.replace(/Entering/gi, 'Entr&eacute;e');
		itineraryText = itineraryText.replace(/\bfor\b/gi, 'pour');
		itineraryText = itineraryText.replace(/\bAt\b/gi, '&Agrave;');
		itineraryText = itineraryText.replace(/onto/gi, 'sur');
		itineraryText = itineraryText.replace(/exit/g, 'sortie');
		itineraryText = itineraryText.replace(/\bto\b/gi, 'vers');
		itineraryText = itineraryText.replace(/\bon\b/gi, 'sur');
		itineraryText = itineraryText.replace(/Turn/g, 'Tournez');
		itineraryText = itineraryText.replace(/turn/g, 'tournez');
		itineraryText = itineraryText.replace(/Return/gi, 'Retournez vers');
		itineraryText = itineraryText.replace(/Take/g, 'Prenez');
		itineraryText = itineraryText.replace(/take/g, 'prenez');
		itineraryText = itineraryText.replace(/toward/gi, 'vers');
		itineraryText = itineraryText.replace(/Exit/g, 'Sortie');
		itineraryText = itineraryText.replace(/Arrive/gi, 'Arriv&eacute;e');
		itineraryText = itineraryText.replace(/Bear/gi, 'Continuez');
		itineraryText = itineraryText.replace(/Ramp/gi, 'Bretelle');
		itineraryText = itineraryText.replace(/Depart/gi, 'D&eacute;part');
		itineraryText = itineraryText.replace(/\bContinue\b/gi, 'Continuez');
		itineraryText = itineraryText.replace(/Keep/g, 'Gardez');
		itineraryText = itineraryText.replace(/keep/g, 'gardez');
		itineraryText = itineraryText.replace(/Stay/gi, 'Restez');
		itineraryText = itineraryText.replace(/Start/gi, 'Commencez');
		itineraryText = itineraryText.replace(/\bthe\b/gi, '');
		itineraryText = itineraryText.replace(/\bW\b/gi, ' O ');
		itineraryText = itineraryText.replace(/Hwy/gi, 'Aut');
		itineraryText = itineraryText.replace(/roundabouts/gi, 'carrefours giratoires');
		
		return itineraryText;
	}
    //Move the center of the map
    //Parameters:   deltaX  change in x
    //              deltaY  change in y
    this.Pan = function(deltaX, deltaY)
    {
        if (this.mapInstance != null)
        {
            this.mapInstance.Pan(deltaX, deltaY);
        }
    }
    
    //Set the location of the map center to the given latLong
    //Parameter:    latLong VELatLong
    this.SetCenter = function(latLong)
    {   
        if (this.mapInstance !=null)
        {
            this.mapInstance.SetCenter(latLong);
        }
    }
    
    //Get the location of the map center to the given latLong
    this.GetCenter = function()
    {   
        var center = null;
        if (this.mapInstance !=null)
        {
            center= this.mapInstance.GetCenter();
        }
        return center;
    }
    
    //Get the location of the map center to the given latLong
    this.GetZoomLevel = function()
    {   
        var level = null;
        if (this.mapInstance !=null)
        {
            level= this.mapInstance.GetZoomLevel();
        }
        return level;
    }
        
        
}

//Callback Functions
//probably don't need this as the start and end locations of the GetRoute take address strings as well as
//lat/longs
function onGotFindResults (shapeLayer, findResults, locations, hasMoreResults)
{}

//a dummy function to use if no callback is wanted, same behavior as passing a null to the callback.
function onGotRouteNOP(){}

//handler for GetRoute, displays the results in a table.
//override this to specialize the route display for the different maps. 
/*
function onGotRoute(route)
{
   ____lastRoute = route; */
   /*var  routeinfo="Route info:\n\n";
   routeinfo += "Total distance: ";
   routeinfo += route.Itinerary.Distance+" ";
   routeinfo += route.Itinerary.DistanceUnit+"\n";
   
   var steps="";
   var len = route.Itinerary.Segments.length;
   
   for(var i = 0; i<len ;i++)
   {
      steps += GenerateResults(route,i,len);
   }
  
   routeinfo += "<table>"+steps + "</table>"; */
/*   
   var  routeinfo="";
   var steps="";
   var len = route.Itinerary.Segments.length;
   
   for(var i = 0; i<len ;i++)
   {
      steps += GenerateResults(route,i,len);
   }
   
   routeinfo = steps;
   
   var ourDiv=document.getElementById('drivingDirections');
   
   ourDiv.innerHTML = routeinfo;
   ___lastRoute = route;
} */

//Generates the specific markup for displaying the route directions
/*function GenerateResults(route, stepNumber, totalSteps){
   var results = ""; 
   var styleSwitch = "";
   
   
     
   if (stepNumber % 2 != 0)
   {
       styleSwitch = "2";       
   }
   
   if (totalSteps>0)
   {
        
        if(stepNumber == 0)
        {        
            //create the markup for the header and first row of the table
            results = results + "<tr>";
            results = results + results,"     <td style=\"border-top: 1px solid rgb(255, 226, 28); padding: 10px 0pt;\" colspan=\"2\">";
            results = results + results,"         <table id=\"DrivingDetails\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\">";
            results = results + "             <tbody>";
            results = results + "                 <tr>";
            results = results + "                     <td class=\"directionsCell2\" colspan=\"2\"/>";
            results = results + "                     <td class=\"directionsCell2\" width=\"90%\">";
            results = results + "                         <strong>Directions</strong>";
            results = results + "                     </td>";
            results = results + "                     <td class=\"directionsCell2\" width=\"4%\">";
            results = results + "                         <strong>Map</strong>";
            results = results + "                     </td>";
            results = results + "                 </tr>";         
            results = results + "        <tr>";
            results = results + "            <td class=\"directionsToFromCell\" width=\"4%\">";
            results = results + "                <strong>From</strong>";
            results = results + "            </td>";
            results = results + "            <td class=\"directionsLetterCell\" width=\"2%\">";
            results = results + "                <img width=\"20\" height=\"20\" alt=\"A\" src=\"http://www.yellowpages.ca/images/circA.png\"/>";
            results = results + "            </td>";
            results = results + "            <td class=\"directionsCell\">";
            results = results + ((stepNumber + 1) + ":" + route.Itinerary.Segments[stepNumber].Instruction + " (" + route.Itinerary.Segments[stepNumber].Distance + " " + route.Itinerary.DistanceUnit + ")");
            results = results + "               <div id=\"ddmap" + stepNumber + "\" style=\"width:525px;height:214px; position:relative;\"></div>";              
            results = results + "                <br/>";
            results = results + "                <img height=\"0\" name=\"map" + stepNumber +"\"/>";
            results = results + "            </td>";
            results = results + "            <td class=\"directionsMapLinkCell\">";
            results = results + "                <a id=\"text" + stepNumber + "\" onclick=\"GenerateDDMap(___lastRoute, " + stepNumber + ")\" >Map</a>";
            results = results + "            </td>";
            results = results + "        </tr>";
            
        }
        else if(stepNumber < totalSteps-1)
        {   
            //create the markup of for steps 1 to n-1
            results = results + "        <tr>";
            results = results + "            <td class=\"directionsToFromCell" + styleSwitch + "\">";
            results = results + "                &nbsp;";
            results = results + "            </td>";
            results = results + "            <td class=\"directionsLetterCell" + styleSwitch + "\">";
            results = results + "                &nbsp;";
            results = results + "            </td>";
            results = results + "            <td class=\"directionsCell" + styleSwitch + "\">";
            results = results + ((stepNumber + 1) + ":" + route.Itinerary.Segments[stepNumber].Instruction + " (" + route.Itinerary.Segments[stepNumber].Distance + " " + route.Itinerary.DistanceUnit + ")");
            results = results + "               <div id=\"ddmap" + stepNumber + "\" style=\"width:525px;height:214px; position:relative;\"></div>";              
            results = results + "                <br/>";
            results = results + "                <img height=\"0\" name=\"map" + stepNumber + "\"/>";
            results = results + "            </td>";
            results = results + "            <td class=\"directionsMapLinkCell" + styleSwitch + "\">";
            results = results + "                <a id=\"text" + stepNumber + "\" onclick=\"GenerateDDMap(___lastRoute, " + stepNumber + ")\">Map</a>";
            results = results + "            </td>";
            results = results + "        </tr>";
           
        }
         else if(stepNumber == totalSteps -1)
        {            
            //create the markup for the last step in the directions and insert add summary info
            results = results + "        <tr>";
            results = results + "            <td class=\"directionsToFromCell" + styleSwitch + "\">";
            results = results + "                <strong>To</strong>";
            results = results + "            </td>";
            results = results + "            <td class=\"directionsLetterCell" + styleSwitch + "\">";
            results = results + "                <img width=\"20\" height=\"20\" alt=\"B\" src=\"http://www.yellowpages.ca/images/circB.png\"/>";
            results = results + "            </td>";
            results = results + "            <td class=\"directionsCell" + styleSwitch + "\">";
            results = results + ((stepNumber + 1) + ":" + route.Itinerary.Segments[stepNumber].Instruction + " (" + route.Itinerary.Segments[stepNumber].Distance + " " + route.Itinerary.DistanceUnit + ")");
            results = results + "               <div id=\"ddmap" + stepNumber + "\" style=\"width:525px;height:214px; position:relative;\"></div>";              
            results = results + "            </td>";
            results = results + "            <td class=\"directionsMapLinkCell" + styleSwitch + "\">";
            results = results + "                <a id=\"text" + stepNumber + "\" onclick=\"GenerateDDMap(___lastRoute, " + stepNumber + ")\">Map</a>";
            results = results + "            </td>";
            results = results + "        </tr>";
            results = results + "        <tr>";
            results = results + "            <td class=\"directionsCell\" colspan=\"4\">";
            results = results + "                <strong>Total Estimated Time : </strong>";
            results = results + route.Itinerary.Time;
            results = results + "              <strong>Total Estimated Distance : </strong>";
            results = results + route.Itinerary.Distance + " " + route.Itinerary.DistanceUnit;
            results = results + "            </td>";
            results = results + "         </tr>";
            results = results + "            </tbody>";
            results = results + "        </table>";
            results = results + "   </td>";
            results = results + "</tr>";
            
        }
        
        return results;
    }
    
}*/

//Work around for VE not yet having turn by turn maps.  When VE 6 releases with Maneuver maps
//change this method to utilize that functionality.  Currently it creates a new map and route
//then zooms in and centers on the area of the specific instruction.
//Parameters:   route   VERoute
//              stepNumber  the current step
function GenerateDDMap(route, stepNumber)
{
    var ddMap = new YPGMapControl("ddmap" + stepNumber);
    var legs = route.RouteLegs;
    
     // Get intermediate legs
		for(var i = 0; i < legs.length; i++)
		{
		   // Get this leg so we don't have to derefernce multiple times
		   leg = legs[i];  // Leg is a VERouteLeg object
			
		   // Unroll each intermediate leg
		  	try{
				___lastStepNumber = stepNumber;
				___lastCenter = leg.Itinerary.Items[stepNumber].LatLong;
				ddMap.CreateAndLoadMap(leg.Itinerary.Items[stepNumber].LatLong, 17, VEMapStyle.Road, true, null, false);
				ddMap.HideVEControls();
				___lastMap = ddMap;
				var routeShape = leg.Itinerary.Items[stepNumber].Shape;
				ddMap.AddPushpin(routeShape);

			}catch(ex){
				alert(ex.message);
			}
		}
}

//Opens the Turn By Turn map.
//TODO: fix behaviour
function OpenMapDiv(route)
{
    var stepNumber = ___lastStepNumber;
    var center = route.Itinerary.Segments[stepNumber].LatLong;
    var ddMap = ___lastMap;
    ddMap.SetCenterAndZoom(center, 17);
    var ourDiv = document.getElementById('ddmap' + stepNumber);
    //ourDiv.style.display = "block";
    //ourDiv.style.height = 214;
    var linkElement = document.getElementById('text' + stepNumber);
    linkElement.setAttribute('onclick', "CloseMapDiv(" + stepNumber + ")"); 
}

//Closes the Turn By Turn map.
//TODO: fix this behavior
function CloseMapDiv(stepNumber)
{
    var ourDiv = document.getElementById('ddmap' + stepNumber);
    //ourDiv.style.display = "none";
    //ourDiv.style.height = 0;
    var linkElement = document.getElementById('text' + stepNumber);
    linkElement.setAttribute('onclick', "GenerateDDMap(___lastRoute, " + stepNumber + ")");
}    


//Verifies the browser is compliant.  
IsBrowserVECompliant = function()
{				
	//firefox
	var firefox_index = navigator.userAgent.indexOf(FIREFOX_AGENTID);
	if (firefox_index != -1)
	{			
		var firefox_version = parseFloat(navigator.userAgent.substring(firefox_index + FIREFOX_AGENTID.length));									
		return firefox_version >= 1.5;				
	}
	
	//internet explorer		
	var ie_index = navigator.userAgent.indexOf(IE_AGENTID);
	if (ie_index != -1)
	{			
		var ie_version = parseFloat(navigator.userAgent.substring(ie_index + IE_AGENTID.length)); 				
		return ie_version >= 6;	
	} 
	
	return false;		
 }  
 
 
 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];
}

 
 //Global variables
 var ___lastCenter = null;
 var ___lastRoute = null;  
 var ___lastStepNumber = 0;
 var ___lastMap = null;



function two(x) {return ((x>9)?"":"0")+x}
function three(x) {return ((x>99)?"":"0")+((x>9)?"":"0")+x}

function time(ms) {
var sec = Math.floor(ms/1000)
ms = ms % 1000

var min = Math.floor(sec/60)
sec = sec % 60
t = two(sec) + "sec"

var hr = Math.floor(min/60)
min = min % 60
t = two(min) + "min " + t

var day = Math.floor(hr/60)
hr = hr % 60
hr = two(hr)
if(hr != 00) { t = two(hr) + "h " + t }
if(day != 0) { t = day + "day " + t }

return t
}
