if (!this.JSON) {

    JSON = function () {

        function f(n) {    // Format integers to have at least two digits.
            return n < 10 ? '0' + n : n;
        }

        Date.prototype.toJSON = function () {

					// Eventually, this method will be based on the date.toISOString method.

            return this.getUTCFullYear()   + '-' +
                 f(this.getUTCMonth() + 1) + '-' +
                 f(this.getUTCDate())      + 'T' +
                 f(this.getUTCHours())     + ':' +
                 f(this.getUTCMinutes())   + ':' +
                 f(this.getUTCSeconds())   + 'Z';
        };


        var m = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        };

        function stringify(value, whitelist) {
            var a,          // The array holding the partial texts.
                i,          // The loop counter.
                k,          // The member key.
                l,          // Length.
                r = /["\\\x00-\x1f\x7f-\x9f]/g,
                v;          // The member value.

            switch (typeof value) {
            case 'string':

// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe sequences.

                return r.test(value) ?
                    '"' + value.replace(r, function (a) {
                        var c = m[a];
                        if (c) {
                            return c;
                        }
                        c = a.charCodeAt();
                        return '\\u00' + Math.floor(c / 16).toString(16) +
                                                   (c % 16).toString(16);
                    }) + '"' :
                    '"' + value + '"';

            case 'number':

// JSON numbers must be finite. Encode non-finite numbers as null.

                return isFinite(value) ? String(value) : 'null';

            case 'boolean':
            case 'null':
                return String(value);

            case 'object':

// Due to a specification blunder in ECMAScript,
// typeof null is 'object', so watch out for that case.

                if (!value) {
                    return 'null';
                }

// If the object has a toJSON method, call it, and stringify the result.

                if (typeof value.toJSON === 'function') {
                    return stringify(value.toJSON());
                }
                a = [];
                if (typeof value.length === 'number' &&
                        !(value.propertyIsEnumerable('length'))) {

// The object is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.

                    l = value.length;
                    for (i = 0; i < l; i += 1) {
                        a.push(stringify(value[i], whitelist) || 'null');
                    }

// Join all of the elements together and wrap them in brackets.

                    return '[' + a.join(',') + ']';
                }
                if (whitelist) {

// If a whitelist (array of keys) is provided, use it to select the components
// of the object.

                    l = whitelist.length;
                    for (i = 0; i < l; i += 1) {
                        k = whitelist[i];
                        if (typeof k === 'string') {
                            v = stringify(value[k], whitelist);
                            if (v) {
                                a.push(stringify(k) + ':' + v);
                            }
                        }
                    }
                } else {

// Otherwise, iterate through all of the keys in the object.

                    for (k in value) {
                        if (typeof k === 'string') {
                            v = stringify(value[k], whitelist);
                            if (v) {
                                a.push(stringify(k) + ':' + v);
                            }
                        }
                    }
                }

// Join all of the member texts together and wrap them in braces.

                return '{' + a.join(',') + '}';
            }
        }

        return {
            stringify: stringify,
            parse: function (text, filter) {
                var j;

                function walk(k, v) {
                    var i, n;
                    if (v && typeof v === 'object') {
                        for (i in v) {
                            if (Object.prototype.hasOwnProperty.apply(v, [i])) {
                                n = walk(i, v[i]);
                                if (n !== undefined) {
                                    v[i] = n;
                                }
                            }
                        }
                    }
                    return filter(k, v);
                }


// Parsing happens in three stages. In the first stage, we run the text against
// regular expressions that look for non-JSON patterns. We are especially
// concerned with '()' and 'new' because they can cause invocation, and '='
// because it can cause mutation. But just to be safe, we want to reject all
// unexpected forms.

// We split the first stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace all backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.

                if (/^[\],:{}\s]*$/.test(text.replace(/\\./g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

// In the second stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.

                    j = eval('(' + text + ')');

// In the optional third stage, we recursively walk the new structure, passing
// each name/value pair to a filter function for possible transformation.

                    return typeof filter === 'function' ? walk('', j) : j;
                }

// If the text is not JSON parseable, then a SyntaxError is thrown.

                throw new SyntaxError('parseJSON');
            }
        };
    }();
}



$.postJSON = function(url, data, callback) {
    $.post(url, data, callback);
};
$.toJSON = function(obj){
    return JSON.stringify(obj);
};
$.parseJSON = function(str){
    return JSON.parse(str);    
};

var lon = -97;
var lat = +40;
var zoom = 3;
var map, layer, street;

OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;
OpenLayers.Util.onImageLoadErrorColor = "transparent";

function moveMap(lon, lat, zoom) {
	var pt = lonlat2sMerc(lon, lat);
	var o = new OpenLayers.LonLat(pt.x, pt.y);

	map.panTo(o);
	map.zoomTo(zoom);
}

jQuery(function(){
  function setLegend(event) {
   loadLegend();
  }		
		var options = {
			projection: new OpenLayers.Projection("EPSG:900913"),
			displayProjection: new OpenLayers.Projection("EPSG:4326"),
			units: "m",
			maxResolution: 156543.0339,
			maxExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508.34),
			eventListeners: {
				"zoomend": setLegend
			}
		};
	
		var mapserver = "/home/map_data/tilecache/tilecache.cgi?";
		street = new OpenLayers.Layer.Google("Google Street", {'sphericalMercator': true});
	
		layer = new OpenLayers.Layer.WMS( "VMap0", mapserver, {
		  layers: 'tsmap', format: 'image/png',  transparent: 'TRUE'
		}, {
		  'isBaseLayer': false,'wrapDateLine': true,  opacity:0.5
		});
		map = new OpenLayers.Map('map', options);
		map.addLayers([layer, street]);
		var pt = lonlat2sMerc(lon, lat);
		o = new OpenLayers.LonLat(pt.x, pt.y);
		map.setCenter(o, zoom);
});

function lonlat2sMerc(lon, lat){
    var src = new OpenLayers.Projection("EPSG:4326");
    var dest  = new OpenLayers.Projection("EPSG:900913");
    var pt = new OpenLayers.Geometry.Point(lon, lat);
    OpenLayers.Projection.transform(pt, src, dest);
    return pt;
}


function loadLegend(){
    if(map.getZoom() <= 5){
	jQuery('#legend').load('/home/map_data/legend.php?l=s');
	return;
    }
    jQuery('#legend').load('/home/map_data/legend.php?l=z');
}

function loadRegion(regionId) {
	var urlparams = "regionId=" + regionId;
	if(regionId != 0) {
		jQuery.ajax({
				type:	"GET",
				url:	"/home/map_data/region_lonlat.php",
				data:	urlparams,
				success:	function(data){
										data = $.parseJSON(data);
										lon = data.longitude;
										lat = data.latitude;
										var pt = lonlat2sMerc(lon, lat);
										o = new OpenLayers.LonLat(pt.x, pt.y);
										if(map.getZoom() != 6){
											map.zoomTo(data.zoom);
										}
										map.panTo(o);
									}
		}); 	
	} else {
		loadAmerica();
	}
}

function loadMarket(marketId){
	if(marketId.trim() == 'any') {
		loadAmerica();
	} else {
		var urlparams = "marketId=" + marketId;
    jQuery.ajax({
	    type: "GET",
			url: "/home/map_data/market_lonlat.php",
			data: urlparams,
			success:	function(data){
									data = $.parseJSON(data);
									lon = data.longitude;
									lat = data.latitude;
									var pt = lonlat2sMerc(lon, lat);
									o = new OpenLayers.LonLat(pt.x, pt.y);
									if(map.getZoom() != 6){
										map.zoomTo(data.zoom);
									}
									map.panTo(o);
								}
		});  	
	}
}

function loadZip(zipId){
	if(zipId) {
    var urlparams = "zip=" + zipId;
		jQuery.ajax({
			type: "GET",
			url: "/home/map_data/zip_lonlat.php",
			data: urlparams,
			success: function(data){
						 data = $.parseJSON(data);
						 lon = data.longitude;
						 lat = data.latitude;
						 var pt = lonlat2sMerc(lon, lat);
						 o = new OpenLayers.LonLat(pt.x, pt.y);
						 map.zoomTo(data.zoom);
						 map.panTo(o);
				}
		});
	} else {
	
	}
   
}

function loadState(stateId){
	if(stateId.trim() != 'All') {
    var urlparams = "stateId=" + stateId;
    jQuery.ajax({
	    type: "GET",
		url: "/home/map_data/state_lonlat.php",
		data: urlparams,
		success: function(data){
		       data = $.parseJSON(data);
		       lon = data.longitude;
		       lat = data.latitude;
		       var pt = lonlat2sMerc(lon, lat);
		       o = new OpenLayers.LonLat(pt.x, pt.y);
		       map.zoomTo(data.zoom);
		       map.panTo(o);
	    }
		});
	} else {
		loadAmerica();
	}
   
}

function loadAmerica() {
	var pt = lonlat2sMerc(-94,37.0625);
	o = new OpenLayers.LonLat(pt.x, pt.y);
	map.zoomTo(4);
	map.panTo(o);
}
