if(typeof wxtools == 'undefined') {var wxtools = {};wxtools.log = function(message) {document.getElementById('log_target').innerHTML = message + '<br />' + document.getElementById('log_target').innerHTML;}}
/**
 * Constants all up front where you like 'em
 */

// Enable logging events
wxtools.MapPane_debug = false;

// Standard tile size
wxtools.MapPane_tileSize = 256;

// The extents of the world, square Mercator style
wxtools.MapPane_minLong = -180;
wxtools.MapPane_maxLong = 180;
wxtools.MapPane_minLat = -85.051111;
wxtools.MapPane_maxLat = 85.051111;

// URL's to know
wxtools.MapPane_seriesList = 'http://gima.weather.com/TileServer/jserieslist.do?count=1';
wxtools.MapPane_tilesPath = 'http://g.imwx.com/TileServer/imgs/';
wxtools.MapPane_tilesPathHash = ['http://g0.imwx.com/TileServer/imgs/','http://g1.imwx.com/TileServer/imgs/','http://g2.imwx.com/TileServer/imgs/','http://g3.imwx.com/TileServer/imgs/'];
wxtools.MapPane_iconsPath = 'http://i.uk.imwx.com/images/Mappane/';
wxtools.MapPane_transparentImg = 'http://i.uk.imwx.com/global/images/transparent.gif';

// All the little graphics that go in the frame
wxtools.MapPane_icons = {
	radar:{name:'radarLegend.png', height:40, width:199},
	eurorad:{name:'radarLegend.png', height:40, width:199},	
	sat:{name:'satLegendCloud.png', height:40, width:199},
	ussat:{name:'satLegendCloud.png', height:40, width:199},
	satrad:{name:'radarLegend.png', height:40, width:199},
	interact:{name:'interact_icon.png', height:48, width:62},
	twc:{name:'twcLogo.png', height:35, width:35},
	ve:{name:'logo_powered_by.png', height:29, width:93}
};
wxtools.MapPane_frameBuffer = 11;
wxtools.MapPane_updatedWidth = 190;

// Arrays used for formatting date/times
wxtools.MapPane_months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sept','Oct','Nov','Dec'];
wxtools.MapPane_hours = ['12','1','2','3','4','5','6','7','8','9','10','11','12','1','2','3','4','5','6','7','8','9','10','11'];

// Array of bitmasks used to translate tile coordinates <--> tile names
wxtools.MapPane_bitmasks = {};
for (var i = 1; i < 20; i++) {
	wxtools.MapPane_bitmasks[i] = 1 << (i - 1);
}

// Insertion of all the class-specific element styles
document.write('<style type="text/css">');
document.write('.MapPane{position:relative; top:0px; left:0px; overflow:hidden; border: 1px #000000 inset;}');
document.write('.MapPane_TileSets{position:absolute; top:0px; left:0px;}');
document.write('.MapPane_Tiles{position:absolute; top:0px; left:0px;}');
document.write('.MapPane_Tile{position:absolute; margin:0px; padding:0px;}');
document.write('.MapPane_Frame{position:absolute; top:0px; left:0px;}');
document.write('.MapPane_FrameElement{position:absolute; margin:0px; padding:0px;}');
document.write(['.MapPane_Updated{position:absolute; margin:0px; padding:2px; width:',wxtools.MapPane_updatedWidth,'px; height:11px; background-color:#000000; color:#FFFFFF; font-size:9px; font-family:Arial; text-align:center;}'].join(''));
document.write('</style>');










/**
 * MapPane_Point
 * this class abstracts logic related to storing and manipulating a lat/long or x/y location
 */
wxtools.MapPane_Point = function(x, y) {
	if (wxtools.MapPane_debug) wxtools.log('Point(' + x + ',' + y + ')');
	
	this.x = x;
	this.y = y;
};
// These really need to be in Math!!!  Do you hear me W3C?
wxtools.MapPane_Point.toRadians = function(degrees) { return degrees * (Math.PI / 180); };
wxtools.MapPane_Point.toDegrees = function(radians) { return radians * (180 / Math.PI); };

// How far is one point from another on the globe
wxtools.MapPane_Point.geoDistance = function(pt1, pt2) {
	if (wxtools.MapPane_debug) wxtools.log('Point.geoDistance(' + pt1 + ',' + pt2 + ')');
	
	var p1R = new MapPane_Point(MapPane_Point.toRadians(pt1.x), MapPane_Point.toRadians(pt1.y));
	var p2R = new MapPane_Point(MapPane_Point.toRadians(pt2.x), MapPane_Point.toRadians(pt2.y));
	var theta  = Math.cos(p1R.y) * Math.cos(p1R.x) * Math.cos(p2R.y) * Math.cos(p2R.x);
	theta += Math.cos(p1R.y) * Math.sin(p1R.x) * Math.cos(p2R.y) * Math.sin(p2R.x);
	theta += Math.sin(p1R.y) * Math.sin(p2R.y);
	theta = Math.acos(theta);
	return theta * 6367.3951;
};

wxtools.MapPane_Point.prototype = {
	// make a new point just like this one
	clone: function() {
		if (wxtools.MapPane_debug) wxtools.log('Point.clone()');
		
		return new MapPane_Point(this.x, this.y);
	},
	// move this point by the given amount
	offset: function(dx, dy) {
		if (wxtools.MapPane_debug) wxtools.log('Point.offset(' + dx + ',' + dy + ')');
		
		this.x += dx;
		this.y += dy;
	},
	// are these the same point?
	equals: function(toCompare) {
		if (wxtools.MapPane_debug) wxtools.log('Point.equals(' + toCompare + ')');
		
		return (toCompare.x == this.x) && (toCompare.y == this.y);
	},
	// make a new point this-v
	decrement: function(v) {
		if (wxtools.MapPane_debug) wxtools.log('Point.decrement(' + v + ')');
		
		return new MapPane_Point(this.x - v.x, this.y - v.y);
	},
	// make a new point this+v
	increment: function(v) {
		if (wxtools.MapPane_debug) wxtools.log('Point.increment(' + v + ')');
		
		return new MapPane_Point(this.x + v.x, this.y + v.y);
	},
	// eye-friendly description of the point
	toString: function() {
		if (wxtools.MapPane_debug) wxtools.log('Point.toString()');
		
		return "(x=" + this.x + ", y=" + this.y + ")";
	}
};










/**
 * MapPane_MercatorProjection
 * this class handles all conversions between lat/long and the equivalent x/y coordinates
 *  for a Mercator projection with the defined contants
 */
wxtools.MapPane_MercatorProjection = function(width, height, minXY, maxXY) {
	if (wxtools.MapPane_debug) wxtools.log('MercatorProjection(' + width + ',' + height + ',' + minXY + ',' + maxXY + ')');
	
	this.width = width;
	this.height = height;
	
	this.minXY = minXY.clone();
	this.maxXY = maxXY.clone();
	
	this.minXY.y = MapPane_MercatorProjection.mercatorY(minXY.y);
	this.maxXY.y = MapPane_MercatorProjection.mercatorY(maxXY.y);
	//alert("Debugging for Daniel:<BR>"+ "Width= "+this.width+", Height= "+this.height );
	this.deltaXY = this.minXY.decrement(this.maxXY);
}
// apply the Mercator functions to scew the y value
wxtools.MapPane_MercatorProjection.mercatorY = function(y) {
	if (wxtools.MapPane_debug) wxtools.log('MercatorProjection.mercatorY(' + y + ')');
	
	var rY = MapPane_Point.toRadians(y);
	var pY = Math.log((1 + Math.sin(rY))/(1 - Math.sin(rY))) / 2;
	return MapPane_Point.toDegrees(pY);
};
// unscew the y value back to normal
wxtools.MapPane_MercatorProjection.unmercatorY = function(y) {
	if (wxtools.MapPane_debug) wxtools.log('MercatorProjection.unmercatorY(' + y + ')');
	
	var rY = MapPane_Point.toRadians(y);
	var pY = 2 * Math.atan(Math.pow(Math.E, rY)) - (Math.PI/2);
	return MapPane_Point.toDegrees(pY);
};

wxtools.MapPane_MercatorProjection.prototype = {
	// convert the point from lat/long to x/y coordinates in the projection
	project: function(point) {
		if (wxtools.MapPane_debug) wxtools.log('MercatorProjection.project(' + point + ')');
		
		var pX = (point.x - this.maxXY.x)/this.deltaXY.x;
		var pY = (MapPane_MercatorProjection.mercatorY(point.y) - this.maxXY.y)/this.deltaXY.y;
		
		var x = this.width - (pX * this.width);
		var y = this.height - (pY * this.height);
		//alert("Debugging for Daniel: - x = " + x + " , y = "+ y);
		
		return new MapPane_Point(x, y);
	},
	// convert the x/y projection coordinates to lat/long
	unproject: function(point) {
		if (wxtools.MapPane_debug) wxtools.log('MercatorProjection.unproject(' + point + ')');
		
		var pX = (this.width - point.x)/this.width;
		var pY = (this.height - point.y)/this.height;
		
		var x = this.maxXY.x + (pX * this.deltaXY.x);
		var y = MapPane_MercatorProjection.unmercatorY(this.maxXY.y + (pY * this.deltaXY.y));
		
		return new MapPane_Point(x, y);
	}
};










/**
 * Handler logic for the callbacks from the series list script include
 */
 
// A hash to store values associated with an expected callback.  This allows requests to be 
//  issues simultaneously by multiple map placements without collision.  The hash keys are
//  the element id's of the map placement that made the request
wxtools.MapPane_overlayTasks = {};

// The function that gets called when the series list script gets parsed.  It pulls the data
//  from the callback and the above hash and sends them over to the function that actually
//  renders the overlay (and then cleans up all this temporary data)
wxtools.MapPane_overlayTiles = function(id, serieslist) {
	
	if (wxtools.MapPane_debug) wxtools.log('overlayTiles(' + id + ',' + serieslist + ')');
	
	var task = wxtools.MapPane_overlayTasks[id];
	var timestamp = serieslist.seriesInfo[task.series].series[0].date;
	
	MapPane.drawOverlay(id, task.center, task.width, task.height, task.level, task.series, task.transparency, timestamp);
	
	wxtools.MapPane_overlayTasks[id] = null;
	delete wxtools.MapPane_overlayTasks[id];
	
	var head = document.getElementsByTagName('head')[0];
	var script = document.getElementById('serieslist_include_' + id);
	if (script) {
		head.removeChild(script);
		
		delete script;
	}
	
};










/**
 * MapPane
 *  a static class (meaning you never create an instance object of type MapPane) that can render static map
 *  placements directly into a page.  It supports 3 methods for doing this:
 *   1. draw - uses document.write to insert the map directly into the page whereever the script is placed
 *   2. create - returns a DOM element that can be inserted into the page wherever you wish
 *   3. getSource - returns a String that you can write into the innerHTML of some page element
 */
wxtools.MapPane = function() {
	if (wxtools.MapPane_debug) wxtools.log('MapPane()');
};


with({
	
	// create a new projection for this level
	getProjection:function(level) {
		if (wxtools.MapPane_debug) wxtools.log('MapPane.getProjection(' + level + ')');
		//alert("Zoom Level = "+ level);
		var layer_width = Math.pow(2, level) * wxtools.MapPane_tileSize;
		var top_left = new MapPane_Point(wxtools.MapPane_minLong, wxtools.MapPane_maxLat);
		var bottom_right = new MapPane_Point(wxtools.MapPane_maxLong, wxtools.MapPane_minLat);
		
		return new MapPane_MercatorProjection(layer_width, layer_width, top_left, bottom_right);
	},
	
	// generate a properly formatted timestamp string
	getTimestampPresentation:function(timestampStr) {
		if (wxtools.MapPane_debug) wxtools.log('MapPane.getTimestampPresentation(' + timestampStr + ')');
		
		if(!timestampStr) return '';
		
		var year = Number(timestampStr.substr(0,4));
		var month = Number(timestampStr.substr(4,2)) - 1;
		var day = Number(timestampStr.substr(6,2));
		var hour = Number(timestampStr.substr(8,2));
		var min = Number(timestampStr.substr(10,2));
		
		var utcDate = new Date(Date.UTC(year, month, day, hour, min));
		var timestampPresentation = ['Updated ',utcDate.getDate(),' ',
										wxtools.MapPane_months[utcDate.getMonth()],' ',
										utcDate.getFullYear(),' ',
										wxtools.MapPane_hours[utcDate.getHours()],':',
										((String(utcDate.getMinutes()).length==1)?'0':''),utcDate.getMinutes(),' ',
										(utcDate.getHours()>11)?'pm':'am',' Local Time'].join('');
		return timestampPresentation;
	},
	
	// returns the url of the given tile
	getTileURL:function(tileName, tileSet, timestamp) {
		if (wxtools.MapPane_debug) wxtools.log('MapPane.getTileURL(' + tileName + ',' + tileSet + ',' + timestamp + ')');
		
		if (tileSet.length == 1) {
			// this is a Microsoft tile
			var number = tileName.substr(tileName.length - 1);
			return ['http://',tileSet,number,'.ortho.tiles.virtualearth.net/tiles/',tileSet,tileName,(tileSet=='r'?'.png?g=15':'.jpg?g=1')].join('');
		} else {
			// this is a Ginsu tile
			// get the last character in the tileName and use it as the Hash key
			var hashKey = Number(tileName.substr((tileName.length - 1),1));
			return [wxtools.MapPane_tilesPathHash[hashKey],tileSet,'/',timestamp,'/',tileName,'.png'].join('');
		}
	},
	
	// computes the quad-encoded tile name
	getTileName:function(tile, level) {
		if (wxtools.MapPane_debug) wxtools.log('MapPane.getTileName(' + tile + ',' + level + ')');
		//alert("Debugging for Daniel: "+tile + " " + level);
		var digits = '';
		
		var bitmask;
		var digit1;
		var digit2;
		for (var i = level; i > 0; i--) {
			digit1 = wxtools.MapPane_bitmasks[i] & tile.x;
			digit2 = wxtools.MapPane_bitmasks[i] & tile.y;
			digits += ((digit1 == 0?0:1) + (digit2 == 0?0:2))
		}
		return digits;
	},
	
	// returns the coordinates of the tile which contains the given geolocation
	getTilePosition:function(tileXY, level, width, height) {
		if (wxtools.MapPane_debug) wxtools.log('MapPane.getTilePosition(' + tileXY + ',' + projection + ',' + maxCoord + ',' + min + ')');
		
		var x_coord = Math.floor(tileXY.x / wxtools.MapPane_tileSize);
		var y_coord = Math.floor(tileXY.y / wxtools.MapPane_tileSize);
		
		return new MapPane_Point(x_coord, y_coord);
	},
	
	// determine the top left tile needed for this viewport
	getMinTile:function(centerXY, width, height, level, projection) {
		if (wxtools.MapPane_debug) wxtools.log('MapPane.getMinTile(' + centerXY + ',' + width + ',' + height + ',' + level + ',' + projection + ')');
		
		var offset = new MapPane_Point(width / 2, height / 2);
		
		var minXY = centerXY.decrement(offset);
		var minTile = this.getTilePosition(minXY, level, projection.width, projection.height);
		
		if (minTile.x < 0) minTile.x = 0;
		if (minTile.y < 0) minTile.y = 0;
		
		return minTile;
	},
	
	// determine the bottom right tile needed for this viewport
	getMaxTile:function(centerXY, width, height, level, projection) {
		if (wxtools.MapPane_debug) wxtools.log('MapPane.getMaxTile(' + centerXY + ',' + width + ',' + height + ',' + level + ',' + projection + ')');
		
		var maxCoord = Math.pow(2, level) - 1;
		var offset = new MapPane_Point(width / 2, height / 2);
		
		var maxXY = centerXY.increment(offset);
		var maxTile = this.getTilePosition(maxXY, level, projection.width, projection.height);
		
		if (maxTile.x > maxCoord) maxTile.x = maxCoord;
		if (maxTile.y > maxCoord) maxTile.y = maxCoord;
		
		return maxTile;
	},
	
	needTransparency:function() {
		var pos = navigator.userAgent.indexOf("MSIE ");
		if (pos == -1) return false;
		var version = navigator.userAgent.substring(pos + 5);
		return (((version.indexOf("5.5") == 0) || (version.indexOf("6") == 0)) && (navigator.platform == ("Win32")));
	},
	
	makeTransparent:function(img) {
		var src = img.src;
		if ((src.indexOf(wxtools.MapPane_transparentImg) == -1)  && (src.indexOf('png') != -1)) {
			img.runtimeStyle.filter = '';
			img.src = wxtools.MapPane_transparentImg;
			img.runtimeStyle.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\',sizingMethod=\'scale\')';
		}
	},
	
	// create a new image tile DOM element
	getTile:function(tileName, tileSet, top, left, timestamp) {
		if (wxtools.MapPane_debug) wxtools.log('MapPane.getTile(' + tileName + ',' + tileSet + ',' + top + ',' + left + ',' + timestamp + ')');
		
		var tileURL = this.getTileURL(tileName, tileSet, timestamp);
		
		var newImage = document.createElement("img");
		newImage.src = tileURL;
		newImage.className = 'MapPane_Tile';
		newImage.style.top = top + 'px';
		newImage.style.left = left + 'px';
		newImage.style.width = wxtools.MapPane_tileSize + 'px';
		newImage.style.height = wxtools.MapPane_tileSize + 'px';
		
		if (this.needTransparency() && timestamp != null) this.makeTransparent(newImage);
		
		return newImage;
	},
	
	// create a new set of positioned image tiles wrapped in a parent DOM element
	getTiles:function(center, width, height, level, tileSet) {
		if (wxtools.MapPane_debug) wxtools.log('MapPane.getTiles(' + center + ',' + width + ',' + height + ',' + level + ',' + tileSet + ')');
		
		var projection = this.getProjection(level);
		var centerXY = projection.project(center);
		
		var minTile = this.getMinTile(centerXY, width, height, level, projection);
		var maxTile = this.getMaxTile(centerXY, width, height, level, projection);
		
		var tiles = document.createElement('div');
		tiles.className = 'MapPane_Tiles';
		tiles.style.width = width + 'px';
		tiles.style.height = height + 'px';
		
		for (var pointX = minTile.x; pointX <= maxTile.x; pointX++) {
			for (var pointY = minTile.y; pointY <= maxTile.y; pointY++) {
				var tileName = this.getTileName(new MapPane_Point(pointX, pointY), level);
				var top = Math.floor(((pointY * wxtools.MapPane_tileSize) - centerXY.y) + (height / 2));
				var left = Math.floor(((pointX * wxtools.MapPane_tileSize) - centerXY.x) + (width / 2));
				
				tileClip = this.getTile(tileName, tileSet, top, left);
				
				tiles.appendChild(tileClip);
			}
		}
		return tiles;
	},
	
	// create an icon image DOM element
	getIcon:function(name, top, left, width, height) {
		if (wxtools.MapPane_debug) wxtools.log('MapPane.getIcon(' + name + ',' + top + ',' + left + ',' + width + ',' + height + ')');
		
		var icon = document.createElement('img');
		
		icon.src = [wxtools.MapPane_iconsPath,name].join('');
		icon.className = 'MapPane_FrameElement';
		icon.style.top = [top,'px'].join('');
		icon.style.left = [left,'px'].join('');
		icon.style.width = [width,'px'].join('');
		icon.style.height = [height,'px'].join('');
		
		if (this.needTransparency()) this.makeTransparent(icon);
		
		return icon;
	},
	
	// create the frame elements wrapped in a parent DOM element
	getInterface:function(width, height, overlay) {
		if (wxtools.MapPane_debug) wxtools.log('MapPane.getInterface(' + width + ',' + height + ',' + overlay + ')');
		
		var path = wxtools.MapPane_iconsPath;
		var icons = wxtools.MapPane_icons;
		
		var interfaceElement = document.createElement('div');
		interfaceElement.className = 'MapPane_Frame';
		interfaceElement.id = 'MapPane_Frame';
		interfaceElement.style.width = width + 'px';
		interfaceElement.style.height = height + 'px';		
		
		var ratio = icons['ve'].width / ((width / 2) - (wxtools.MapPane_frameBuffer + (wxtools.MapPane_updatedWidth / 2)));
		var twc = {height:icons['twc'].height,width:icons['twc'].width};
		var ve = {height:icons['ve'].height,width:icons['ve'].width};
		
		if (ratio > 1) {
		if(overlay == ""){
			twc.height = twc.height / ratio*10;
			twc.width = twc.width / ratio*10;
			ve.height = ve.height / ratio*10;
			ve.width = ve.width / ratio*10;		
		}else{
			twc.height = twc.height / ratio;
			twc.width = twc.width / ratio;
			ve.height = ve.height / ratio;
			ve.width = ve.width / ratio;
			}
		}
		interfaceElement.appendChild(this.getIcon(icons['ve'].name, height - (ve.height + wxtools.MapPane_frameBuffer), wxtools.MapPane_frameBuffer, ve.width, ve.height));
		interfaceElement.appendChild(this.getIcon(icons['twc'].name, height - (twc.height + wxtools.MapPane_frameBuffer), width - (twc.width + wxtools.MapPane_frameBuffer), twc.width, twc.height));
		
		return interfaceElement;
	},
	
	// generate the innerHTML text for a new set of positioned image tiles wrapped in a parent container
	getTilesSource:function(id, center, width, height, level, tileSet, overlay, transparency) {
		if (wxtools.MapPane_debug) wxtools.log('MapPane.getTilesSource(' + center + ',' + width + ',' + height + ',' + level + ',' + tileSet + ',' + overlay + ',' + transparency + ')');
		
		var projection = this.getProjection(level);
		var centerXY = projection.project(center);
		
		var minTile = this.getMinTile(centerXY, width, height, level, projection);
		var maxTile = this.getMaxTile(centerXY, width, height, level, projection);
		
		var tiles = ['<div class="MapPane_Tiles" style="width:',width,'px; height:',height,'px;">'];
		for (var pointX = minTile.x; pointX <= maxTile.x; pointX++) {
			for (var pointY = minTile.y; pointY <= maxTile.y; pointY++) {
				var tileURL = this.getTileURL(this.getTileName(new MapPane_Point(pointX, pointY), level), tileSet);
				
				tiles.push('<img src="',tileURL,'" ',
							  'class="MapPane_Tile" ',
							  'style="',
								'top:',Math.floor(((pointY * wxtools.MapPane_tileSize) - centerXY.y) + (height / 2)),'px; ',
								'left:',Math.floor(((pointX * wxtools.MapPane_tileSize) - centerXY.x) + (width / 2)),'px; ',
								'width:',wxtools.MapPane_tileSize,'px; ',
								'height:',wxtools.MapPane_tileSize,'px;" />');
			}
		}
		tiles.push('</div>');
		
		return tiles.join('');
	},
	
	addInterface:function(id, width, height, overlay) {
		wxtools.MapPane_interfacesToAdd[id] = { width:width, height:height, overlay:overlay };
	},
	
	// initiate a request for series list information that, when returned, will trigger rendering of the ginsu layer
	addOverlay:function(id, center, width, height, level, overlay, transparency) {
		if (wxtools.MapPane_debug) wxtools.log('MapPane.addOverlay(' + id + ',' + center + ',' + width + ',' + height + ',' + level + ',' + overlay + ',' + transparency + ')');
		
		// store the data needed to the rendering task
		wxtools.MapPane_overlayTasks[id] = {
			center: center,
			width: width,
			height: height,
			level: level,
			series: overlay,
			transparency: transparency
		};
		
		// create the script source include for the data request
		var head = document.getElementsByTagName('head')[0];
		var script = document.getElementById('serieslist_include_' + id);
		
		// this should never happen, but just in case...
		if (script) {
			head.removeChild(script);
			delete script;
		}
		
		script = document.createElement('script');
		script.id = 'serieslist_include_' + id;
		script.type = 'text/javascript';
		script.src = wxtools.MapPane_seriesList + '&function=wxtools.MapPane_overlayTiles&id=' + id;
		
		head.appendChild(script);
	}
}) {
	
	// return a DOM element that can be inserted into the page wherever you wish
	wxtools.MapPane.create = function(latitude, longitude, width, height, level, tileSet, overlay, transparency) {
		if (wxtools.MapPane_debug) wxtools.log('MapPane.create(' + latitude + ',' + longitude + ',' + width + ',' + height + ',' + level + ',' + tileSet + ',' + overlay + ',' + transparency + ')');
		
		if (navigator.userAgent.indexOf("MSIE ") == -1) {
			width -= 2;
			height -= 2;
		}
		
		var center = new MapPane_Point(longitude, latitude);
		var projection = getProjection(level);
		
		var id = 1000 * Math.random();
		
		var node = document.createElement('div');
		node.id = id;
		node.className = 'MapPane';
		node.style.width = width + 'px';
		node.style.height = height + 'px';
		
		var tilesets = document.createElement('div');
		tilesets.className = 'MapPane_TileSets';
		tilesets.style.width = width + 'px';
		tilesets.style.height = height + 'px';
		tilesets.appendChild(getTiles(center, width, height, level, tileSet));
		node.appendChild(tilesets);
		
		node.appendChild(getInterface(width, height, overlay));
		
		if (overlay) addOverlay(id, center, width, height, level, overlay, transparency);
		
		return node;
	};
	
	// return a String that you can write into the innerHTML of some page element
	wxtools.MapPane.getSource = function(latitude, longitude, width, height, level, tileSet, overlay, transparency) {
		if (wxtools.MapPane_debug) wxtools.log('MapPane.getSource(' + latitude + ',' + longitude + ',' + width + ',' + height + ',' + level + ',' + tileSet + ',' + overlay + ',' + transparency + ')');
		
		if (navigator.userAgent.indexOf("MSIE ") == -1) {
			width -= 2;
			height -= 2;
		}
		
		var id = 1000 * Math.random();
		
		var center = new MapPane_Point(longitude, latitude);
		var node = ['<div class="MapPane" id="',id,'" style="width:',width,'px; height:',height,'px;">',
					'<div class="MapPane_TileSets" " style="width:',width,'px; height:',height,'px;">',getTilesSource(id, center, width, height, level, tileSet, overlay, transparency),'</div>',
					'</div>'];
		
		addInterface(id, width, height, overlay);
		
		if (overlay) addOverlay(id, center, width, height, level, overlay, transparency);
		
		return node.join('');
	};
	
	// use document.write to insert the map directly into the page whereever the script is placed
	wxtools.MapPane.draw = function(latitude, longitude, width, height, level, tileSet, overlay, transparency) {
		if (wxtools.MapPane_debug) wxtools.log('MapPane.draw(' + latitude + ',' + longitude + ',' + width + ',' + height + ',' + level + ',' + tileSet + ',' + overlay + ',' + transparency + ')');
	
		document.write(this.getSource(latitude, longitude, width, height, level, tileSet, overlay, transparency));
	
	};
	
	wxtools.MapPane.addInterfaces = function() {
		for (var id in wxtools.MapPane_interfacesToAdd) {
			var mappane = document.getElementById(id);
			mappane.appendChild(getInterface(wxtools.MapPane_interfacesToAdd[id].width, wxtools.MapPane_interfacesToAdd[id].height, wxtools.MapPane_interfacesToAdd[id].overlay));
			wxtools.MapPane_interfacesToAdd[id] = null;
			delete wxtools.MapPane_interfacesToAdd[id];
		}
	};
	
	// handle incoming series list response
	wxtools.MapPane.drawOverlay = function(id, center, width, height, level, series, transparency, timestamp) {
		
		if (wxtools.MapPane_debug) wxtools.log('MapPane.drawOverlay(' + id + ',' + center + ',' + width + ',' + height + ',' + level + ',' + series + ',' + transparency + ',' + timestamp + ')');
		
		if (wxtools.MapPane_interfacesToAdd != {}) this.addInterfaces();
		
		var projection = getProjection(level);
		var centerXY = projection.project(center);
		
		var minTile = getMinTile(centerXY, width, height, level, projection);
		var maxTile = getMaxTile(centerXY, width, height, level, projection);
		
		var tileContainer = document.getElementById(id).firstChild;
		
		var tiles = document.createElement('div');
		tiles.className = 'MapPane_Tiles';
		tiles.style.width = width + 'px';
		tiles.style.height = height + 'px';
		
		for (var pointX = minTile.x; pointX <= maxTile.x; pointX++) {
			for (var pointY = minTile.y; pointY <= maxTile.y; pointY++) {
				var tileName = getTileName(new MapPane_Point(pointX, pointY), level);
				var top = (((pointY * wxtools.MapPane_tileSize) - centerXY.y) + (height / 2));
				var left = (((pointX * wxtools.MapPane_tileSize) - centerXY.x) + (width / 2));
				
				tileClip = getTile(tileName, series, top, left, timestamp);
				
				tiles.appendChild(tileClip);
			}
		}
		
		if (transparency) {
			tiles.style.MozOpacity = (100 - transparency)/100;
			tiles.style.filter = 'alpha(opacity=' + (100 - transparency) + ')'
			tiles.style.opacity = (100 - transparency)/100;
		}
		
		tileContainer.appendChild(tiles);
		
		var frame = tileContainer.nextSibling;
		frame.className = 'MapPane_Frame';
		frame.style.width = width + 'px';
		frame.style.height = height + 'px';
		
		var updated = document.createElement('div');
		updated.className = 'MapPane_Updated';
		updated.style.top = (height - 26) + 'px';
		updated.style.left = ((width / 2) - (wxtools.MapPane_updatedWidth / 2)) + 'px';
		updated.innerHTML = getTimestampPresentation(timestamp);
		
		var icons = wxtools.MapPane_icons;
		var legend = getIcon(icons[series].name, wxtools.MapPane_frameBuffer, width - (icons[series].width + wxtools.MapPane_frameBuffer), icons[series].width, icons[series].height);
		
		frame.appendChild(updated);
		frame.appendChild(legend);
	};
}


wxtools.MapPane_interfacesToAdd = {};
if (window.addEventListener) {
	window.addEventListener('load', wxtools.MapPane.addInterfaces, false);
} else if (window.attachEvent) {
	window.attachEvent('onload', wxtools.MapPane.addInterfaces);
}


// Alias the MapPane classes to global names outside of the wxtools context
var MapPane_Point = wxtools.MapPane_Point;
var MapPane_MercatorProjection = wxtools.MapPane_MercatorProjection;
var MapPane = wxtools.MapPane;