(function($) {
	var MapLIB = window.MapLIB = window.i$ = function() {

		var map = null;
		var LangType = {
			ENG: '0',	// English 
			ES: '1'		// Spanish
		};
		
		// global variables IN MapLIB
		var vars = {
		};

		// extended options which are used in programs
		var options = {};
		
		// default options which is not changed by parameter passed by users
		var defaults = {
			mapId: "map",
			listingContainerId: "listing_container",
			centerLat: 0,
			centerLng: 0,
			zoom: 15,
			mapLeftOffset: 320,
			mapStyle: VEMapStyle.Road,
			mapMode: VEMapMode.Mode2D,
			streetScene:true,
			distanceUnit: "K",
			defaultDashboard: true,
			lang: LangType.ENG,
			resizeCallback:null,
			isReverseLookup:false
		};

		// message object by language
		var Message = {
			loading 	: ["Loading", "Cargando"],
			streetScene : ["Street Scene", "infocalle"],
			moveRefresh : ["Move & Refresh", "Mover y Actualizar"],
			moreWebcams : ["More Webcams", "Plus de Webcams"],
			birdseye 	: ["Bird's eye", "Bird's eye"]
		};

		var getMessage = function(name) {
			return Message[name][this.defaults.lang];
		};

		var prevMapStyle = VEMapStyle.Road;

		var setSizeOfInitMap = function(mapId, leftOffset, listingContainerId) {
			var minHeight = 500;
			var minStreetSceneHeight = 200;
			var minWidth = 500;
			var mapLeftOffset = leftOffset; // this offset is fixed otherwise it is very hard to adjust the left offset of the map div.
			var clHeight = $(window).height();

			var topOffset;
			var mapTop = $("#"+mapId).offset().top;

			var newHeight = Math.max(minHeight, clHeight - mapTop - 100);

			// check if there is box ad
			if($("#_boxad_").length != 0) {
				newWidth = Math.max(minWidth, $(window).width() - mapLeftOffset - 135); // 135 is size of box ad
			} 
			else {
				newWidth = Math.max(minWidth, $(window).width() - mapLeftOffset - 3);
			}
			
			newWidth = $.browser.safari ? newWidth-20: newWidth;

			$("#"+mapId).width(newWidth).height(newHeight);
			$("#"+listingContainerId).height(newHeight);
		};

		// initialize map
		var init = function(opts) {
			var options = $.extend(defaults, opts);

			// get init size of map
			if(options.mapLeftOffset >= 0)
				setSizeOfInitMap(options.mapId, options.mapLeftOffset, options.listingContainerId);

			map = new VEMap(options.mapId);
			// _CAN_BING_TOKEN_ is defined in header.jsp and directions_print.jsp
			map.SetClientToken(_CAN_BING_TOKEN_);
			
			if(options.onMapLoad != null) {
				map.onLoadMap = options.onMapLoad(map);
			}
			map.LoadMap();
			
			map.SetMapStyle(options.mapStyle);
			map.SetMapMode(options.mapMode);
			map.SetCenterAndZoom(new VELatLong(options.centerLat, options.centerLng), options.zoom);
			map.SetScaleBarDistanceUnit(options.distanceUnit == "K" ? VEDistanceUnit.Kilometers : VEDistanceUnit.Miles);
			
			map.SetMouseWheelZoomToCenter(true);

		    if(options.resizeCallback != null) {
				this.vars.prevSize = getWindowSize();
		    }

		    map.AttachEvent('onchangemapstyle', changeMapStyleHandler);
		    map.AttachEvent("onmousewheel", function(){return true;}); // disable zoom by mouse wheel

			$('.MSVE_Dashboard, .MSVE_Dashboard_V6')
			 .mouseover(function(){	
				 if(map.GetMapMode() == VEMapMode.Mode3D)
				     $('.customBtn').css('opacity', 1);		// in 3D, it becomes 1
				 else
					 $('.customBtn').css('opacity', 0.9);
			 })
			 .mouseout(function(){ 
				 if(map.GetMapMode() == VEMapMode.Mode3D)
				     $('.customBtn').css('opacity', 1);					 
				 else
					 $('.customBtn').css('opacity', 0.7); 
			 });

			// customized map tiles don't work in 3D mode
			if(options.streetScene) {
				// if use HideTileLayer, when the button is clicked quickly, 3D won't work properly.
				$('#MSVE_navAction_View3DMapMode')
				 .mouseover(function(){ 
					 if(map.GetMapMode() == VEMapMode.Mode2D && typeof mjStreetView !== 'undefined' && 
							 // M : maplisting page, D : detail page
							 (mjStreetView.options.pageType == 'M' || mjStreetView.options.pageType == 'D') && 
							 !mjStreetView.isStreetView)
						 map.DeleteTileLayer("canpages_mj"); 
				 })
				 .mouseout(function(){
					 if(map.GetMapMode() == VEMapMode.Mode2D && typeof mjStreetView !== 'undefined' && 
							 (mjStreetView.options.pageType == 'M' || mjStreetView.options.pageType == 'D') &&
							 !mjStreetView.isStreetView)
						 mjStreetView.showTile(0); 					 
				 });

				$('#MSVE_navAction_FlatlandMapMode')
				 .click(function(){
					 if(typeof mjStreetView !== 'undefined' && !mjStreetView.isStreetView) {
						 // download the tiles
						 mjStreetView.showTile(0);
						 // it takes a time to download tiles
						 setTimeout(function() { MapLIB.streetSceneButton(); }, 1000);
					 }
				});
			}
			
			// for now, 3D mode is disabled
			$('#MSVE_navAction_FlatlandMapMode').css('display', 'none');
			$('#MSVE_navAction_View3DMapMode').css('display','none');
			
			$('#MSVE_navAction_showLabels').css('display','none');
			$('#MSVE_navAction_separator0, #MSVE_navAction_separator2, #MSVE_navAction_separator3').css('display','none');
			$('#MSVE_navAction_container').css('width', '260px');
			$('#MSVE_navAction_toggleGlyphWrapper').css('display','none');

			if(options.resizeCallback != null)
				setTimeout(function(){	window.onresize = options.resizeCallback; }, 300);

			//map.SetShapesAccuracy(VEShapeAccuracy.Pushpin);

			// -------------------------- add customized zoom bar
			$('<div id="ZoomBar_Background" class="customBtn" ></div>')
			 .setCustomButton({
			 	style: {top:0, left:0, width:"30px", height:"300px", 'background-color':"#235087", opacity:0.7}
			});

			var html = "";
			html += "<img style='position:relative;top:70px;left:7px;cursor:pointer;' src='/images/plus.gif' onclick='MapLIB.getMapInstance().ZoomIn();'/>";
			for(var i = 19; i >= 1; i--) {
				var zoomImage = "/images/zoomstep_off.gif";
				if(i == map.GetZoomLevel())
					zoomImage = "/images/zoomstep_on.gif";

				//html += "<img id='zoomScale" + i +"' style='position:relative;top:"+ (72 + (20-i)) + "px;left:6px;cursor:pointer;' src='"+ zoomImage +"' onclick='map.SetZoomLevel("+ i +");' onmouseover='MapLIB.ZoomBarOnMouseOverImage(this);' onmouseout='MapLIB.ZoomBarOnMouseOutImage(this);' />";
				html += "<img id='zoomScale" + i +"' style='position:relative;top:"+ (72 + (20-i)) + "px;left:6px;cursor:pointer;' src='"+ zoomImage +"' onclick='MapLIB.getMapInstance().SetZoomLevel("+ (i ) +");' onmouseover='this.src=\"/images/zoomstep_on.gif\"' onmouseout='MapLIB.ZoomBarOnMouseOutImage(this);' />";
			}
			html += "<img style='position:relative;top:93px;left:6px;cursor:pointer;' src='/images/minus.gif' onclick='MapLIB.getMapInstance().ZoomOut();'/>";

			$('<div id="ZoomBar_Main">'+ html +'</div>')
			 .setCustomButton( {style: {top:0, left:0, width:"30px", height:"300px", 'background-color':""} });		     

			$('#ZoomBar_Background').css('zIndex',80);
			$('#MSVE_navAction_leftBar').css('display', 'none');
			$('#MSVE_navAction_leftBackground').css('display', 'none');
			// --------------------------------------------------------

			// it should be placed at the end of this function
			if(!options.defaultDashboard) {
				map.HideDashboard();		// hide default hash board
				hideCustomZoomBar();
			}

			return map;
		};

		var ZoomBarOnMouseOverImage = function(image) {
			image.src = "/images/zoomstep_on.gif";
		};		
		
		var ZoomBarOnMouseOutImage = function(image) {
			var ZoomLevel = parseInt(image.id.substring(9));
			if(map.GetZoomLevel() == ZoomLevel)
				image.src = "/images/zoomstep_on.gif";
			else
				image.src = "/images/zoomstep_off.gif";
		};

		var getMapInstance = function() {
			return map;
		};

		var hideStreetSceneButton = function() {
			$('#btnStreetScene').css('display','none');
		};
		var showStreetSceneButton = function() {
			$('#btnStreetScene').css('display','block');
		};

		var Button = {
			that:this,
			streetScene : function() {
	 			mjStreetView.toggleView();

	 			// toggle check box image
	 			if(mjStreetView.isStreetView) {
	 			    mjStreetView.showTile(0.6);
	 				$(this).find('img').css('display', 'block');

	 				// in streetview mode, 3D and Birds eye view button are hidden
	 				//$("#MSVE_navAction_View3DMapMode").css('display','none')
	 				$("#MSVE_navAction_ObliqueMapView").css('display','none')
	 				$("#MSVE_navAction_container").css('width','190px');
	 				
	 				// in detail page, there is no move&refresh button
	 				if($("#btnMoveRefresh").length != 0) {
	 					var px = MapLIB.defaults.lang == MapLIB.LangType.ENG ? '280px' : '310px';
	 					
		 				$("#btnMoveRefresh").css('left','190px');
		 				$("#btnStreetScene").css('left', px);
	 				} 
	 				else
	 					$("#btnStreetScene").css('left','190px');
	 			}
	 			else {
	 				mjStreetView.showTile(0);
	 				$(this).find('img').css('display', 'none');

	 				//$("#MSVE_navAction_View3DMapMode").css('display','block')
	 				$("#MSVE_navAction_ObliqueMapView").css('display','block')
	 				$("#MSVE_navAction_container").css('width','260px');
	 				
	 				if($("#btnMoveRefresh").length != 0) {
	 					var px = MapLIB.defaults.lang == MapLIB.LangType.ENG ? '350px' : '380px';
	 					
		 				$("#btnMoveRefresh").css('left','260px');
		 				$("#btnStreetScene").css('left', px);
	 				}
	 				else
	 					$("#btnStreetScene").css('left','260px');
	 			}
	 			$('#btnBirdseye').find('img').css('display', 'none');

	 			return false;
			},

			moveRefresh: function(e) {
				if(iMap.isRefreshMapOn) {
					$(this).find('img').css('display', 'none');//.end().find('div').css('fontWeight','normal');
					iMap.isRefreshMapOn = false;
				}
				else {
					$(this).find('img').css('display', 'block');//.end().find('div').css('fontWeight','bold');
					iMap.isRefreshMapOn = true;
				}

				return false;
			},

			moreWebcams: function() {
				if(Webcam.isMoreWebcamsOn) { // more camera checkbox
					Webcam.setMoreCameras('F');
					$(this).find('img').css('display', 'none').end().find('div').css('fontWeight','normal');
				}
				else {
					Webcam.setMoreCameras('T');
					$(this).find('img').css('display', 'block').end().find('div').css('fontWeight','bold');
				}
			},

			mapMode: function() {
	 			if(map.GetMapMode() == VEMapMode.Mode2D) {
	 				map.ShowDashboard();
	 				map.SetMapMode(VEMapMode.Mode3D);
	 			}
	 			else
	 				map.SetMapMode(VEMapMode.Mode2D);
	 			
	 			if(map.GetMapStyle() == VEMapStyle.Aerial)
	 				$('#btnMap').html(Message.road);
	 			else
	 				$('#btnMap').html(Message.aerial);
	 			
	 			$('#btnBirdseye').find('img').css('display', 'none');
			},
			
			mapStyle: function() {
		 		if(prevMapStyle == VEMapStyle.Road) {
		 			map.SetMapStyle(VEMapStyle.Hybrid);
		 			$(this).html(Message.road);
		 			prevMapStyle = VEMapStyle.Hybrid;
		 		} 
		 		else {
		 			map.SetMapStyle(VEMapStyle.Road);
		 			$(this).html(Message.aerial);
		 			prevMapStyle = VEMapStyle.Road;
		 		}
		 		
		 		$('#btnBirdseye').find('img').css('display', 'none');
			},
			
			birdseye: function() {
				if(map.GetMapStyle() != VEMapStyle.BirdseyeHybrid) {
		 			map.SetMapStyle(VEMapStyle.BirdseyeHybrid);
		 			$(this).find('img').css("display","block");
	
		 			if(prevMapStyle == VEMapStyle.Road) {
		 				$('#btnMap').html(Message.road);
		 				prevMapStyle = VEMapStyle.Hybrid;
		 			}
		 			else {
		 				$('#btnMap').html(Message.aerial);
		 				prevMapStyle = VEMapStyle.Road;
		 			}
			 	 }
			},
			
			zoomIn: function() {
				map.ZoomIn();
			},
			
			zoomOut: function() {
				map.ZoomOut();
			}
		};
		
		var addPolygon = function(opts) {
			var defaults = {
				id:"",
				type:"",
				points:[],	
				lineColor: {R:0, G:0, B:255, opacity: 1},
				fillColor: {R:255,G:255,B:255, opacity: 0},
				lineWidth: 1,
				zIndex: 30
			};
			
			var options = $.extend({}, defaults, opts);

			var polygon = new VEShape(VEShapeType.Polygon, options.points);
			polygon.HideIcon();
			polygon.SetLineColor(new VEColor(options.lineColor.R,options.lineColor.G,options.lineColor.B,options.lineColor.opacity));
			polygon.SetFillColor(new VEColor(options.lineColor.R,options.lineColor.G,options.lineColor.B,options.lineColor.opacity));
			polygon.SetLineWidth(options.lineWidth);
			polygon.SetZIndex(options.zIndex);

			map.AddShape(polygon);
			polygon._can_id = options.id;
			polygon._can_type = options.type;

			return polygon;			
		};

		var addPushpin = function(opts) {
			var defaults = {
				id:"",	// default id
				type:"",
				lat:0,
				lng:0,
				pinHTML: "",
				pinIMG: "",
				offsetX: 10,
				offsetY: -20,
				beakOffsetX:0,
				beakOffsetY:0,
				title:null,
				desc:null,
				zIndex:1000,
				params:null,
				addShapeFlag:true,
				clearInfoBoxStyles:false
			};

			var options = $.extend({}, defaults, opts);
			var point = (options.lat==0||options.lat==null) ? map.GetCenter(): new VELatLong(options.lat, options.lng);

			var shape = new VEShape(VEShapeType.Pushpin, point);
			//shape.SetCustomIcon(options.pinHTML);
			var spec = new VECustomIconSpecification();

			spec.CustomHTML = options.pinHTML;		// it works for 2D
			spec.Image = options.pinIMG;			// it works for 3D
			spec.ImageOffset = new VEPixel(options.offsetX, options.offsetY);// it works for 3D
			shape.SetCustomIcon(spec);
			shape.SetZIndex(options.zIndex);

			if(options.desc != null) {
				shape.SetTitle(options.title);
				shape.SetDescription(options.desc);
			}

			if(options.viewPoint)
				shape._can_viewPoint = options.viewPoint;

			if(options.clearInfoBoxStyles)
				map.ClearInfoBoxStyles();

			if(options.addShapeFlag)
				map.AddShape(shape);

			if(options.params != null)
				shape._can_params = options.params;

			shape._can_id = options.id;
			shape._can_type = options.type;
			shape._can_beakOffsetX = options.beakOffsetX;
			shape._can_beakOffsetY = options.beakOffsetY;

			return shape;
		};

		var addArrayOfShapes = function(shapes) {
			map.AddShape(shapes);
		};		

		var updatePushpin = function(opts) {
			var defaults = {
					shape:"",
					lat:0,
					lng:0,					
					pinHTML: "",
					pinIMG: "",
					zIndex: 1001
				};
			var options = $.extend({}, defaults, opts);

		    options.shape.SetPoints([new VELatLong(options.lat, options.lng)]);
		    options.shape.SetCustomIcon(options.pinHTML);
		    options.shape.SetZIndex(options.zIndex);
		};

		// to fix transparency issue in IE6
		var FixTiles = function() {
		    $('.MSVE_ImageTile').each(function() {
		    	// opacity=60 : don't change the value.
		    	// it is set to 0.6 as switched street scene view to normal map view
		    	if(this.style.filter != null && this.style.filter.match("opacity=60") == "opacity=60")
		    		this.style.filter = this.style.filter.substring(0, this.style.filter.length - 20);
		    });

		    setTimeout("MapLIB.FixTiles()", 500);
		};

		var isThereBlueDots = function() {
			var $ = jQuery;
			var isThereBlueDots = false;

			$('.MSVE_ImageTile, .msve_canpages_mj_tile').each(function() {
				if(this.className == 'MSVE_ImageTile msve_canpages_mj_tile')
					isThereBlueDots = true;
				// it is to detect blue dots in IE6 which doesn't have the tile name 'msve_canpages_mj_tile'.
				// in IE6 the value is null, in IE7 is ""(empty string)
				else if(typeof this.style !== 'undefined' && this.style.filter != "" && this.style.filter != null)
					isThereBlueDots = true;
			});

			return isThereBlueDots;
		};

		var getWindowSize = function() {
			return {width:jQuery(window).width() , height: jQuery(window).height()};
		};

		var removeInfoBox = function() {
			//if($('#CAN_infobox_exit').length != 0) {
			try {
				$('.CAN_infobox_grp').each(function(){
					var me = $(this).get(0);
					me.parentNode.removeChild(me);
				})
				.removeShadow();
			} catch(e) {
				
			}
			//}
		};

		// make customized infobox
		var showInfoBox = function(shape, event) {
			var $ = jQuery;
			var beakX, beakY, pixel;
			// default beak width
			// for now, its real width is 29. 
			// But if it is defined as 29, infobox is not displayed properly.
			var beakWidth = 40;
			// default beak height
			var beakHeight = 36;
			// default padding of infobox
			var infoboxPadding = 10;
			var points = shape.GetPoints();
			var type = shape._can_type;
			
			removeInfoBox();

			if(type == 'H-PIN' || type.indexOf('WEBCAMS') >= 0) {
				pixel = map.LatLongToPixel(points[0]);

				// put infobox body width pixels of center points of pin
				$('<div id="CAN_infobox" class="CAN_infobox_grp">' +
						'<div style="text-align:right">' +
						'<img id="CAN_infobox_exit" height="13px" width="14px" src="/images/exit.png" border="0" />' +
						'</div><div id="CAN_infobox_body"></div></div>')
				 .css({display:'none',
					   position:'absolute',
					   top: 0,		// temporally attached to here 
					   left: 0,		// temporally attached to here
					   padding:infoboxPadding+'px',
					   color:'#676767',
					   'font-size':'11px',
					   'background-color':'#FFFFFF',
					   border:'1px solid #999999',
					   zIndex:501})
				 .find('#CAN_infobox_body')
				 .html(shape.GetDescription())	// insert webcam html
				 .end()
				 // it should be appended to not map but body.
				 // if it is attacehd to map, in some cases, calculation for height of infobox is not correct.
				 // for now(June 24,2009), this bug is shown with IE6, IE7 and FF3
				 .appendTo('body');
			     //.appendTo('#'+this.defaults.mapId); // it is ok with IE8

				// adjust with offset value of pushpin which is size of 12x32.
				// by default beakX and beakY are located at the center of shape and move with offset values
				beakX = parseInt(pixel.x + shape._can_beakOffsetX);
				beakY = parseInt(pixel.y - shape._can_beakOffsetY);

				var infoboxTop = parseInt(pixel.y-$('#CAN_infobox').height()-(infoboxPadding*2)-shape._can_beakOffsetY-beakHeight);
				var infoboxLeft = beakX-parseInt($('#CAN_infobox').width()/2)-(beakWidth/2);
				var infoboxRight = parseInt(beakX + ($('#CAN_infobox').width()/2));

				//alert('beakX : '+beakX + '== beakY : ' + beakY + ' info left : ' + infoboxLeft + ' - info right : ' + infoboxRight + '-' + ' info width : ' + ($('#CAN_infobox').width()+infoboxPadding) + '- info top ' + infoboxTop);
				var deltaX = deltaY = 0;
				var beakTop = beakLeft = 0;

				if(infoboxLeft <= 0) {
					deltaX = infoboxLeft;
					infoboxLeft = 10;//infoboxLeft + -1*deltaX + 20;
					beakLeft = beakX - (beakWidth/2) + -1*deltaX;
				}
				else if(infoboxRight >= $('#'+this.defaults.mapId).width()) {
					deltaX = infoboxRight - $('#'+this.defaults.mapId).width();
					infoboxLeft = infoboxLeft - deltaX -10;
					beakLeft = beakX - (beakWidth/2) - deltaX;
				}
				else {
					beakLeft = beakX - (beakWidth/2);
				}

				if(infoboxTop <= 0) {
					deltaY = infoboxTop;
					infoboxTop = infoboxTop + -1*deltaY;
					beakTop = beakY - beakHeight + -1*deltaY;
				} 
				else {
					beakTop = beakY - beakHeight;
				}

				// move map to fit the infobox.
				// add - value to move down and right
				// add + value to move up and left
				// but in terms of position of top and left it should be opposite.
				// That is to move infobox to right, add value to original one but substract from original value to move to left
				map.Pan(deltaX, deltaY);
				
				setTimeout(function(){
					// create a copy of the infobox to append it to map
					var cloneObj = $('#CAN_infobox').clone();
					
					// remove original infobox
					$('#CAN_infobox').empty().remove();
					
					// define css for cloned infobox and append to map
					// and then make it visible
					cloneObj
					 .css({display:'block',
						   top: infoboxTop,
						   left: infoboxLeft})
					 .find('.clickImg')
					 .mouseover(function(){$(this).css('cursor','pointer');})
					 .click(function(){
						 $('#mainCamTitle').html($(this).get(0).alt);
						 $('#mainCam').find('img').attr('src', $(this).get(0).src);
						 return false;
					 })
					 .end()						   
					 .dblclick(function(){return false;})	//disable dbl click event
					 .mousedown(function(){return false;})	//disable mousedown event
					 .mouseup(function(){return false;})	// disable mouseup event
					 .appendTo('#'+MapLIB.defaults.mapId);

					// make a shadow for infobox
				    cloneObj.dropShadow({ color: "#555", left: 5, top:5, blur:0, opacity: 0.6 });

					// dropShadow changes the zindex of infobox whichi is not good.
				    // so override it here
					$('#CAN_infobox').css({zIndex:600});

					var beakImg = ($.browser.version=='6.0' && $.browser.msie) ? "beak.gif": "beak.png";

					// put beak
					$('<div id="CAN_beak" class="CAN_infobox_grp"><img border="0" width="29px" height="36px" src="/images/'+beakImg+' "/></div>')
					 .css({position:'absolute',
						   top:beakTop,
						   left:beakLeft,
						   zIndex:600})
					 .appendTo('#'+MapLIB.defaults.mapId);
					
					// for mySask411 only, showListingBox on mouse click instead of mouseOver
					var impId = jQuery("#iMap_imp").html();
					if (impId==15) { //Direct West 
						showListingBox2(shape._can_id, 0);
						//highlightBox(shape._can_id);
					}	

					// add click event to exit image
					$('#CAN_infobox_exit')
					 .mouseover(function(){$(this).css('cursor','pointer');})
					 .click(function(){MapLIB.removeInfoBox(); });
					// if delta is not 0, wait for few ms for map to pan
				}, (deltaX != 0 || deltaY != 0) ? 300 : 0);
			};
		};

		var changeMapStyleHandler = function() {
			if(map.GetMapStyle() == VEMapStyle.BirdseyeHybrid || map.GetMapStyle() == VEMapStyle.Birdseye)
				hideStreetSceneButton();
			else if(map.GetMapStyle() == VEMapStyle.Road || map.GetMapStyle() == VEMapStyle.Aerial) {
				// if there is no timeout button is not restored in Firefox after switching between other map style  
				setTimeout(function() {
							if(MapLIB.isThereBlueDots())
								$('#btnStreetScene').css('display','block');
				}, 300);
			}

			if(map.GetMapStyle() == "b" || (typeof mjStreetView !== 'undefined' && mjStreetView.isStreetView))
				hideCustomZoomBar();
			else
				showCustomZoomBar();
		};

		var hideCustomZoomBar = function() {
			$('#ZoomBar_Background').css('display','none');
			$('#ZoomBar_Main').css('display','none');
			$('#MSVE_navAction_leftBar').css('display','block');
			$('#MSVE_navAction_leftBackground').css('display','block');
		};

		var showCustomZoomBar = function() {
			$('#ZoomBar_Background').css('display','block');
			$('#ZoomBar_Main').css('display','block');
			$('#MSVE_navAction_leftBar').css('display','none');
			$('#MSVE_navAction_leftBackground').css('display','none');
		};

		var getPinLetter = function(index) {
			return String.fromCharCode("a".charCodeAt(0) + (index -1));
		};

		var getPinHTML = function(letter, isOn) {
			var fname = isOn ? letter +"_on" : letter + "_off";

			if(jQuery.browser.version=="6.0" && jQuery.browser.msie)
				return "<div style='border:0px solid red;'><img style='position:absolute;top:-20px;left:10px;float:left;' src='"+"http://imfimg.com/images/mapicon/" + fname + ".gif"+"' /><img style='position:absolute;top:-20px;left:10px;' src='http://imfimg.com/images/mapicon/shadow.gif' /></div>";
			else
				return "<div style='border:0px solid red;'><img style='position:absolute;top:-20px;left:10px;float:left;' src='"+"http://imfimg.com/images/mapicon/" + fname + ".png"+"' /><img style='position:absolute;top:-20px;left:10px;' src='http://imfimg.com/images/mapicon/shadow.png' /></div>";
		};

		var getPinIMG = function(letter, isOn) {
			var fname = isOn ? letter +"_on" : letter + "_off";

			if(jQuery.browser.version=="6.0" && jQuery.browser.msie)
				return "http://imfimg.com/images/mapicon/" + fname + ".gif";
			else
				return "http://imfimg.com/images/mapicon/" + fname + ".png";
		};
		
		//Calculate distance between two points specified by latitude/longitude using law of cosines.
		//ref: http://www.movable-type.co.uk/scripts/LatLong.html
		var veGetDistance = function (p1, p2, miles) {
			p1.Latitude= latLonToRadians(p1.Latitude);
			p1.Longitude= latLonToRadians(p1.Longitude);
			
			p2.Latitude= latLonToRadians(p2.Latitude);
			p2.Longitude= latLonToRadians(p2.Longitude);

			var R = 6371; // earth's mean radius in km
			var dLat  = p2.Latitude- p1.Latitude;
			var dLong = p2.Longitude- p1.Longitude;
			var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(p1.Latitude) * Math.cos(p2.Latitude) * Math.sin(dLong/2) * Math.sin(dLong/2);
			var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
			var disKm = R * c;
			var disMiles = disKm * 0.6214;

			return (miles ? disMiles : disKm);
		};
		//convert lat/long in degrees to radians
		var latLonToRadians = function( point ) {
			return point * Math.PI / 180;	
		};

		var streetSceneButton = function() {
			if(isThereBlueDots())
				showStreetSceneButton();
			else
				hideStreetSceneButton();
		};
		
		// time is an integer representing seconds
		// returns a formatted string
		var getTime = function(time) {
		   if(time == null)
		      return("");

		   if(time > 60) {                                 
			   								// if time == 100
		      var seconds = time % 60;       // seconds == 40
		      var minutes = time - seconds;  // minutes == 60
		      minutes     = minutes / 60;    // minutes == 1

		      if(minutes > 60) {                                     
		    	  									// if minutes == 100
		         var minLeft = minutes % 60;        // minLeft    == 40
		         var hours   = minutes - minLeft;   // hours      == 60
		         hours       = hours / 60;          // hours      == 1

		         return(hours + " hour(s), " + minLeft + " minute(s), " + seconds + " second(s)");
		      }
		      else {
		         return(minutes + " minutes, " + seconds + " seconds");
		      }
		   }
		   else {
		      return(time + " seconds");
		   }
		};

		var addShim = function(el) {
			var shim = document.createElement("iframe");

			shim.id = "shim_"+el.id;
			shim.frameBorder = "0";
			shim.scrolling = "no";
			shim.style.position = "absolute";
			shim.style.zIndex = "1";
			shim.style.top = el.offsetTop + "px";	// don't remove string 'px'. it needs for FF
			shim.style.left = el.offsetLeft + "px";	// don't remove string 'px'. it needs for FF
			shim.width = el.offsetWidth;
			shim.height = el.offsetHeight;

			el.shimElement = shim;
			el.style.opacity = 1;
			el.parentNode.insertBefore(shim, el);
		};
		
		var blockMap = function(msg_) {
			var mapId = '#'+this.defaults.mapId;
			var msg = msg_||(MapLIB.defaults.lang == MapLIB.LangType.ENG ? "Loading":"Cargando");
			
			//$('#'+this.defaults.mapId).block({message: msg, css:{padding:'10px 0',width:'200px','font-size':'12px'}, overlayCSS:{backgroundColor:'#FFFFFF', opacity:'0.4'}});
			//$('div.mapdiv').block(msg);
 			//$.blockUI({message:msg, css:{padding:'10px 0',width:'200px','font-size':'12px'}, overlayCSS:{backgroundColor:'#FFFFFF', opacity:'0.4'}});
			var top, left, w, h;

			top = $(mapId).offset().top;
			left = $(mapId).offset().left;
			w = $(mapId).width();
			h = $(mapId).height();

			// top and left for inside message box
			top2 = parseInt(h/2 + top);
			left2 = parseInt(w/2 + left);

			$('<div class="divBlocker"></div>')
			 .css({position:'absolute', 
				   top:top, 
				   left:left, 
				   width:w, 
				   height:h, 
				   'background-color':"#FFFFFF", 
				   'opacity':0.4, 
				   'z-index':2000})
			 .appendTo('body');
			
			$('<div class="divBlocker">'+msg+'</div>')
			 .css({position:'absolute',
				   padding:'10px 0',
				   'text-align':'center',
				   top:top2-10,
				   left:left2-90,
				   width:'180px',
				   height:'20px',
				   border:'2px solid #999999',
				   'background-color':"#FFFFFF",
				   'font-size':'13px',
				   color: '#000000',
				   'z-index':2001})
			 .appendTo('body');
			
			//On Mac Safari, infobox remains - bug
			removeInfoBox();
		};
		
		var unblockMap = function() {
			//$('#'+this.defaults.mapId).unblock();
			//$.unblockUI({fadeOut:200});
			$('.divBlocker')
			 .empty()
			 .each(function(){
				var me = $(this).get(0);
				me.parentNode.removeChild(me);
			});
		};
		
		var getFullVirtualVisit = function(html) {
			var newHtml = html.replace(/hires=0/, 'hires=1');	// make it full screen mode
			newHtml = newHtml.replace(/"798"/, '"1143"');		// change width of iframe
			newHtml = newHtml.replace(/"477"/, '"707"');		// change height of iframe

			/*
			 * to show it in a layer
			 * 
			$(newHtml)
			 .css({display:'none', position:'absolute', top:'100px', left:'100px', zIndex:1004})
			 .appendTo('body');

			setTimeout(function() { 
				$('<img src="/images/fullscreen360_off.png" border="0" alt="full screen"/>')
				 .css({position:'absolute', top:'30px', right:'30px', zIndex:2001})
				 .mouseover(function(){ $(this).css('cursor','pointer'); $(this).get(0).src="/images/fullscreen360_on.png"})
				 .mouseout(function(){$(this).get(0).src="/images/fullscreen360_off.png"})
				 .click(function(){ MapLIB.closeVirtualTour(); })
				 .appendTo('#virtualFrame');}, 
			500);
			*/
			
			vtWin = window.open("",'','toolbar=no,resizable=no,directories=no,menubar=no,scrollbars=no,status=0,width='+screen.width+',height='+screen.height+'\'');			
			//vtWin.document.write($('#virtualFrame').html());

			vtWin.document.write('<body style="margin:0;padding:0">'+newHtml+'</body>');
		};

		var getVirtualVisit = function(companyName_, companyId, _sid, isDetail_) {
			var sid = _sid;
			var isDetail = isDetail_||false;
			var imgALT = (MapLIB.defaults.lang == MapLIB.LangType.ENG ? 'full screen' : 'maximiser')
			var companyName = companyName_ + ' - ' + (MapLIB.defaults.lang == MapLIB.LangType.ENG ? 'virtual visit' : 'visite virtuelle');
			var rightOffset = -100;
			/*
			if(companyId == '4696256' || companyId == '3315165')
				sid = "422";
			else if(companyId == '4979564')
				sid = "425";
			else if(companyId == '4178290')
				sid = "426";
			*/
			if(!isDetail) {
				cClick();
				closeVideo();
				rightOffset = 210;
			}

			html = '<div id="virtualFrame">'+
				   ' <iframe  style="position:relative" name="avuNavFrameInsertSee" id="IframeNavInsert"  frameborder="0"  vspace="0"  hspace="0"  marginwidth="0"  marginheight="0" ' + 
			       '	width="798" scrolling="NO"  height="477" ' +
			       '	src="http://www.avu3d.com/avu3D.htwl?sid='+sid+'&lang=' + (MapLIB.defaults.lang == MapLIB.LangType.ENG ? '3&':'5&') + 'hires=0&imgsvr=imfimg.com" ' +   
				   '	style="Z-INDEX: 1000; POSITION: relative; visibility: visible;">' +
				   ' </iframe>'+
				   '</div>';

			if(!isDetail) {
				overlib(html, TEXTPADDING, 0, STICKY, CLOSECLICK,	CLOSETEXT, '<img onClick="MapLIB.closeVirtualTour();" src="/images/exit.gif" border="0" />', 
						CAPTION, companyName, CGCOLOR, '#FFCC00', CAPCOLOR, '#000000', CAPTIONSIZE, '10px', 
					  	DELAY,0, TEXTPADDING, '1', TEXTSIZE, '10px', WIDTH, 560, HEIGHT, 160, BORDER, 3, BGCOLOR,'#FFCC00', FGCOLOR,'#FFFFFF', 
					  	SHADOW, SHADOWX,10, SHADOWY,10, STATUS, '');	
			}
			else 
				$('#virtualvisitTabBody_Content').html(html);
			
			$('<img src="/images/fullscreen360_off.png" border="0" alt="'+imgALT+'" title="'+imgALT+'" />')
			 .css({position:'absolute', top:'45px', right:rightOffset, zIndex:1001})
			 .mouseover(function(){$(this).css('cursor','pointer'); $(this).get(0).src="/images/fullscreen360_on.png"})
			 .mouseout(function(){$(this).get(0).src="/images/fullscreen360_off.png"})
			 .click(function(){ /*MapLIB.closeVirtualTour();*/ MapLIB.getFullVirtualVisit(html); })
			 .appendTo('#virtualFrame');
		};
		
		var closeVirtualTour = function() {
			var shim = document.getElementById("IframeNavInsert");
		   	if(shim != null) {
		   		shim.parentNode.removeChild(shim);
		   	}
		   	
		   	var vf = document.getElementById("virtualFrame");
		   	if(vf != null)
		   		vf.parentNode.removeChild(vf);
	   		
			cClick();
		}

		return {
			init:init,
			vars:vars,
			defaults:defaults,
			getMapInstance:getMapInstance,
			getMessage:getMessage,
			Button:Button,
			LangType:LangType,
			addShim:addShim,
			blockMap:blockMap,
			unblockMap:unblockMap,
			showInfoBox:showInfoBox,
			removeInfoBox:removeInfoBox,
			addPushpin:addPushpin,
			addPolygon:addPolygon,
			addArrayOfShapes:addArrayOfShapes,
			getPinLetter:getPinLetter,
			getPinHTML:getPinHTML,
			getPinIMG:getPinIMG,
			getTime:getTime,
			veGetDistance:veGetDistance,
			getWindowSize:getWindowSize,
			updatePushpin:updatePushpin,
			FixTiles:FixTiles,
			isThereBlueDots:isThereBlueDots,
			changeMapStyleHandler:changeMapStyleHandler,
			streetSceneButton:streetSceneButton,
			hideCustomZoomBar:hideCustomZoomBar,
			showCustomZoomBar:showCustomZoomBar,
			ZoomBarOnMouseOutImage:ZoomBarOnMouseOutImage,
			ZoomBarOnMouseOverImage:ZoomBarOnMouseOverImage,
			closeVirtualTour:closeVirtualTour,
			getVirtualVisit:getVirtualVisit,
			getFullVirtualVisit:getFullVirtualVisit
		};
	}();
})(jQuery);

// Plugin for custom buttons on the map
(function($) {
	$.fn.setCustomButton = function(options) {
		var opts = $.extend({}, $.fn.setCustomButton.defaults, options||{});
		var optsStyle = $.extend({}, $.fn.setCustomButton.defaults.style, opts.style||{}); 
		
		return this.each(function() {
			var map = MapLIB.getMapInstance();

			$(this)
			 //.appendTo('#'+opts.containerID)
			 .appendTo(opts.containerID)
			 .find('div')
			 .html(opts.name)
			 .end()
			 .css(optsStyle)
			 .mouseover(function(){
				 // in order to adjust opacity to default dashboard
				 if(map.GetMapMode() == VEMapMode.Mode3D)
					 $(this).css('opacity', 1);
				 else
					 $(this).css('opacity', 0.9);
			  })
			 .mouseout(function(){
				 if(map.GetMapMode() == VEMapMode.Mode3D)
					 $(this).css('opacity', 1);
				 else
					 $(this).css('opacity', 0.7);
			 })
			 .click(opts.clickFn)
			 .dblclick(function(){return false;})
			 //.mouseup(function(){return false;})
			 .mousedown(function(){return false;}); // because mousedown event is attached to the map, it should be removed from this button
		});
	};

	$.fn.setCustomButton.defaults = {
			containerID: "#"+MapLIB.defaults.mapId,
			style: {
						position:"absolute",
						top:"0px",
						left:"435px",
						width:"60px",
						height:"27px",
						padding:"0px",
						fontFamily:"Tahoma, Helvetica, Arial, sans-serif",
						color:"#FFFFFF",
						fontSize:"10px",
						backgroundColor:"#235087",
						//textAlign:"center",
						borderColor: "#8DC2EE",
						border:"",
						opacity: 0.7,
						cursor: "pointer",
						zIndex: 80 // in FF, it should be defined otherwise button will be disappeared
					},
			name: "",
			clickFn: null
		};
})(jQuery);

jQuery(window).unload(function() {
	var map = MapLIB.getMapInstance();
    if(map) 
    	map.Dispose();
});
