/** * IHT.com * Script for Google Maps (August 2007) * Display the article's location on Google Maps and adds search function to IHT.com based on that location. */ //create the LittleInfoWindow overlay onject function LittleInfoWindow(marker,html,width) { this.html_ = html; this.width_ = ( width ? width + 'px' : 'auto'); this.marker_ = marker; } //use the GOverlay class LittleInfoWindow.prototype = new GOverlay(); //initialize the container and shadowContainer LittleInfoWindow.prototype.initialize = function(map) { this.map_ = map; var container = document.createElement("div"); container.style.display='none'; map.getPane(G_MAP_FLOAT_PANE).appendChild(container); this.container_ = container; /*var shadowContainer = document.createElement("div"); shadowContainer.style.display='none'; map.getPane(G_MAP_FLOAT_SHADOW_PANE).appendChild(shadowContainer); this.shadowContainer_ = shadowContainer;*/ } LittleInfoWindow.prototype.remove = function() { this.container_.parentNode.removeChild(this.container_); //don't forget to remove the shadow as well //this.shadowContainer_.parentNode.removeChild(this.shadowContainer_); } LittleInfoWindow.prototype.copy = function() { return new LittleInfoWindow(this.marker_,this.html_,this.width_); } LittleInfoWindow.prototype.redraw = function(force) { if (!force) return; //get the content div var content = document.createElement("span"); content.innerHTML = this.html_; content.style.font='bold 11px Arial'; content.style.margin='0'; content.style.padding='0'; content.style.border='0'; content.style.display='inline'; if(!this.width_ || this.width_=='auto' || this.width_ <= 0) { //the width is unknown so set arough maximum and minimum content.style.minWidth = '10px'; content.style.maxWidth = '300px'; content.style.width = 'auto'; } else { //the width was set when creating the window content.style.width= width + 'px'; } //make it invisible for now content.style.visibility='hidden'; //temporarily append the content to the map container this.map_.getContainer().appendChild(content); //retrieve the rendered width and height var contentWidth = content.offsetWidth; var contentHeight = content.offsetHeight; //remove the content from the map content.parentNode.removeChild(content); content.style.visibility='visible'; //set the width and height to ensure they //stay that size when drawn again content.style.width=contentWidth+'px'; content.style.height=contentHeight+'px'; //set up the actual position relative to your images content.style.position='absolute'; content.style.left='7px'; content.style.top='7px'; content.style.background='white'; //create the wrapper for the window var wrapper = document.createElement("div"); //first append the content so the wrapper is above wrapper.appendChild(content); //create an object to reference each image var wrapperParts = { tl:{l:0, t:0, w:7, h:7}, t:{l:7, t:0, w:(contentWidth-1), h:7}, tr:{l:(contentWidth+6), t:0, w:8, h:7}, l:{l:0, t:7, w:7, h:contentHeight}, r:{l:(contentWidth+6), t:7, w:8, h:(contentHeight)}, bl:{l:0, t:(contentHeight+7), w:7, h:8}, p:{l:7, t:(contentHeight+7), w:8, h:12}, b:{l:15, t:(contentHeight+7), w:(contentWidth-9), h:8}, br:{l:(contentWidth+6), t:(contentHeight+7), w:8, h:8} } //create the image DOM objects for (i in wrapperParts) { var img = document.createElement('img'); //load the image from your local image directory //based on the property name of the wrapperParts object img.src = 'http://img.iht.com/images/article/gmap/' + i + '.png'; //set the appropriate positioning attributes img.style.position='absolute'; img.style.top=wrapperParts[i].t+'px'; img.style.left=wrapperParts[i].l+'px'; img.style.width=wrapperParts[i].w+'px'; img.style.height=wrapperParts[i].h+'px'; wrapper.appendChild(img); wrapperParts[i].img = img; } //add any event handlers like the close box var marker = this.marker_; GEvent.addDomListener(wrapperParts.tr.img, "click", function() { marker.closeLittleInfoWindow(); }); //get the X,Y pixel location of the marker var pixelLocation = this.map_.fromLatLngToDivPixel( this.marker_.getPoint() ); //position the container div for the window this.container_.style.position='absolute'; this.container_.style.left = (pixelLocation.x-10) + "px"; this.container_.style.top = (pixelLocation.y - contentHeight - 25 - this.marker_.getIcon().iconSize.height ) + "px"; this.container_.style.border = '0'; this.container_.style.margin = '0'; this.container_.style.padding = '0'; this.container_.style.display = 'block'; //append the styled info window to the container this.container_.appendChild(wrapper); //add ashadow /*this.shadowContainer_.style.position='absolute'; this.shadowContainer_.style.left = (pixelLocation.x+15) + "px"; this.shadowContainer_.style.top = (pixelLocation.y - 10 - this.marker_.getIcon().iconSize.height ) + "px"; this.shadowContainer_.style.border = '1px solid black'; this.shadowContainer_.style.margin = '0'; this.shadowContainer_.style.padding = '0'; this.shadowContainer_.style.display = 'block'; var shadowParts = { sl:{l:0, t:0, w:35, h:26}, s:{l:35, t:0, w:(contentWidth-40), h:26}, sr:{l:(contentWidth-5), t:0, w:35, h:26} } for (i in shadowParts) { var img = document.createElement('img'); img.src = '/images/article/gmap/' + i + '.png'; img.style.position='absolute'; img.style.top=shadowParts[i].t+'px'; img.style.left=shadowParts[i].l+'px'; img.style.width=shadowParts[i].w+'px'; img.style.height=shadowParts[i].h+'px'; this.shadowContainer_.appendChild(img); }*/ //pan if necessary so it shows on the screen var mapNE = this.map_.fromLatLngToDivPixel( this.map_.getBounds().getNorthEast() ); var panX=0; var panY=0; if(this.container_.offsetTop < mapNE.y) { //top of window is above the top edge of the map container panY = mapNE.y - this.container_.offsetTop; } if(this.container_.offsetLeft+contentWidth+10 > mapNE.x) { //right edge of window is outside the right edge of the map container panX = (this.container_.offsetLeft+contentWidth+10) - mapNE.x; } if(panX!=0 || panY!=0) { //pan the map this.map_.panBy(new GSize(-panX-10,panY+30)); } } //add anew method to GMarker so you //can use asimilar API to the existing info window. GMarker.prototype.LittleInfoWindowInstance = null; GMarker.prototype.openLittleInfoWindow = function(content,width) { if(this.LittleInfoWindowInstance == null) { this.LittleInfoWindowInstance = new LittleInfoWindow( this, content, width ); map.addOverlay(this.LittleInfoWindowInstance); } } GMarker.prototype.closeLittleInfoWindow = function() { if(this.LittleInfoWindowInstance != null) { map.removeOverlay(this.LittleInfoWindowInstance); this.LittleInfoWindowInstance = null; } } function gmap_init() { map = null; geocoder = null; zoomCountryLevel = 3; zoomCityLevel = 4; showMapFlag = null; firstRequest = false; exLocation = null; if (GBrowserIsCompatible()) { map = new GMap2(document.getElementById("gmap_map")); // CapitalCitiesCache is a custom cache that extends the standard GeocodeCache. // We call apply(this) to invoke the parent's class constructor. function ihtGmapCache() { GGeocodeCache.apply(this); } // Assigns an instance of the parent class as a prototype of the // child class, to make sure that all methods defined on the parent // class can be directly invoked on the child class. ihtGmapCache.prototype = new GGeocodeCache(); geocoder = new GClientGeocoder(); geocoder.setCache(new ihtGmapCache()); /** * "Toggle" function so the map shows/hides everytime you click on the article location link. * We had to write our own toggle function because the map can be hidden by two separate ways. * @param {Object} e */ /*jQuery("a#articleLocation").click(function(e){*/ jQuery("a[@id*=articleLocation]").click(function(e){ if (exLocation != jQuery(this).text()) { showMapFlag = false; firstRequest = false; } else { showMapFlag = false; firstRequest = true; } exLocation = jQuery(this).text(); /** * If the flag indicates the map is not being shown AND it has not been the first request yet, * we call the function loadAddress that sends the request to the google server and show the map. */ if (showMapFlag != true & firstRequest != true) { loadAddress(jQuery(this).text(), e, zoomCityLevel); valueofzoom = zoomCityLevel; return false; } /** * If the flag indicates the map is not being shown AND we already made a request to Google Maps , * we don't need to send another request to the google server and just need to show the map that is already loaded. */ else if (showMapFlag != true & firstRequest == true) { showMap(e); return false; } /** * If the flag indicates the map is being show then we hide the map */ else { hideMap(); return false; }; }); /** * If you click anywhere on the page while the map is being shownm, it will hide the map. * But to avoid this when clicking on the map itself, we put logic in the showMap(e) function below. * @param {Object} e */ jQuery(this).click(function(e){ if (showMapFlag){ hideMap(); } }); /** * Second handler way to hide the map */ jQuery("a#closeme").click(function() { hideMap(); return false; }); /** * Prevents showing/hiding the map when the ENTER button is pushed while a#articleLocation has the focus */ /*jQuery("a#articleLocation").focus(function(){*/ jQuery("a[@id*=articleLocation]").focus(function(){ jQuery(this).keypress( function() { return false; }) }); } else { alert('Your browser is not compatible with Google Maps.');} } /** * Hides the map with visibility style */ function hideMap() { if (marker.LittleInfoWindowInstance){ marker.closeLittleInfoWindow(); } document.getElementById("gmap_shell").style.visibility = "hidden"; showMapFlag = false; } /** * Shows the map with visibility style * It prevents the map itself to hide when someone clikc on it * but we need to keep the link contained in the bubble window active. */ function showMap(e) { document.getElementById("gmap_shell").style.position = "absolute"; document.getElementById("gmap_shell").style.top = e.pageY+8 + "px"; document.getElementById("gmap_shell").style.left = e.pageX-18 + "px"; document.getElementById("gmap_shell").style.visibility = "visible"; marker.openLittleInfoWindow(bubbleContent); bubbleSearchClicked = false; jQuery("div#gmap_shell").click(function(e){ if (!bubbleSearchClicked) { return false; } }); jQuery("a#bubbleSearch").click(function(e){ bubbleSearchClicked = true; }); showMapFlag = true; } /** * Makes a request to Google servers to obtain geocodes for the article specified location. * If the request was not successful and returns a null point : * a) we retrieve the country from the location that is in a 'CITY, Country' format, so we can display at * least the country of the location on the map. * @param {Object} address */ function loadAddress(address, e, zoomLevel) { if (geocoder) { geocoder.getLocations( address, function (response) { if (response.Status.code == G_GEO_SUCCESS) { /*if ( address.indexOf(",") != -1 ) { city = capitalize(address.split(",")[0]); country = address.split(",")[1]; address = city + ", " + country; } else { address = capitalize(address.split(",")[0]); }*/ place = response.Placemark[0]; point = new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]); map.setCenter(point, zoomLevel); marker = new GMarker(point); map.addOverlay(marker); bubbleContent = "Find more articles related to:
" + address + ""; marker.openLittleInfoWindow(bubbleContent); GEvent.addListener(marker, "click", function() { if (marker.LittleInfoWindowInstance){ marker.closeLittleInfoWindow(); } else { marker.openLittleInfoWindow(bubbleContent); } }); map.addControl(new GSmallMapControl()); map.addControl(new GMapTypeControl()); showMap(e); firstRequest = true; } // code 602 else if (response.Status.code == G_GEO_UNKNOWN_ADDRESS) { if ( address.indexOf(",") == -1 ) { alert("Sorry, we were unable to locate this address."); } else { country = address.split(",")[1]; loadAddress(country, e, zoomCountryLevel); valueofzoom = zoomCountryLevel; } } // code 603 else if (response.Status.code == G_GEO_UNAVAILABLE_ADDRESS) { alert("The geocode for the given address or the route for the given directions query cannot be returned by Google Maps due to legal or contractual reasons."); } // code 500 else if (response.Status.code == G_GEO_SERVER_ERROR) { alert(" A geocoding or directions request could not be successfully processed by Google Maps, yet the exact reason for the failure is not known."); } else { alert("Sorry, we were unable to locate this address."); } } ); } } function capitalize(pattern) { return pattern.charAt(0).toUpperCase() + pattern.substr(1).toLowerCase(); } // add to list of functions which run on window load womAdd('gmap_init()'); // ensure that jQuery doesn't conflict with other libraries // but still uses short names for objects jQuery.noConflict();