(function() {
var lang = YAHOO.lang;
inputEx.MapFieldGlobals = {
yahoo_preloader_error : 1,
lat : 43.648565,
lon : -79.385329,
uzoom : -13,
api : 'virtualearth',
api_key : ''
};
inputEx.MapFieldZoom = {
google : {
to_universal : function(orig) {
orig = parseInt(orig);
return Math.min(-1, -orig);
},
to_native : function(universal) {
universal = parseInt(universal);
return universal > 0 ? universal : -universal;
}
},
virtual_earth : {
to_universal : function(orig) {
orig = parseInt(orig);
return Math.min(-1, -orig);
},
to_native : function(universal) {
universal = parseInt(universal);
return universal > 0 ? universal : -universal;
}
},
yahoo : {
to_universal : function(orig) {
orig = parseInt(orig);
return Math.min(-1, orig - 18);
},
to_native : function(universal) {
universal = parseInt(universal);
return universal > 0 ? universal : Math.max(universal + 18, 1);
}
}
};
/**
* Wrapper for Mapping APIs, including Google Maps, Yahoo Maps and Virtual Earth
* @class inputEx.MapField
* @extends inputEx.Field
* @constructor
* @param {Object} options Added options:
* <ul>
* <li>width</li>
* <li>height</li>
* <li>loading</li>
* <li>lat</li>
* <li>lon</li>
* <li>uzoom</li>
* <li>api: google, yahoo or virtualearth (default)</li>
* <li>api_key</li>
* </ul>
*/
inputEx.MapField = function(options) {
inputEx.MapField.superclass.constructor.call(this,options);
};
lang.extend(inputEx.MapField, inputEx.Field, {
/**
* Adds the 'inputEx-MapField' default className
*/
setOptions: function(options) {
inputEx.MapField.superclass.setOptions.call(this, options);
this.options.className = options.className || 'inputEx-Field inputEx-MapField';
this.options.width = options.width || '400px';
this.options.height = options.height || '400px';
this.options.loading = options.loading || 'loading....';
this.options.lat = options.lat || inputEx.MapFieldGlobals.lat;
this.options.lon = options.lon || inputEx.MapFieldGlobals.lon;
this.options.uzoom = options.uzoom || inputEx.MapFieldGlobals.uzoom;
this.options.api = options.api || inputEx.MapFieldGlobals.api;
this.options.api_key = options.api_key || inputEx.MapFieldGlobals.api_key;
},
/**
* Render the field using the appropriate mapping function
*/
renderComponent: function() {
if(inputEx.MapFieldsNumber == undefined) { inputEx.MapFieldsNumber = -1; }
inputEx.MapFieldsNumber += 1;
this.apid = this.virtualearth;
if (this.options.api == "virtualearth") {
this.apid = this.virtualearth;
} else if (this.options.api == "google") {
this.apid = this.google;
} else if (this.options.api == "yahoo") {
this.apid = this.yahoo;
} else {
alert("unknown API '" + this.options.api + "': using 'virtualearth'");
}
var id = "inputEx-MapField-"+inputEx.MapFieldsNumber;
var idWrapper = "inputEx-MapFieldWrapper-"+inputEx.MapFieldsNumber;
var idLat = "inputEx-MapFieldLat-"+inputEx.MapFieldsNumber;
var idLon = "inputEx-MapFieldLon-"+inputEx.MapFieldsNumber;
var idUZoom = "inputEx-MapFieldUZoom-"+inputEx.MapFieldsNumber;
var idNZoom = "inputEx-MapFieldNZoom-"+inputEx.MapFieldsNumber;
// the wrapper is needed for Virtual Earth
this.elWrapper = inputEx.cn('div',
{ id: idWrapper, style: "width: " + this.options.width + "; height: " + this.options.height },
null,
null
);
this.fieldContainer.appendChild(this.elWrapper);
this.el = inputEx.cn('div',
{ id: id, style: "position: relative; width: " + this.options.width + "; height: " + this.options.height },
null,
this.options.loading
);
this.elWrapper.appendChild(this.el);
this.elLat = inputEx.cn('input', { id: idLat, type: "hidden", value: this.options.lat });
this.fieldContainer.appendChild(this.elLat);
this.elLon = inputEx.cn('input', { id: idLon, type: "hidden", value: this.options.lon });
this.fieldContainer.appendChild(this.elLon);
this.elUZoom = inputEx.cn('input', { id: idUZoom, type: "hidden", value: this.options.uzoom });
this.fieldContainer.appendChild(this.elUZoom);
this.elNZoom = inputEx.cn('input', { id: idNZoom, type: "hidden", value: this.options.uzoom });
this.fieldContainer.appendChild(this.elNZoom);
if (this.apid.preload(this)) {
return;
} else {
this.wait_create();
}
},
/**
* set the value: {lat: 45.23234, lon: 2.34456, uzoom: 6, nzoom: 6}
*/
setValue: function(value) {
var any = false;
if (value.uzoom != undefined) {
this.elUZoom.value = value.uzoom;
any = true;
} else if (value.nzoom != undefined) {
this.elUZoom.value = this.apid.f_zoom.to_universal(value.uzoom);
any = true;
}
if (value.lat != undefined) {
this.elLat.value = value.lat;
any = true;
}
if (value.lon != undefined) {
this.elLon.value = value.lon;
any = true;
}
if (any) {
this.apid.onposition();
}
},
/**
* return the same structure as setValue
*/
getValue: function() {
if (!this.elLat) return {};
return {
lat : parseFloat(this.elLat.value),
lon : parseFloat(this.elLon.value),
uzoom : parseInt(this.elUZoom.value),
nzoom : parseInt(this.elNZoom.value)
};
},
/**
* This will wait until the DOM element appears before completion of map rendering
*/
wait_create : function(_this) {
if (this == window) {
_this.wait_create(_this);
return;
}
if (document.getElementById(this.el.id)) {
this.apid.create(this);
} else {
window.setTimeout(this.wait_create, 0.1, this);
}
},
yahoo : {
y_map : null,
f_zoom : inputEx.MapFieldZoom.yahoo,
/**
* This preloaded MAY not really work -- we recommend that you use
* the following JavaScript instead _after_ "yahoo-dom-event.js" (or similar)
* is included:
*
* script type="text/javascript"
* YMAPPID = [yourapikey]
* /script
* script type="text/javascript" src="http://us.js2.yimg.com/us.js.yimg.com/lib/map/js/api/ymapapi_3_8_0_7.js"
* /script
*
* Note the non-standard loading pattern! See:
* http://yuiblog.com/blog/2006/12/14/maps-plus-yui/
*/
preload : function(superwrapper) {
if (window.YMap) {
return;
}
if (!inputEx.MapFieldGlobals.yahoo_preloader_error) {
inputEx.MapFieldGlobals.yahoo_preloader_error = 1;
alert("InputEx.MapField: we do not recommend dynamic API loading for Yahoo Maps");
}
var preloader = 'MapYahooPreloader_' + inputEx.MapFieldsNumber;
if (!inputEx[preloader]) {
inputEx[preloader] = 1;
var api_key = superwrapper.options.api_key[window.location.hostname];
if (!api_key) {
var api_key = superwrapper.options.api_key;
}
if (!api_key) {
alert("No map key is defined for Yahoo Maps");
return true;
}
window.YMAPPID = api_key;
var script = document.createElement("script");
script.src = "http://us.js2.yimg.com/us.js.yimg.com/lib/map/js/api/ymapapi_3_8_0_7.js";
script.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(script);
}
window.setTimeout(function() {
if (window.YMap) {
superwrapper.wait_create();
} else {
superwrapper.yahoo.preload(superwrapper);
}
}, 0.1);
return true;
},
create : function(superwrapper) {
this.y_map = new YMap(superwrapper.el);
this.y_map._mapField = superwrapper;
this.y_map.addTypeControl();
this.y_map.addZoomLong();
this.y_map.addPanControl();
this.y_map.setMapType(YAHOO_MAP_REG);
YEvent.Capture(this.y_map, EventsList.endMapDraw, this.onposition);
YEvent.Capture(this.y_map, EventsList.changeZoom, this.onposition);
YEvent.Capture(this.y_map, EventsList.endPan, this.onposition);
this.y_map.drawZoomAndCenter(
new YGeoPoint(superwrapper.elLat.value, superwrapper.elLon.value),
inputEx.MapFieldZoom.yahoo.to_native(superwrapper.elUZoom.value)
);
},
onposition : function() {
try {
var c = this.getCenterLatLon();
this._mapField.elLat.value = c.Lat;
this._mapField.elLon.value = c.Lon;
var z = this.getZoomLevel();
this._mapField.elNZoom.value = z;
this._mapField.elUZoom.value = inputEx.MapFieldZoom.yahoo.to_universal(z);
} catch (x) {
//alert(x);
}
}
},
google : {
g_map : null,
f_zoom : inputEx.MapFieldZoom.google,
/**
* If the Google Maps API has not been explicitly loaded, this will go get
* it on the user's behalf. They must have set 'api_key' to be either the API Key
* for this host, or a dictionary of { window.location.hostname : api_key }.
*
* See: http://code.google.com/apis/ajax/documentation/#Dynamic
*/
preload : function(superwrapper) {
if (window.GMap2) {
return;
}
var api_key = superwrapper.options.api_key[window.location.hostname];
if (!api_key) {
var api_key = superwrapper.options.api_key;
}
if (!api_key) {
alert("No map key is defined for Google Maps");
return true;
}
var preloader = 'MapGooglePreloader_' + inputEx.MapFieldsNumber;
inputEx[preloader] = function() {
google.load("maps", "2", {
"callback" : function() {
superwrapper.wait_create();
}
});
};
if (window.google) {
inputEx[preloader]();
} else {
var script = document.createElement("script");
script.src = "http://www.google.com/jsapi?key=" + api_key + "&callback=inputEx." + preloader;
script.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(script);
}
return true;
},
create : function(superwrapper) {
this.g_map = new GMap2(superwrapper.el);
this.g_map._mapField = superwrapper;
this.g_geocoder = new GClientGeocoder();
this.g_geocoder.setBaseCountryCode("ca");
GEvent.addListener(this.g_map, "load", this.onposition);
GEvent.addListener(this.g_map, "moveend", this.onposition);
GEvent.addListener(this.g_map, "zoomend", this.onposition);
this.g_map.addControl(new GSmallMapControl());
this.g_map.addControl(new GMapTypeControl());
this.g_map.setCenter(
new GLatLng(parseFloat(superwrapper.elLat.value), parseFloat(superwrapper.elLon.value)),
inputEx.MapFieldZoom.google.to_native(superwrapper.elUZoom.value)
);
},
onposition : function() {
try {
var c = this.getCenter();
this._mapField.elLat.value = c.lat();
this._mapField.elLon.value = c.lng();
var z = this.getZoom();
this._mapField.elNZoom.value = z;
this._mapField.elUZoom.value = inputEx.MapFieldZoom.google.to_universal(z);
} catch (x) {
//alert(x);
}
}
},
virtualearth : {
ve_map : null,
f_zoom : inputEx.MapFieldZoom.virtualearth,
/**
* If Virtual Earth has not been added via script tag, this
* will download it for you
*
* http://soulsolutions.com.au/Blog/tabid/73/EntryID/519/Default.aspx
* p_elSource.attachEvent is not a function
*/
preload : function(superwrapper) {
if (window.VEMap) {
return;
}
var preloader = 'MapVEPreloader_' + inputEx.MapFieldsNumber;
inputEx[preloader] = function() {
superwrapper.wait_create();
};
/*
* Fixes the 'p_elSource.attachEvent is not a function' error
* http://www.google.ca/search?hl=en&q=p_elSource.attachEvent+is+not+a+function&btnG=Google+Search&meta=
*
*/
if (!window.attachEvent) {
var script = document.createElement("script");
script.src = "http://dev.virtualearth.net/mapcontrol/v6.2/js/atlascompat.js";
script.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(script);
}
var script = document.createElement("script");
script.src = "http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2&onScriptLoad=inputEx." + preloader;
script.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(script);
return true;
},
create : function(superwrapper) {
superwrapper.el.style.position = "absolute";
this.ve_map = new VEMap(superwrapper.el.id);
this.ve_map._mapField = superwrapper;
this.ve_map.LoadMap(
new VELatLong(superwrapper.elLat.value, superwrapper.elLon.value),
inputEx.MapFieldZoom.virtual_earth.to_native(superwrapper.elUZoom.value),
VEMapStyle.Road, false, VEMapMode.Mode2D, true, 1);
var onposition = this.onposition;
var ve_map = this.ve_map;
this.ve_map.AttachEvent("onendzoom", function() { onposition(ve_map); });
this.ve_map.AttachEvent("onendpan", function() { onposition(ve_map); });
this.onposition(this.ve_map);
},
onposition : function(ve_map) {
if (!ve_map) return;
try {
var c = ve_map.GetCenter();
if (!c || !c.Latitude) {
return;
}
ve_map._mapField.elLat.value = c.Latitude;
ve_map._mapField.elLon.value = c.Longitude;
var z = ve_map.GetZoomLevel();
ve_map._mapField.elNZoom.value = z;
ve_map._mapField.elUZoom.value = inputEx.MapFieldZoom.virtual_earth.to_universal(z);
} catch (x) {
alert("MapField.virtualearth.onposition:" + x);
}
}
},
end : 0
});
// Register this class as "map" type
inputEx.registerType("map", inputEx.MapField);
})();