/**
* 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();