//# expects js2py
//#####################  Added for PathMap
jzGMap=jz.Module() // create a jz Module
with(jzGMap){      // Use name spave dont indent whole file

importFrom(jz,'_ dof mapf addListener removeObjListeners update at Class IE Log getId urlMerge update')

if (window.GUnload) addListener(window,'unload',GUnload)

$.gotostr= function(map,posstr){
	if (!map) return
	var pos=mapf(posstr.split(','),parseFloat)
	var newpos= newLatLng(pos[0],pos[1])
	alert(' new pos ='+newpos)
	map.setCenter(newpos)
	}

$.newPolyline = function(seg,style) {
	style=style||{}
	return new GPolyline(seg,style['color'],style['weight'],style['opacity'])
	}

$.boundsOf= function(a,b){
		//return bounds formed by latlng a and b
		//not the same as GBounds(a,b) because a is not min and b is not max
		//could be:
		//var alalt=a.lat(), blat=b.lat(), alng=a.lng(), blng=b.lng()
		//GBounds( GlatLng( min(alat,blat),min(alng,blng) ), GLatLng( max(alat,blat),max(alng,blng) ) )
		var bnds= new GBounds(a)
		bnds.extend(b)
		return bnds
		}

$.distanceTo= function(p1,p2,c){
		// distance from latlng c to segemnt formed by latlng's p1 and p2
		// from: maps.forum.nu/gm_mouse_dist_to_line.html
		// I know, I know I'm working with degress not pixels ... but it works magnitudes are preserved (in higher zooms)
		var abs= Math.abs, pow=Math.pow
		var p1x=p1.lng(), p1y=p1.lat(), p2x=p2.lng(), p2y=p2.lat(), cx=c.lng(), cy=c.lat()
		if (p2x != p1x) {
				var a= (p2y-p1y)/(p2x-p1x), b= p2y - a*p2x
				var distc= abs(a*cx + b - cy / Math.sqrt(a*a+1))
				}
		else var distc= abs(cx-p2x)
		var seglen2=  pow(p2x-p1x,2) + pow(p2y-p1y,2)
		var distcp22= pow(cx-p2x,2) + pow(cy-p2y,2)
		var distcp12= pow(cx-p1x,2) + pow(cy-p1y,2)
		var distc2=   pow(distc,2)
	}

$.unittxt= function(dst,u){
	if (u &&  u in _units)
	     u= _units[u]
	else u= unitdef
	return (dst/u.unitscale).toFixed(u.unitfixed)+u.unitname
	}

$.unittxtk= function(dst,unit) { return unittxt(dst*1000,unit) }

$._units= {
	km: { unitname:' km', unitscale:1000., unitfixed:1 },
	m:  { unitname:' m',  unitscale:1.,    unitfixed:0 },
	mi: { unitname:' mi', unitscale:1609.344, unitfixed:1 },
	nmi:{ unitname:' nmi',unitscale:1852., unitfixed:1 }
	}

$.setunit= function(unit){

	var newu= _units[unit.toLowerCase()]
	if (newu) {
	    update($,newu)
	    $.unitdef=newu
	    $.unitname= unit.toLowerCase()
	    }
	return newu
	}
setunit('km')

$.timetxt= function(time){
	var hrs= Math.floor(Math.round(time/60.)/60.)
	var mn= Math.round(time/60.)%60
	var hrt= hrs?_((hrs>1)?'$h h':'$h h',{h:hrs}):''
	var mnt= mn ?_((mn>1)?'$m min':'$m min',{m:mn}):''
	return hrt+(hrt?' ':'')+mnt
	},

$.polyPoximity= function(poly,bnds,findclosest){
		if (!bnds.intersects(poly.getbounds())) return false //if bounds dont intersect thers no chance ...

		var l=poly.getVertexCount(),  bof= boundsOf, ct= bnds.getCenter()
		var a=poly.getVertex(0), hit=false
		for (var i=1; i<l; i++){
			b=poly.getVertex(i)
			if (bnds.intersects(bof(a,b))) {
				//could be close enough calc distance to segment
				segbnds=new GBounds(pt)
				segbnds.extend(poly.getVertex(i-1))
				if (bnds.intersects(segbnds)){
					if (!findclosest) return true
					//get distnace to segment 
					if (dst<cdst){
						//update cdst
						}
					}
				}
			a= b
			}
		if (!hit) return false
		return hit
	} 


$.newEPolyline = function(epts,eseg,style,zIndex) {

//         var encodedPoints = "iuowFf{kbMzH}N`IbJb@zBpYzO{dAvfF{LwDyN`_@`NzKqB|Ec@|L}BKmBbCoPjrBeEdy@uJ`Mn@zoAer@bjA~Xz{JczBa]pIps@de@tW}rCdxSwhPl`XgikCl{soA{dLdAaaF~cCyxCk_Aao@jp@kEvnCgoJ`]y[pVguKhCkUflAwrEzKk@yzCv^k@?mI";
//         var encodedLevels = "B????????????????????????????????????B";
//  
//         var encodedPolyline = new GPolyline.fromEncoded({
// 		color: "#3333cc",
// 		weight: 10,
// 		points: encodedPoints,
// 		levels: encodedLevels,
// 		zoomFactor: 32,
// 		numLevels: 4
// 	});
// 	return encodedPolyline



	var style=style||{}
	var style2={
		color	: style['color'],
		weight	: style['weight'],
		opacity	: style['opacity'],
		points	: epts,
		levels	: eseg,
		zoomFactor: 2,
		numLevels:18
		}
	//Log('createin encoded poly with: ')
	//LogObj(style2)
	var ret=GPolyline.fromEncoded(style2)
	//Log('...got ')
	//LogObj(ret)
	//if (zIndex) ret.setZindex(zIndex)
	return ret
	}


$.newEPolygon = function(epts,eseg,style,zIndex) {

	var style=style||{}
	var style2={
		points	: epts,
		levels	: eseg,
		zoomFactor: 2,
		numLevels:18
		}
		
	var style3={
		polylines:[style2],
		color	: style['color'],
		weight	: style['weight'],
		opacity	: style['opacity'],
		fill: true,
		outline: false
		}
	var ret=GPolygon.fromEncoded(style3)
	return ret
	}


$.newPolygon = function (seg,lineStyle,fillStyle) {
	if (seg[0]!=last(seg)) seg.push(seg[0])
	return newPolyline(seg,lineStyle)
	}

$.newMarker = function (coord,ops) {
	//Prepare parametrers
	ops=ops||{}
	if (typeof ops['icon'] == 'string') ops['icon']=MAPIcons[icon]
	var mOps={icon:ops['icon'], 
		clickable:(ops['href'] || ops['click'] || ops['dblclick'] || ops['hoverContent'] || ( ops.icon && ops.icon.hoverImage) ) ? true:false,
		draggable:( ops['dragstart'] || ops['drag'] || ops['dragend'] ||  ops['draggable']) ? true:false
		}
	// always us myhovers if (typeof ops['hoverContent']==='string') mOps['title']=ops['hoverContent']

	//Allocate(create) object
	var marker=new GMarker(coord,mOps)
	if (ops.title) marker.title=ops.title
	//Apply initializations
	if (mOps['draggable']) marker._jzEnableDrag=true //flag to force enable drag after addOverlay
	if ((typeof ops['hoverContent']==='function')||(typeof ops['hoverContent']==='string')|| ( ops.icon && ops.icon.hoverImage)) {
		if ((typeof ops['hoverContent']==='function')||(typeof ops['hoverContent']==='string')) marker.hoverContent=ops['hoverContent']
		if (ops.icon && ops.icon.hoverImage) {
			marker.hoverImage=ops.icon.hoverImage
			marker.nonHoverImage=ops.icon.image
			}
		GEvent.addListener(marker,'mouseover',function(){showHover(marker)})
		GEvent.addListener(marker,'mouseout',function(){hideHover(marker)})
		}
	if (ops['href']) {
		GEvent.addListener(marker,'click',function(pt){doNavigate(marker,pt)})
		marker.href=ops['href']
		}
	marker.getHoverAnchor=marker.getPoint
	if (ops['debug']) {
		marker.debugName=ops['debug']
		var s=''
		for (var key in mOps) if (typeof mOps[key] != 'function') s+=(key+':'+mOps[key]+', ')
		Log('got debug mode for '+marker.debugName+' mops='+s); //rare case where its required
		var s=''
		//jzCleanup(ops)
		for (var key in ops) s+=(key+':'+(typeof ops[key]=='function'?'function':ops[key])+', ');
		Log('and ops='+s); //rare case where its required
		dof(['resize','click','dblclick','contextmenu','mouseover','mouseout','mousedown','mouseup','dragstart','dragend','drag','remove'],function(event){ 
			 GEvent.addListener(marker,event, new Function('Log("'+event+' on "+this.debugName)'))
			})
		}

	if (ops.jz_doRemoved) marker.jz_doRemoved = ops.jz_doRemoved 
	dof(['click','dblclick','dragstart','drag','dragend','mouseover','mouseout','remove'], function(event){
		if (ops[event]) {
			if (ops['debug']) Log('adding '+event+' listener on '+ops['debug'])
			GEvent.addListener(marker,event,ops[event])
			}
		})
		
	return marker
	}

$.getOffsetPos = function(elem){
	//Log('get Offset Pos')
	var x = 0, y = 0, dx,dy
	while (elem) {
		x += (dx=elem.offsetLeft)
		y += (dy=elem.offsetTop)
		//Log('.. dx='+dx+' dy='+dy+' x='+x+' y='+y+' for '+elem+' pos='+elem.position)
		elem = elem.offsetParent
		//Log('..next elem='+elem)
		}
	var ret={x:x, y:y}
	//Log('..returning: '+ret.x,','+ret.y)
	return ret
	}

$.getPos = function(elem){
	//Log('get Pos')
	var x = 0, y = 0, dx,dy
	while (elem) {
		if (dx=elem.style.top)  x+=parseInt(dx)
		if (dy=elem.style.left) y+=dy
		//Log(' .. dx='+dx+' dy='+dy+' x='+x+' y='+y+' pos= '+elem.style.position+' for elem '+elem)
		elem = elem.parentNode
		}
	var ret={x:x, y:y}
	//Log('..returning: '+ret.x+','+ret.y)
	return ret
	}

$.getClientBounds = function(marker){

	if (!mapDiv) return
	var vMap=mapDiv.vMap

	if (marker.bounds_) { // gota rectangle like object
		var c1 = vMap.fromLatLngToContainerPixel(marker.bounds_.getSouthWest());
		var c2 = vMap.fromLatLngToContainerPixel(marker.bounds_.getNorthEast());
		var b = new GBounds([c1,c2])
		//alert('return bounds='+b)
		return b
		}

	if (marker.getPoint) { //Ok got a marker
	
		var markerPos = vMap.fromLatLngToContainerPixel(marker.getPoint())
		var iconSize = marker.getIcon().iconSize
		var iconAnchor = marker.getIcon().iconAnchor
	
		var left  = markerPos.x - iconAnchor.x
		var right = left+iconSize.width
		var top   = markerPos.y - iconAnchor.y
		var bottom= top + iconSize.height
		return new GBounds([new GPoint(left,top),new GPoint(right,bottom)])
		}
	return //Got something undefined
	}

$.MAPIcons={} // Icon registry

$.newIcon = function (name,ops,copyIcon) {
	ops = ops||{}
	if (typeof copyIcon == 'string') copyIcon=MAPIcons[copyIcon]

	var icon = new GIcon(copyIcon)
	var item
	if (item=ops['image']) icon.image=item
	if (item=ops['hoverImage']) icon.hoverImage=item
	if (item=ops['printImage']) icon.printImage=item
	if (item=ops['shadow']) icon.shadow=item
	if (item=ops['iconSize']) icon.iconSize=new GSize(item[0],item[1])
	if (item=ops['shadowSize']) icon.shadowSize=new GSize(item[0],item[1])
	if (item=ops['iconAnchor']) icon.iconAnchor=new GPoint(item[0],item[1])
	if (item=ops['infoWindowAnchor']) icon.infoWindowAnchor=new GPoint(item[0],item[1])
	if (item=ops['imageMap']) icon.imageMap=item
	if (item=ops['transparent']) icon.transparent=item
	if (icon.image) {
		icon.cache=new Image()
		icon.cache
		icon.cache.onload=function(){initIcon(icon)}
		icon.cache.src=icon.image
		}

	if (name && icon) MAPIcons[name]=icon
	return icon
	}

$.initIcon = function(icon) {
	if (!icon.iconSize) icon.iconSize= new GSize(icon.cache.width,icon.cache.height)
	if (!icon.iconAnchor) icon.iconAnchor= new GSize(icon.iconSize.width/2,icon.iconSize.height)
	if (!icon.infoWindowAnchor) icon.infoWindowAnchor= new GSize(icon.iconSize.width/2,0)
	if (!icon.imageMap) {
		var x=icon.iconSize.width, y=icon.iconSize.height
		icon.imageMap = [0,0, x,0, x,y, 0,y, 0,0]
		}
	//alert('imageMap='+icon.imageMap)
	//if (!icon.transparent) icon.transparent=icon.image
	
	icon.cache = null
	}
	
$.newMap = function(elem,ops) { 
	var map=new GMap(elem,ops)
	// patch addOverlay
	map._jzAddOverlay=map.addOverlay
	map.addOverlay=function(ovl) {
		if (ovl && ovl._jzEnableDrag) {
			//alert('doing enable drag patch2')
			var ret=this._jzAddOverlay(ovl)
			delete ovl._jzEnableDrag
			var ret2=ovl.enableDragging()
			}
		else var ret=this._jzAddOverlay(ovl)
		return ret
		}
		
	if (!map.fromLatLngToContainerPixel) {
		map.fromLatLngToContainerPixel  = function(latlng){
			var pos = this.fromLatLngToDivPixel(latlng)
			var pane= this.getPane(G_MAP_MARKER_PANE).parentNode.style
			var offx=parseInt(pane.left)
			var offy=parseInt(pane.top)
			return new GPoint(pos.x+offx, pos.y+offy)
			}
		}

	
	GEvent.addListener(map,'mouseover',function(pos){ map.mousePos = pos })
	GEvent.addListener(map,'mouseout', function(pos){ map.mousePos = false })
	GEvent.addListener(map,'mousemove',function(pos){
		map.mousePos = pos
		if (elem.hoverDiv && elem.hoverDiv.openPos) setHoverPos(pos)
		})
	return map
	}

$.addNavtec = function(map){
	G_NORMAL_MAP.getName = function() { return 'TeleAtlas'}
	map.addMapType(G_NORMAL_MAP)
	map.addMapType(getNavTeq())
	
	copyrights = new GCopyrightCollection('Map data');
	copyrights.addCopyright(new GCopyright('gmaps-navteq',
		newBounds(newLatLng(-90,-180), newLatLng(90,180)),
		0,'©2006 NAVTEQ'))

	var tileset = new GTileLayer(copyrights, 0, 14)
	tileset.getTileUrl = function(tile, zoom){
    		tileServer++;
  		if (tileServer > 3) tileServer = 0
    		return 'http://mt' + tileServer + '.google.com/mt?n=404&v=w2.21&x=' + tile.x + '&y=' + tile.y + '&zoom=' + (17 - zoom) + ''
		}		;
	tileset.isPng = function() { return false }
	tileset.getOpacity = function() { return 1.0 }

	var maptype = new GMapType(
    				[tileset],
    				new GMercatorProjection(14),
    				'NAVTEQ',
				{shortName:'NT',tileSize:256,maxResolution:14,minResolution:0}
				)
	}

$.intersects = function(bounds){ return bounds.contains(this) }

$.newLatLng = function (lat,lng) {
	var ret= new GLatLng(lat,lng)
	ret.intersects = intersects //Of course could also modify the prototype ....
	return ret
	}

$.newBounds = function (includeList) {
	if (!includeList.length) includeList=[includeList]
	var bounds=new GLatLngBounds()
	dof(includeList, function(p){
		// Is P a bounded object
		if (p.getBounds) p=p.getBounds() // Yes then get bounds of object
		//Is P a GLatLng Bounds object
		if (p.getSouthWest) { // Yes then extend with SW and NE corners
			bounds.extend(p.getSouthWest())
			bounds.extend(p.getNorthEast())
			}
		// else assume this is a GLatLng
		else if (p.lat) bounds.extend(p)
		})
	return bounds
 }

$.doNavigate = function(overlay,point) {
	//alert('doNavigate o='+overlay+' p='+point)
	//return doNavigateReq(overlay,point)
	if (overlay && overlay.href){
		//var pos=overlay.href.indexOf('viaexplora.com')
		//alert('pos='+pos+' for '+overlay.href)
		if (mapDiv && (mapDiv.home=='vx') ) return doNewNavigate(overlay,point)
		if (mapDiv && (!mapDiv.iframe) ) return doNavigateReq(overlay,point)
		
		gotohref(overlay,overlay.href)
		}
	//else alert('got donavigate nohref on '+overlay)
	}

$.doNavigateReq = function(overlay,point) {
	//alert('doNavigateReq o='+overlay+' p='+point)
	if (!mapDiv) return
	
	//from plone stuf
	var name=mapDiv.id.slice(0,mapDiv.id.lastIndexOf('.')) //remove ._map
	var reqstr = scanChecksFor(name+'._reqAttrait')
	if (overlay && overlay.href) gotohref(overlay,overlay.href+getHrefArgs())
	//else alert('got donavigate nohref on '+overlay)
	}

$.doNewNavigate = function(overlay,point) {
	//alert('doNewNavigate o='+overlay+' p='+point)
	var newhref= urlMerge(overlay.href)
	//alert('new navidate url='+newhref)
	gotohref(overlay,newhref)
	}


$.doNavigateIndirect = function(rect){//This alows us to change doNavReq after the evnt listener was been set ...
	//alert('doNavigateIndirect o='+overlay+' p='+point)
	doNavigate(rect)
	//panAndZoomTo(rect.bounds_)
	}

$.gotohref= function(overlay,href){
	if (overlay && overlay.hreftarget)
	     window.open(href,overlay.hreftarget[0],overlay.hreftarget[1])
	else top.location=href
	}

// A Rectangle is a simple overlay that outlines a lat/lng bounds on the
// map. It has a border of the given weight and color and can optionally
// have a semi-transparent background color.

$.newRectangle = function (bounds,ops,cls){//Rectangle factory
	ops=ops||{}
	cls=cls||Rectangle
	var rect= cls(bounds,ops['weight'],ops['color'])
	if (ops['hoverContent']) rect.hoverContent = ops.hoverContent
	rect._jzSetZ=Rectangle.currentZIndex++ //new rects always on top
	// apply ops
	return rect
	}

$.Rectangle = Class(GOverlay,{

	jz_init	: function(bounds,opt_weight,opt_color,opt_background,opt_opacity) {
		this.bounds_ = bounds;
		if (typeof opt_weight == 'undefined') opt_weight=2
		this.weight_ = opt_weight 
		this.color_ = opt_color || ""
		if (IE){
			this.background_ = opt_background || "transparent"
			//this.opacity_ = opt_opacity || 0.1
			}
		else {
			this.background_ = opt_background || ""
			this.opacity_ = opt_opacity || 0.2
			}
		},

	currentZIndex : 100000,

	// Creates the DIV representing this rectangle.
	initialize : function(map) {
		// Create the DIV representing our rectangle
		this.map_ = map
		var div = document.createElement("div")
		this.div_ = div
		div.jz_Listeners = []
		if (this.divClass) div.className=this.divClass

		div.style.border = this.weight_ + "px solid " + this.color_;
		if (this.background_) div.style.backgroundColor = this.background_
		if (this.opacity_) {
			div.style.MozOpacity = div.style.khtmlOpacity = div.style.opacity = this.opacity_
			div.style.filter="alpha(opacity="+(100*this.opacity_)+")"
			}
		div.style.position = "absolute"
		div.style.overflow = "hidden"
		
		// 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)
		if (this._jzSetZ) {
			div.style.zIndex=this._jzSetZ
			}
		else div.style.zIndex=GOverlay.getZIndex(this.bounds_.getNorthEast().lat())
		map.getPane(G_MAP_MARKER_SHADOW_PANE).appendChild(div);

		//div.onclick="alert('goa click')"
		this.inithref(map)
		if (this.hoverContent) this.initHover(map)
		},

	inithref : function(map){
		if (this.href){
			var self=this, div=this.div_
			addListener(div,'click',function(e){doNavigateReqIndirect(self)})
			addListener(div,'mouseover',function(e){div.style.borderColor='red';div.style.borderWidth='3px';})
			addListener(div,'mouseout',function(e){div.style.borderColor=self.color_;div.style.borderWidth=self.weight_+'px';})
			}
		},

	initHover : function(map){
		if (!mapDiv) return
		var self=this,div=this.div_
		addListener(div,'mouseover',function(e){showRectHover(self,e)})
		addListener(div,'mouseout',function(){
			hideHover(self)
			//if (mapDiv && mapDiv.hoverDiv) mapDiv.hoverDiv.style.visibility='hidden'
			})
		},

	// Remove the main DIV from the map pane
	remove : function() {
		if (!this.div_) return
		var cnt=removeObjListeners(this.div_)
		this.div_.parentNode.removeChild(this.div_)
		this.div_ = false
		},

	// Copy our data to a new Rectangle
	copy : function() {
		return new Rectangle(this.bounds_, this.weight_, this.color_,this.backgroundColor_, this.opacity_);
		},

	// Redraw the rectangle based on the current projection and zoom level
	redraw : function(force) {
		// We only need to redraw if the coordinate system has changed
		if (!force) return;
		if (!this.div_) return
		
		// Calculate the DIV coordinates of two opposite corners of our bounds to
		// get the size and position of our rectangle
		var c1 = this.map_.fromLatLngToDivPixel(this.bounds_.getSouthWest());
		var c2 = this.map_.fromLatLngToDivPixel(this.bounds_.getNorthEast());
		
		// Now position our DIV based on the DIV coordinates of our bounds
		this.div_.style.width = Math.abs(c2.x - c1.x) + "px";
		this.div_.style.height = Math.abs(c2.y - c1.y) + "px";
		this.div_.style.left = (Math.min(c2.x, c1.x) - this.weight_) + "px";
		this.div_.style.top = (Math.min(c2.y, c1.y) - this.weight_) + "px";
		},

	getHoverAnchor : function(){return newLatLng( this.bounds_.getSouthWest().lng(), this.bounds_.getNorthEast().lat())}, //remember newlatlng inverts lat and lng

	//Get bounds of rectangle (read only)
	getBounds : function (){return this.bounds_} ,// { return newBounds(this.bounds_) }

	removeable : function (){return true}
	
	})//end Rectangle class def

$.FocusRectStyle =  { opacity:.3,    color:'#ff00ff', weight:8 }
$.FocusZoneStyle =  { opacity:.3,    color:'#0000ff', weight:8 }
$.FocusRectangle = Class(Rectangle,{

	divClass : 'jz-focusrect',

	_mouseDownTime : new Date,
	inithref : function(map){
		var self=this, div=this.div_
		if (this.href){
			addListener(div, 'mousedown', function(e){self._mouseDownTime = new Date})
			addListener(div, 'click',     function(e){if (((new Date)-self._mouseDownTime)<500) doNavigateIndirect(self)})//Ignore drags or slow clicks ...
			}
		addListener(div, 'mouseover', function(e){self.doShowFocus()})
		addListener(div, 'mouseout',  function(e){self.doHideFocus()})
		},
	doShowFocus : function(){
		if (!mapDiv) return
		if (mapDiv.home=='vx' && IE && IE>=7.) return //patch ie hover bug ...
		if (this.overlays) { dof(this.overlays,function(ovl){mapDiv.vMap.addOverlay(ovl)}); return }
		if (!this.path ) return
		//Create overlay
		this.overlays=mapf(this.path.eoverlays, function(ovl){ return newEPolyline(ovl[0],ovl[1],FocusRectStyle)})
		dof(this.overlays,function(ovl){mapDiv.vMap.addOverlay(ovl)})
		},
	doShowFocusNew : function(){
		if (!mapDiv) return
		if (!this.path ) return
		//Create overlay
		dof(this.path.overlayCache,function(ovl){
			var oldstyle
			if (!ovl.jz_oldStyle) oldstyle=ovl.jz_oldStyle={}  
			dof(FocusRectStyle,function(val,key){
				if (oldstyle) oldstyle[key]=ovl[key]
				ovl[key]=val
				})
			ovl.redraw(true)
			})
		},

	doHideFocus : function(){
		if (!mapDiv) return
		if (this.overlays) { dof(this.overlays,function(ovl){mapDiv.vMap.removeOverlay(ovl)}); return }
		this.overlays=false
		},

	doHideFocusNew : function(){
		if (!mapDiv) return
		if (!this.path ) return
		//Create overlay
		dof(this.path.overlayCache,function(ovl){
			if (!ovl.jz_oldStyle) return //continue
			update(ovl,ovl.jz_oldStyle)
			delete ovl.jz_oldStyle
			ovl.redraw(true)
			})
		}
	})//End Focus Rectangle class

$.newFocusRectangle = function(bounds,ops){ return newRectangle(bounds,ops,FocusRectangle) }


$.jzControl = Class(new GControl(true,false),{ //Rectangle Class
	jz_init : function(innerHtml,style,pos){
		if (innerHtml)	this.html=innerHtml
		if (style)	this.style=style
		if (pos)	this.pos=pos
		},

	// Creates the DIV representing this rectangle.
	initialize : function(map) {
		// Create the DIV representing our rectangle
		this.map_ = map
		var div = document.createElement("div")
		div.className='jz'
		div.map= map
		update(div.style,this.style)
		div.innerHTML=this.html
		this.div_ = div;
		map.getContainer().appendChild(div)
		return div
		},

	pos : new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(10,10)),
	// Remove the main DIV from the map pane
	//Control.prototype.printable = function() { Log('in printable'); return true }
	//Control.prototype.selectable = function() { Log('in selectable'); return true }

	// Copy our data to a new Rectangle
	getDefaultPosition : function(){ return  this.pos }
	})

$._CopyrightText = 'Sentiers de motoneige &copy; Gouvernement du Québec'
$._CopyrightText_en = 'Snowmobile trails &copy; Gouvernement du Québec'
$.CopyrightControl = Class(jzControl(
	'<span style="font:8pt sans-serif; letter-spacing:-1px;">'+_CopyrightText+'</span>',
	{},new GControlPosition(G_ANCHOR_BOTTOM_RIGHT,new GSize(5,15))
	))
$.CopyrightControl_en = Class(CopyrightControl('<span style="font:8pt sans-serif; letter-spacing:-1px;">'+_CopyrightText_en+'</span>'))

$.Copyright2Control = Class(jzControl(
	'<span style="font:8pt sans-serif; letter-spacing:-1px;">'+_CopyrightText+'</span>',
	{},new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(125,15) )
	))
$.Copyright2Control_en = Class(Copyright2Control('<span style="font:8pt sans-serif; letter-spacing:-1px;">'+_CopyrightText_en+'</span>'))

$.LogoControl = Class(jzControl(
	'<a href="http://www.ViaExplora.com" onclick="top.location=this.href" ><img src="/static/image/logosml.gif" style="height:49px ; width:150px; border:0px" /></a>',
	{},new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(80,10))
	))

$.SmllogoControl = Class(jzControl(
	'<a href="http://www.ViaExplora.com" onclick="top.location=this.href" ><img src="/static/image/logovsml.gif" style="height:25px ; width75px; border:0px" /></a>',
	{},new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(5,5))
	))

$.Smllogo2Control = Class(jzControl(
	'<a href="http://www.ViaExplora.com" onclick="top.location=this.href" ><img src="/static/image/logovsml.gif" style="height:25px ; width75px; border:0px" /></a>',
	{},new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(45,5))
	))


$.MessageControl = Class(jzControl(
	'<div id="MessageControlElem" style="visibility:hidden; font:9pt sans-serif; color:black;  background:white; border:1px solid black; padding: 1px"></div>',
	{},new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(235,25))
	))

$.dirctrlhtml=_('\
	 <div id="DirectionsControl" style=" font:9pt sans-serif; color:black;  background:url(/static/image/50white.png); padding: 1px; border: 1px solid grey">\n\
		 <input type="checkbox" id="DirectionsControl.check" checked="true" \n\
			 onclick="jzGMap.dodirectionscontrolchange(this.parentNode.parentNode,this.checked)">$dirctrltext</input>\n\
		 </div>',{dirctrltext:_('dirctrltext')})

//alert('dirctrlhtml='+dirctrlhtml)
$.DirectionsControl = Class(jzControl(dirctrlhtml,
	{},new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(80,60))
	),{ 
	initialize : function(map) {
		var ret= jzControl.prototype.initialize.call(this,map) //eh super cls ...
		dodirectionscontrolchange(this.div_,getId('DirectionsControl.check').checked,' init control')
		return ret
		}
	})

$.dodirectionscontrolchange= function(ctrldiv,checked,caller){
	//var ctrldiv= ctrl.parentNode.parentNode
	caller=caller?caller:'no caller'
	//alert(' in dir ctl change fom '+caller+' div='+ctrldiv+' map='+ctrldiv.map+' router='+(ctrldiv.map?ctrldiv.map.router:'nomap')+' checked='+checked)
	var map= ctrldiv.map
	if (!map) return //setup is not finished
	var router=map.router
	var elem= getId('mappane_container')
	var dirdiv= getId('directions')
	//alert('dirdiv='+dirdiv)
	if (checked) {
		if (elem && jz.vsplitRestoreRight) jz.vsplitRestoreRight('mappane')
		else if (dirdiv) dirdiv.style.display='block'
		if (router) router.show()
		}
	else {
		if (elem && jz.vsplitMaxRight) jz.vsplitMaxRight('mappane')
		else if (dirdiv) dirdiv.style.display='none'
		if (router) router.hide()
		}
	map.checkResize()		
	}

$.Legend1Control = Class(jzControl(_('\
	 <div id="Legend1ControlElem" style="font:7pt sans-serif; color:black;  background:url(/static/image/50white.png); border:1px solid black; padding: 1px; width:11em;height:3em; margin-bottom:0.5em">\n\
		<div class="LegendBlock">\n\
			<div class="LegendElem" style="border-color:#00ff00; clear:both" ></div>$PisteCyclable</div>\n\
		<div class="LegendBlock">\n\
			<div class="LegendElem" style="border-color:#4040ff;" ></div>$CircuitRoutier</div>\n\
	    </div>',{PisteCyclable:_('PisteCyclable'), CircuitRoutier:_('CircuitRoutier')} ),
	{},new GControlPosition(G_ANCHOR_BOTTOM_LEFT, new GSize(5,35))
	))

//		<div class="LegendBlock">\n\
//			<div class="LegendElem" style="border-color:#20A0B0;" ></div>$Hybride</div>\n\
//  ,Hybride:_('Hybride')

$.Legend2Control = Class(jzControl(
	'<div id="Legend1ControlElem" style="font-family:Arial, Helvetica, sans-serif; font-size:7pt; color:black;  background:url(/static/image/75white.png);  border:1px solid black; padding: 1px; width:13em;height:14em; margin-bottom:0.5em">'+
		'<div><b>'+_('Piste-cyclable')+'</b></div>'+
			'<div class="LegendBlock"><div class="LegendElem" style="border-color:#008000;" ></div>'+_('Asphaltée')+'</div>'+
			'<div class="LegendBlock"><div class="LegendElem" style="border-color:#00ff00;" ></div>'+_('Poussière de pierre')+'</div>'+
		//'<div class="lgndE" >'+
		//	'<div class="lgndB" style="background:#000000;" ></div>'+
		//	'Projet</div>'+

		'<div><b>'+_('Balisée sur route')+'</b></div>'+
			'<div class="LegendBlock"><div class="LegendElem" style="border-color:#8080ff;margin-bottom:1.2em" ></div>'+_('Chaussée désignée asphaltée')+'</div>'+
			'<div class="LegendBlock"><div class="LegendElem" style="border-color:#00ff80;" ></div>'+_('Bande cyclable')+'</div>'+
			'<div class="LegendBlock"><div class="LegendElem" style="border-color:#ffa020;" ></div>'+_('Accotement asphalté')+'</div>'+
		//'<div class class="LegendBlock"="lgndE">'+
		//	'<div class="lgndB" style="background:#000000;" ></div>'+
		//	'Projet</div>'+

		'<div><b>'+_('Non balisée sur route')+'</b></div>'+
			'<div class="LegendBlock"><div class="LegendElem" style="border-color:#808080;" ></div>'+_('Chaussée pavée')+'</div>'+
			'<div class="LegendBlock"><div class="LegendElem" style="border-color:#b07040;"></div>'+_('Chaussée non pavée')+'</div>'+
		//'<div><b>'+_('Autres')+'</b></div>'+
		//'<div class="lgndE" >'+
		//	'<div class="lgndB" style="background:#ff8000;" ></div>'+
		//	'Navette terrestre</div>'+
		//'<div class="lgndE">'+
		//	'<div class="lgndB" style="background:#ffff00;" ></div>'+
		//	'Navette fluviale</div>'+
		//	'<div class="LegendBlock"><div class="LegendElem" style="border-color:#ff80ff;" ></div>'+_('Train')+'</div>'+
	'</div>',
	{},new GControlPosition(G_ANCHOR_BOTTOM_LEFT, new GSize(5,35))
	))
	
$.Legend3Control = Class(jzControl(_('\
	 <div id="Legend1ControlElem" style="font:7pt sans-serif; color:black;  background:url(/static/image/50white.png); border:1px solid black; padding: 1px; width:10em;height:4em; margin-bottom:0.5em">\n\
		<div class="LegendBlock">\n\
			<div class="LegendElem" style="border-color:#8080ff;" ></div>$transQuebec</div>\n\
		<div class="LegendBlock">\n\
			<div class="LegendElem" style="border-color:#00ff00; clear:both" ></div>$regional</div>\n\
		<div class="LegendBlock">\n\
			<div class="LegendElem" style="border-color:#ff8000;" ></div>$local</div>\n\
	    </div>',{transQuebec:_('PMN-TransQuebec'), regional:_('PMN-Regional'), local:_('PMN-local')} ),
	{},new GControlPosition(G_ANCHOR_BOTTOM_LEFT, new GSize(60,35))
	))


$.mCalcDistance = function(p1,p2) { // Calculate ditance between point p1 and p2(both GPoints)  
	var pi=Math.PI,earthRadious=6378.137,p1RLat,p2RLat,p1RLng,p2RLng //6378137 was 6366.707
	p1RLat=  pi*(90-p1.lat())/180
	p2RLat=  pi*(90-p2.lat())/180
	p1RLng= pi*((360+p1.lng()) % 360)/180
	p2RLng= pi*((360+p2.lng()) % 360)/180

	var x1,y1,z1,x2,y2,z2
	x1 = Math.cos(p1RLng)*Math.sin(p1RLat)
	y1 = Math.sin(p1RLng)*Math.sin(p1RLat)
	z1 = Math.cos(p1RLat)
	
	x2 = Math.cos(p2RLng)*Math.sin(p2RLat)
	y2 = Math.sin(p2RLng)*Math.sin(p2RLat)
	z2 = Math.cos(p2RLat) // could cor
	
	var gc = earthRadious*Math.acos((2-((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2)))/2)
	
	return gc
   	}

$.distance = function(pts,toIdx){
	if (toIdx === undefined) toIdx=pts.length-1
	if (!pts._distances) {
		var distances=mapf(pts.length,function(v,i,l){
			if (!i) return 0
			return l+mCalcDistance(at(pts,i-1),at(pts,i))
			})
		distances.end   = distances[distances.length-1]
		distances.start = distances[0] //should be zero
		pts._distances  = distances
		}
	return pts._distances[toIdx]
	}
} //end jzGMap name space

