123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755 |
- (function(){
- /**
- * @exports mxn.util.$m as $m
- */
- var $m = mxn.util.$m;
- /**
- * Initialise our provider. This function should only be called
- * from within mapstraction code, not exposed as part of the API.
- * @private
- */
- var init = function() {
- this.invoker.go('init', [ this.currentElement, this.api ]);
- this.applyOptions();
- };
- /**
- * Mapstraction instantiates a map with some API choice into the HTML element given
- * @name mxn.Mapstraction
- * @constructor
- * @param {String} element The HTML element to replace with a map
- * @param {String} api The API to use, one of 'yahoo', 'microsoft', 'openstreetmap', 'multimap', 'map24', 'openlayers', 'mapquest'. If omitted, first loaded provider implementation is used.
- * @param {Bool} debug optional parameter to turn on debug support - this uses alert panels for unsupported actions
- * @exports Mapstraction as mxn.Mapstraction
- */
- var Mapstraction = mxn.Mapstraction = function(element, api, debug) {
- if (!api){
- api = mxn.util.getAvailableProviders()[0];
- }
- this.api = api;
- this.maps = {};
- this.currentElement = $m(element);
- this.eventListeners = [];
- this.markers = [];
- this.layers = [];
- this.polylines = [];
- this.images = [];
- this.controls = [];
- this.loaded = {};
- this.onload = {};
- this.element = element;
- // option defaults
- this.options = {
- enableScrollWheelZoom: false,
- enableDragging: true
- };
- this.addControlsArgs = {};
- // set up our invoker for calling API methods
- this.invoker = new mxn.Invoker(this, 'Mapstraction', function(){ return this.api; });
- // Adding our events
- mxn.addEvents(this, [
- /**
- * Map has loaded
- * @name mxn.Mapstraction#load
- * @event
- */
- 'load',
- /**
- * Map is clicked {location: LatLonPoint}
- * @name mxn.Mapstraction#click
- * @event
- */
- 'click',
- /**
- * Map is panned
- * @name mxn.Mapstraction#endPan
- * @event
- */
- 'endPan',
- /**
- * Zoom is changed
- * @name mxn.Mapstraction#changeZoom
- * @event
- */
- 'changeZoom',
- /**
- * Marker is removed {marker: Marker}
- * @name mxn.Mapstraction#markerAdded
- * @event
- */
- 'markerAdded',
- /**
- * Marker is removed {marker: Marker}
- * @name mxn.Mapstraction#markerRemoved
- * @event
- */
- 'markerRemoved',
- /**
- * Polyline is added {polyline: Polyline}
- * @name mxn.Mapstraction#polylineAdded
- * @event
- */
- 'polylineAdded',
- /**
- * Polyline is removed {polyline: Polyline}
- * @name mxn.Mapstraction#polylineRemoved
- * @event
- */
- 'polylineRemoved'
- ]);
- // finally initialize our proper API map
- init.apply(this);
- };
- // Map type constants
- Mapstraction.ROAD = 1;
- Mapstraction.SATELLITE = 2;
- Mapstraction.HYBRID = 3;
- // methods that have no implementation in mapstraction core
- mxn.addProxyMethods(Mapstraction, [
- /**
- * Adds a large map panning control and zoom buttons to the map
- * @name mxn.Mapstraction#addLargeControls
- * @function
- */
- 'addLargeControls',
- /**
- * Adds a map type control to the map (streets, aerial imagery etc)
- * @name mxn.Mapstraction#addMapTypeControls
- * @function
- */
- 'addMapTypeControls',
- /**
- * Adds a GeoRSS or KML overlay to the map
- * some flavors of GeoRSS and KML are not supported by some of the Map providers
- * @name mxn.Mapstraction#addOverlay
- * @function
- * @param {String} url GeoRSS or KML feed URL
- * @param {Boolean} autoCenterAndZoom Set true to auto center and zoom after the feed is loaded
- */
- 'addOverlay',
- /**
- * Adds a small map panning control and zoom buttons to the map
- * @name mxn.Mapstraction#addSmallControls
- * @function
- */
- 'addSmallControls',
- /**
- * Applies the current option settings
- * @name mxn.Mapstraction#applyOptions
- * @function
- */
- 'applyOptions',
- /**
- * Gets the BoundingBox of the map
- * @name mxn.Mapstraction#getBounds
- * @function
- * @returns {BoundingBox} The bounding box for the current map state
- */
- 'getBounds',
- /**
- * Gets the central point of the map
- * @name mxn.Mapstraction#getCenter
- * @function
- * @returns {LatLonPoint} The center point of the map
- */
- 'getCenter',
- /**
- * Gets the imagery type for the map.
- * The type can be one of:
- * mxn.Mapstraction.ROAD
- * mxn.Mapstraction.SATELLITE
- * mxn.Mapstraction.HYBRID
- * @name mxn.Mapstraction#getMapType
- * @function
- * @returns {Number}
- */
- 'getMapType',
- /**
- * Returns a ratio to turn distance into pixels based on current projection
- * @name mxn.Mapstraction#getPixelRatio
- * @function
- * @returns {Float} ratio
- */
- 'getPixelRatio',
- /**
- * Returns the zoom level of the map
- * @name mxn.Mapstraction#getZoom
- * @function
- * @returns {Integer} The zoom level of the map
- */
- 'getZoom',
- /**
- * Returns the best zoom level for bounds given
- * @name mxn.Mapstraction#getZoomLevelForBoundingBox
- * @function
- * @param {BoundingBox} bbox The bounds to fit
- * @returns {Integer} The closest zoom level that contains the bounding box
- */
- 'getZoomLevelForBoundingBox',
- /**
- * Displays the coordinates of the cursor in the HTML element
- * @name mxn.Mapstraction#mousePosition
- * @function
- * @param {String} element ID of the HTML element to display the coordinates in
- */
- 'mousePosition',
- /**
- * Resize the current map to the specified width and height
- * (since it is actually on a child div of the mapElement passed
- * as argument to the Mapstraction constructor, the resizing of this
- * mapElement may have no effect on the size of the actual map)
- * @name mxn.Mapstraction#resizeTo
- * @function
- * @param {Integer} width The width the map should be.
- * @param {Integer} height The width the map should be.
- */
- 'resizeTo',
- /**
- * Sets the map to the appropriate location and zoom for a given BoundingBox
- * @name mxn.Mapstraction#setBounds
- * @function
- * @param {BoundingBox} bounds The bounding box you want the map to show
- */
- 'setBounds',
- /**
- * setCenter sets the central point of the map
- * @name mxn.Mapstraction#setCenter
- * @function
- * @param {LatLonPoint} point The point at which to center the map
- * @param {Object} options Optional parameters
- * @param {Boolean} options.pan Whether the map should move to the locations using a pan or just jump straight there
- */
- 'setCenter',
- /**
- * Centers the map to some place and zoom level
- * @name mxn.Mapstraction#setCenterAndZoom
- * @function
- * @param {LatLonPoint} point Where the center of the map should be
- * @param {Integer} zoom The zoom level where 0 is all the way out.
- */
- 'setCenterAndZoom',
- /**
- * Sets the imagery type for the map
- * The type can be one of:
- * mxn.Mapstraction.ROAD
- * mxn.Mapstraction.SATELLITE
- * mxn.Mapstraction.HYBRID
- * @name mxn.Mapstraction#setMapType
- * @function
- * @param {Number} type
- */
- 'setMapType',
- /**
- * Sets the zoom level for the map
- * MS doesn't seem to do zoom=0, and Gg's sat goes closer than it's maps, and MS's sat goes closer than Y!'s
- * TODO: Mapstraction.prototype.getZoomLevels or something.
- * @name mxn.Mapstraction#setZoom
- * @function
- * @param {Number} zoom The (native to the map) level zoom the map to.
- */
- 'setZoom',
- /**
- * Turns a Tile Layer on or off
- * @name mxn.Mapstraction#toggleTileLayer
- * @function
- * @param {tile_url} url of the tile layer that was created.
- */
- 'toggleTileLayer'
- ]);
- /**
- * Sets the current options to those specified in oOpts and applies them
- * @param {Object} oOpts Hash of options to set
- */
- Mapstraction.prototype.setOptions = function(oOpts){
- mxn.util.merge(this.options, oOpts);
- this.applyOptions();
- };
- /**
- * Sets an option and applies it.
- * @param {String} sOptName Option name
- * @param vVal Option value
- */
- Mapstraction.prototype.setOption = function(sOptName, vVal){
- this.options[sOptName] = vVal;
- this.applyOptions();
- };
- /**
- * Enable scroll wheel zooming
- * @deprecated Use setOption instead.
- */
- Mapstraction.prototype.enableScrollWheelZoom = function() {
- this.setOption('enableScrollWheelZoom', true);
- };
- /**
- * Enable/disable dragging of the map
- * @param {Boolean} on
- * @deprecated Use setOption instead.
- */
- Mapstraction.prototype.dragging = function(on) {
- this.setOption('enableDragging', on);
- };
- /**
- * Change the current api on the fly
- * @param {String} api The API to swap to
- * @param element
- */
- Mapstraction.prototype.swap = function(element,api) {
- if (this.api === api) {
- return;
- }
- var center = this.getCenter();
- var zoom = this.getZoom();
- this.currentElement.style.visibility = 'hidden';
- this.currentElement.style.display = 'none';
- this.currentElement = $m(element);
- this.currentElement.style.visibility = 'visible';
- this.currentElement.style.display = 'block';
- this.api = api;
- if (this.maps[this.api] === undefined) {
- init.apply(this);
- this.setCenterAndZoom(center,zoom);
- for (var i = 0; i < this.markers.length; i++) {
- this.addMarker(this.markers[i], true);
- }
- for (var j = 0; j < this.polylines.length; j++) {
- this.addPolyline( this.polylines[j], true);
- }
- }
- else {
- //sync the view
- this.setCenterAndZoom(center,zoom);
- //TODO synchronize the markers and polylines too
- // (any overlays created after api instantiation are not sync'd)
- }
- this.addControls(this.addControlsArgs);
- };
- /**
- * Returns the loaded state of a Map Provider
- * @param {String} api Optional API to query for. If not specified, returns state of the originally created API
- */
- Mapstraction.prototype.isLoaded = function(api){
- if (api === null) {
- api = this.api;
- }
- return this.loaded[api];
- };
- /**
- * Set the debugging on or off - shows alert panels for functions that don't exist in Mapstraction
- * @param {Boolean} debug true to turn on debugging, false to turn it off
- */
- Mapstraction.prototype.setDebug = function(debug){
- if(debug !== null) {
- this.debug = debug;
- }
- return this.debug;
- };
- /////////////////////////
- //
- // Event Handling
- //
- // FIXME need to consolidate some of these handlers...
- //
- ///////////////////////////
- // Click handler attached to native API
- Mapstraction.prototype.clickHandler = function(lat, lon, me) {
- this.callEventListeners('click', {
- location: new LatLonPoint(lat, lon)
- });
- };
- // Move and zoom handler attached to native API
- Mapstraction.prototype.moveendHandler = function(me) {
- this.callEventListeners('moveend', {});
- };
- /**
- * Add a listener for an event.
- * @param {String} type Event type to attach listener to
- * @param {Function} func Callback function
- * @param {Object} caller Callback object
- */
- Mapstraction.prototype.addEventListener = function() {
- var listener = {};
- listener.event_type = arguments[0];
- listener.callback_function = arguments[1];
- // added the calling object so we can retain scope of callback function
- if(arguments.length == 3) {
- listener.back_compat_mode = false;
- listener.callback_object = arguments[2];
- }
- else {
- listener.back_compat_mode = true;
- listener.callback_object = null;
- }
- this.eventListeners.push(listener);
- };
- /**
- * Call listeners for a particular event.
- * @param {String} sEventType Call listeners of this event type
- * @param {Object} oEventArgs Event args object to pass back to the callback
- */
- Mapstraction.prototype.callEventListeners = function(sEventType, oEventArgs) {
- oEventArgs.source = this;
- for(var i = 0; i < this.eventListeners.length; i++) {
- var evLi = this.eventListeners[i];
- if(evLi.event_type == sEventType) {
- // only two cases for this, click and move
- if(evLi.back_compat_mode) {
- if(evLi.event_type == 'click') {
- evLi.callback_function(oEventArgs.location);
- }
- else {
- evLi.callback_function();
- }
- }
- else {
- var scope = evLi.callback_object || this;
- evLi.callback_function.call(scope, oEventArgs);
- }
- }
- }
- };
- ////////////////////
- //
- // map manipulation
- //
- /////////////////////
- /**
- * addControls adds controls to the map. You specify which controls to add in
- * the associative array that is the only argument.
- * addControls can be called multiple time, with different args, to dynamically change controls.
- *
- * args = {
- * pan: true,
- * zoom: 'large' || 'small',
- * overview: true,
- * scale: true,
- * map_type: true,
- * }
- * @param {array} args Which controls to switch on
- */
- Mapstraction.prototype.addControls = function( args ) {
- this.addControlsArgs = args;
- this.invoker.go('addControls', arguments);
- };
- /**
- * Adds a marker pin to the map
- * @param {Marker} marker The marker to add
- * @param {Boolean} old If true, doesn't add this marker to the markers array. Used by the "swap" method
- */
- Mapstraction.prototype.addMarker = function(marker, old) {
- marker.mapstraction = this;
- marker.api = this.api;
- marker.location.api = this.api;
- marker.map = this.maps[this.api];
- var propMarker = this.invoker.go('addMarker', arguments);
- marker.setChild(propMarker);
- if (!old) {
- this.markers.push(marker);
- }
- this.markerAdded.fire({'marker': marker});
- };
- /**
- * addMarkerWithData will addData to the marker, then add it to the map
- * @param {Marker} marker The marker to add
- * @param {Object} data A data has to add
- */
- Mapstraction.prototype.addMarkerWithData = function(marker, data) {
- marker.addData(data);
- this.addMarker(marker);
- };
- /**
- * addPolylineWithData will addData to the polyline, then add it to the map
- * @param {Polyline} polyline The polyline to add
- * @param {Object} data A data has to add
- */
- Mapstraction.prototype.addPolylineWithData = function(polyline, data) {
- polyline.addData(data);
- this.addPolyline(polyline);
- };
- /**
- * removeMarker removes a Marker from the map
- * @param {Marker} marker The marker to remove
- */
- Mapstraction.prototype.removeMarker = function(marker) {
- var current_marker;
- for(var i = 0; i < this.markers.length; i++){
- current_marker = this.markers[i];
- if(marker == current_marker) {
- this.invoker.go('removeMarker', arguments);
- marker.onmap = false;
- this.markers.splice(i, 1);
- this.markerRemoved.fire({'marker': marker});
- break;
- }
- }
- };
- /**
- * removeAllMarkers removes all the Markers on a map
- */
- Mapstraction.prototype.removeAllMarkers = function() {
- var current_marker;
- while(this.markers.length > 0) {
- current_marker = this.markers.pop();
- this.invoker.go('removeMarker', [current_marker]);
- }
- };
- /**
- * Declutter the markers on the map, group together overlapping markers.
- * @param {Object} opts Declutter options
- */
- Mapstraction.prototype.declutterMarkers = function(opts) {
- if(this.loaded[this.api] === false) {
- var me = this;
- this.onload[this.api].push( function() {
- me.declutterMarkers(opts);
- } );
- return;
- }
- var map = this.maps[this.api];
- switch(this.api)
- {
- // case 'yahoo':
- //
- // break;
- // case 'openstreetmap':
- //
- // break;
- // case 'microsoft':
- //
- // break;
- // case 'openlayers':
- //
- // break;
- case 'multimap':
- /*
- * Multimap supports quite a lot of decluttering options such as whether
- * to use an accurate of fast declutter algorithm and what icon to use to
- * represent a cluster. Using all this would mean abstracting all the enums
- * etc so we're only implementing the group name function at the moment.
- */
- map.declutterGroup(opts.groupName);
- break;
- // case 'mapquest':
- //
- // break;
- // case 'map24':
- //
- // break;
- case ' dummy':
- break;
- default:
- if(this.debug) {
- alert(this.api + ' not supported by Mapstraction.declutterMarkers');
- }
- }
- };
- /**
- * Add a polyline to the map
- * @param {Polyline} polyline The Polyline to add to the map
- * @param {Boolean} old If true replaces an existing Polyline
- */
- Mapstraction.prototype.addPolyline = function(polyline, old) {
- polyline.api = this.api;
- polyline.map = this.maps[this.api];
- var propPoly = this.invoker.go('addPolyline', arguments);
- polyline.setChild(propPoly);
- if(!old) {
- this.polylines.push(polyline);
- }
- this.polylineAdded.fire({'polyline': polyline});
- };
- // Private remove implementation
- var removePolylineImpl = function(polyline) {
- this.invoker.go('removePolyline', arguments);
- polyline.onmap = false;
- this.polylineRemoved.fire({'polyline': polyline});
- };
- /**
- * Remove the polyline from the map
- * @param {Polyline} polyline The Polyline to remove from the map
- */
- Mapstraction.prototype.removePolyline = function(polyline) {
- var current_polyline;
- for(var i = 0; i < this.polylines.length; i++){
- current_polyline = this.polylines[i];
- if(polyline == current_polyline) {
- this.polylines.splice(i, 1);
- removePolylineImpl.call(this, polyline);
- break;
- }
- }
- };
- /**
- * Removes all polylines from the map
- */
- Mapstraction.prototype.removeAllPolylines = function() {
- var current_polyline;
- while(this.polylines.length > 0) {
- current_polyline = this.polylines.pop();
- removePolylineImpl.call(this, current_polyline);
- }
- };
- /**
- * autoCenterAndZoom sets the center and zoom of the map to the smallest bounding box
- * containing all markers
- */
- Mapstraction.prototype.autoCenterAndZoom = function() {
- var lat_max = -90;
- var lat_min = 90;
- var lon_max = -180;
- var lon_min = 180;
- var lat, lon;
- var checkMinMax = function(){
- if (lat > lat_max) {
- lat_max = lat;
- }
- if (lat < lat_min) {
- lat_min = lat;
- }
- if (lon > lon_max) {
- lon_max = lon;
- }
- if (lon < lon_min) {
- lon_min = lon;
- }
- };
- for (var i = 0; i < this.markers.length; i++) {
- lat = this.markers[i].location.lat;
- lon = this.markers[i].location.lon;
- checkMinMax();
- }
- for(i = 0; i < this.polylines.length; i++) {
- for (var j = 0; j < this.polylines[i].points.length; j++) {
- lat = this.polylines[i].points[j].lat;
- lon = this.polylines[i].points[j].lon;
- checkMinMax();
- }
- }
- this.setBounds( new BoundingBox(lat_min, lon_min, lat_max, lon_max) );
- };
- /**
- * centerAndZoomOnPoints sets the center and zoom of the map from an array of points
- *
- * This is useful if you don't want to have to add markers to the map
- */
- Mapstraction.prototype.centerAndZoomOnPoints = function(points) {
- var bounds = new BoundingBox(points[0].lat,points[0].lon,points[0].lat,points[0].lon);
- for (var i=1, len = points.length ; i<len; i++) {
- bounds.extend(points[i]);
- }
- this.setBounds(bounds);
- };
- /**
- * Sets the center and zoom of the map to the smallest bounding box
- * containing all visible markers and polylines
- * will only include markers and polylines with an attribute of "visible"
- */
- Mapstraction.prototype.visibleCenterAndZoom = function() {
- var lat_max = -90;
- var lat_min = 90;
- var lon_max = -180;
- var lon_min = 180;
- var lat, lon;
- var checkMinMax = function(){
- if (lat > lat_max) {
- lat_max = lat;
- }
- if (lat < lat_min) {
- lat_min = lat;
- }
- if (lon > lon_max) {
- lon_max = lon;
- }
- if (lon < lon_min) {
- lon_min = lon;
- }
- };
- for (var i=0; i<this.markers.length; i++) {
- if (this.markers[i].getAttribute("visible")) {
- lat = this.markers[i].location.lat;
- lon = this.markers[i].location.lon;
- checkMinMax();
- }
- }
- for (i=0; i<this.polylines.length; i++){
- if (this.polylines[i].getAttribute("visible")) {
- for (j=0; j<this.polylines[i].points.length; j++) {
- lat = this.polylines[i].points[j].lat;
- lon = this.polylines[i].points[j].lon;
- checkMinMax();
- }
- }
- }
- this.setBounds(new BoundingBox(lat_min, lon_min, lat_max, lon_max));
- };
- /**
- * Automatically sets center and zoom level to show all polylines
- * Takes into account radious of polyline
- * @param {Int} radius
- */
- Mapstraction.prototype.polylineCenterAndZoom = function(radius) {
- var lat_max = -90;
- var lat_min = 90;
- var lon_max = -180;
- var lon_min = 180;
- for (var i=0; i < mapstraction.polylines.length; i++)
- {
- for (var j=0; j<mapstraction.polylines[i].points.length; j++)
- {
- lat = mapstraction.polylines[i].points[j].lat;
- lon = mapstraction.polylines[i].points[j].lon;
- latConv = lonConv = radius;
- if (radius > 0)
- {
- latConv = (radius / mapstraction.polylines[i].points[j].latConv());
- lonConv = (radius / mapstraction.polylines[i].points[j].lonConv());
- }
- if ((lat + latConv) > lat_max) {
- lat_max = (lat + latConv);
- }
- if ((lat - latConv) < lat_min) {
- lat_min = (lat - latConv);
- }
- if ((lon + lonConv) > lon_max) {
- lon_max = (lon + lonConv);
- }
- if ((lon - lonConv) < lon_min) {
- lon_min = (lon - lonConv);
- }
- }
- }
- this.setBounds(new BoundingBox(lat_min, lon_min, lat_max, lon_max));
- };
- /**
- * addImageOverlay layers an georeferenced image over the map
- * @param {id} unique DOM identifier
- * @param {src} url of image
- * @param {opacity} opacity 0-100
- * @param {west} west boundary
- * @param {south} south boundary
- * @param {east} east boundary
- * @param {north} north boundary
- */
- Mapstraction.prototype.addImageOverlay = function(id, src, opacity, west, south, east, north) {
- var b = document.createElement("img");
- b.style.display = 'block';
- b.setAttribute('id',id);
- b.setAttribute('src',src);
- b.style.position = 'absolute';
- b.style.zIndex = 1;
- b.setAttribute('west',west);
- b.setAttribute('south',south);
- b.setAttribute('east',east);
- b.setAttribute('north',north);
- var oContext = {
- imgElm: b
- };
- this.invoker.go('addImageOverlay', arguments, { context: oContext });
- };
- Mapstraction.prototype.setImageOpacity = function(id, opacity) {
- if (opacity < 0) {
- opacity = 0;
- }
- if (opacity >= 100) {
- opacity = 100;
- }
- var c = opacity / 100;
- var d = document.getElementById(id);
- if(typeof(d.style.filter)=='string'){
- d.style.filter='alpha(opacity:'+opacity+')';
- }
- if(typeof(d.style.KHTMLOpacity)=='string'){
- d.style.KHTMLOpacity=c;
- }
- if(typeof(d.style.MozOpacity)=='string'){
- d.style.MozOpacity=c;
- }
- if(typeof(d.style.opacity)=='string'){
- d.style.opacity=c;
- }
- };
- Mapstraction.prototype.setImagePosition = function(id) {
- var imgElement = document.getElementById(id);
- var oContext = {
- latLng: {
- top: imgElement.getAttribute('north'),
- left: imgElement.getAttribute('west'),
- bottom: imgElement.getAttribute('south'),
- right: imgElement.getAttribute('east')
- },
- pixels: { top: 0, right: 0, bottom: 0, left: 0 }
- };
- this.invoker.go('setImagePosition', arguments, { context: oContext });
- imgElement.style.top = oContext.pixels.top.toString() + 'px';
- imgElement.style.left = oContext.pixels.left.toString() + 'px';
- imgElement.style.width = (oContext.pixels.right - oContext.pixels.left).toString() + 'px';
- imgElement.style.height = (oContext.pixels.bottom - oContext.pixels.top).toString() + 'px';
- };
- Mapstraction.prototype.addJSON = function(json) {
- var features;
- if (typeof(json) == "string") {
- features = eval('(' + json + ')');
- } else {
- features = json;
- }
- features = features.features;
- var map = this.maps[this.api];
- var html = "";
- var item;
- var polyline;
- var marker;
- var markers = [];
- if(features.type == "FeatureCollection") {
- this.addJSON(features.features);
- }
- for (var i = 0; i < features.length; i++) {
- item = features[i];
- switch(item.geometry.type) {
- case "Point":
- html = "<strong>" + item.title + "</strong><p>" + item.description + "</p>";
- marker = new Marker(new LatLonPoint(item.geometry.coordinates[1],item.geometry.coordinates[0]));
- markers.push(marker);
- this.addMarkerWithData(marker,{
- infoBubble : html,
- label : item.title,
- date : "new Date(\""+item.date+"\")",
- iconShadow : item.icon_shadow,
- marker : item.id,
- iconShadowSize : item.icon_shadow_size,
- icon : "http://boston.openguides.org/markers/AQUA.png",
- iconSize : item.icon_size,
- category : item.source_id,
- draggable : false,
- hover : false
- });
- break;
- case "Polygon":
- var points = [];
- polyline = new Polyline(points);
- mapstraction.addPolylineWithData(polyline,{
- fillColor : item.poly_color,
- date : "new Date(\""+item.date+"\")",
- category : item.source_id,
- width : item.line_width,
- opacity : item.line_opacity,
- color : item.line_color,
- polygon : true
- });
- markers.push(polyline);
- break;
- default:
- // console.log("Geometry: " + features.items[i].geometry.type);
- }
- }
- return markers;
- };
- /**
- * Adds a Tile Layer to the map
- *
- * Requires providing a parameterized tile url. Use {Z}, {X}, and {Y} to specify where the parameters
- * should go in the URL.
- *
- * For example, the OpenStreetMap tiles are:
- * m.addTileLayer("http://tile.openstreetmap.org/{Z}/{X}/{Y}.png", 1.0, "OSM", 1, 19, true);
- *
- * @param {tile_url} template url of the tiles.
- * @param {opacity} opacity of the tile layer - 0 is transparent, 1 is opaque. (default=0.6)
- * @param {copyright_text} copyright text to use for the tile layer. (default=Mapstraction)
- * @param {min_zoom} Minimum (furtherest out) zoom level that tiles are available (default=1)
- * @param {max_zoom} Maximum (closest) zoom level that the tiles are available (default=18)
- * @param {map_type} Should the tile layer be a selectable map type in the layers palette (default=false)
- */
- Mapstraction.prototype.addTileLayer = function(tile_url, opacity, copyright_text, min_zoom, max_zoom, map_type) {
- if(!tile_url) {
- return;
- }
- this.tileLayers = this.tileLayers || [];
- opacity = opacity || 0.6;
- copyright_text = copyright_text || "Mapstraction";
- min_zoom = min_zoom || 1;
- max_zoom = max_zoom || 18;
- map_type = map_type || false;
- return this.invoker.go('addTileLayer', [ tile_url, opacity, copyright_text, min_zoom, max_zoom, map_type] );
- };
- /**
- * addFilter adds a marker filter
- * @param {field} name of attribute to filter on
- * @param {operator} presently only "ge" or "le"
- * @param {value} the value to compare against
- */
- Mapstraction.prototype.addFilter = function(field, operator, value) {
- if (!this.filters) {
- this.filters = [];
- }
- this.filters.push( [field, operator, value] );
- };
- /**
- * Remove the specified filter
- * @param {Object} field
- * @param {Object} operator
- * @param {Object} value
- */
- Mapstraction.prototype.removeFilter = function(field, operator, value) {
- if (!this.filters) {
- return;
- }
- var del;
- for (var f=0; f<this.filters.length; f++) {
- if (this.filters[f][0] == field &&
- (! operator || (this.filters[f][1] == operator && this.filters[f][2] == value))) {
- this.filters.splice(f,1);
- f--; //array size decreased
- }
- }
- };
- /**
- * Delete the current filter if present; otherwise add it
- * @param {Object} field
- * @param {Object} operator
- * @param {Object} value
- */
- Mapstraction.prototype.toggleFilter = function(field, operator, value) {
- if (!this.filters) {
- this.filters = [];
- }
- var found = false;
- for (var f = 0; f < this.filters.length; f++) {
- if (this.filters[f][0] == field && this.filters[f][1] == operator && this.filters[f][2] == value) {
- this.filters.splice(f,1);
- f--; //array size decreased
- found = true;
- }
- }
- if (! found) {
- this.addFilter(field, operator, value);
- }
- };
- /**
- * removeAllFilters
- */
- Mapstraction.prototype.removeAllFilters = function() {
- this.filters = [];
- };
- /**
- * doFilter executes all filters added since last call
- * Now supports a callback function for when a marker is shown or hidden
- * @param {Function} showCallback
- * @param {Function} hideCallback
- * @returns {Int} count of visible markers
- */
- Mapstraction.prototype.doFilter = function(showCallback, hideCallback) {
- var map = this.maps[this.api];
- var visibleCount = 0;
- var f;
- if (this.filters) {
- switch (this.api) {
- case 'multimap':
- /* TODO polylines aren't filtered in multimap */
- var mmfilters = [];
- for (f=0; f<this.filters.length; f++) {
- mmfilters.push( new MMSearchFilter( this.filters[f][0], this.filters[f][1], this.filters[f][2] ));
- }
- map.setMarkerFilters( mmfilters );
- map.redrawMap();
- break;
- case ' dummy':
- break;
- default:
- var vis;
- for (var m=0; m<this.markers.length; m++) {
- vis = true;
- for (f = 0; f < this.filters.length; f++) {
- if (! this.applyFilter(this.markers[m], this.filters[f])) {
- vis = false;
- }
- }
- if (vis) {
- visibleCount ++;
- if (showCallback){
- showCallback(this.markers[m]);
- }
- else {
- this.markers[m].show();
- }
- }
- else {
- if (hideCallback){
- hideCallback(this.markers[m]);
- }
- else {
- this.markers[m].hide();
- }
- }
- this.markers[m].setAttribute("visible", vis);
- }
- break;
- }
- }
- return visibleCount;
- };
- Mapstraction.prototype.applyFilter = function(o, f) {
- var vis = true;
- switch (f[1]) {
- case 'ge':
- if (o.getAttribute( f[0] ) < f[2]) {
- vis = false;
- }
- break;
- case 'le':
- if (o.getAttribute( f[0] ) > f[2]) {
- vis = false;
- }
- break;
- case 'eq':
- if (o.getAttribute( f[0] ) == f[2]) {
- vis = false;
- }
- break;
- }
- return vis;
- };
- /**
- * getAttributeExtremes returns the minimum/maximum of "field" from all markers
- * @param {field} name of "field" to query
- * @returns {array} of minimum/maximum
- */
- Mapstraction.prototype.getAttributeExtremes = function(field) {
- var min;
- var max;
- for (var m=0; m<this.markers.length; m++) {
- if (! min || min > this.markers[m].getAttribute(field)) {
- min = this.markers[m].getAttribute(field);
- }
- if (! max || max < this.markers[m].getAttribute(field)) {
- max = this.markers[m].getAttribute(field);
- }
- }
- for (var p=0; m<this.polylines.length; m++) {
- if (! min || min > this.polylines[p].getAttribute(field)) {
- min = this.polylines[p].getAttribute(field);
- }
- if (! max || max < this.polylines[p].getAttribute(field)) {
- max = this.polylines[p].getAttribute(field);
- }
- }
- return [min, max];
- };
- /**
- * getMap returns the native map object that mapstraction is talking to
- * @returns the native map object mapstraction is using
- */
- Mapstraction.prototype.getMap = function() {
- // FIXME in an ideal world this shouldn't exist right?
- return this.maps[this.api];
- };
- //////////////////////////////
- //
- // LatLonPoint
- //
- /////////////////////////////
- /**
- * LatLonPoint is a point containing a latitude and longitude with helper methods
- * @name mxn.LatLonPoint
- * @constructor
- * @param {double} lat is the latitude
- * @param {double} lon is the longitude
- * @exports LatLonPoint as mxn.LatLonPoint
- */
- var LatLonPoint = mxn.LatLonPoint = function(lat, lon) {
- // TODO error if undefined?
- // if (lat == undefined) alert('undefined lat');
- // if (lon == undefined) alert('undefined lon');
- this.lat = lat;
- this.lon = lon;
- this.lng = lon; // lets be lon/lng agnostic
- this.invoker = new mxn.Invoker(this, 'LatLonPoint');
- };
- mxn.addProxyMethods(LatLonPoint, [
- 'fromProprietary', 'toProprietary'
- ], true);
- /**
- * toString returns a string represntation of a point
- * @returns a string like '51.23, -0.123'
- * @type String
- */
- LatLonPoint.prototype.toString = function() {
- return this.lat + ', ' + this.lon;
- };
- /**
- * distance returns the distance in kilometers between two points
- * @param {LatLonPoint} otherPoint The other point to measure the distance from to this one
- * @returns the distance between the points in kilometers
- * @type double
- */
- LatLonPoint.prototype.distance = function(otherPoint) {
- // Uses Haversine formula from http://www.movable-type.co.uk
- var rads = Math.PI / 180;
- var diffLat = (this.lat-otherPoint.lat) * rads;
- var diffLon = (this.lon-otherPoint.lon) * rads;
- var a = Math.sin(diffLat / 2) * Math.sin(diffLat / 2) +
- Math.cos(this.lat*rads) * Math.cos(otherPoint.lat*rads) *
- Math.sin(diffLon/2) * Math.sin(diffLon/2);
- return 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)) * 6371; // Earth's mean radius in km
- };
- /**
- * equals tests if this point is the same as some other one
- * @param {LatLonPoint} otherPoint The other point to test with
- * @returns true or false
- * @type boolean
- */
- LatLonPoint.prototype.equals = function(otherPoint) {
- return this.lat == otherPoint.lat && this.lon == otherPoint.lon;
- };
- /**
- * Returns latitude conversion based on current projection
- * @returns {Float} conversion
- */
- LatLonPoint.prototype.latConv = function() {
- return this.distance(new LatLonPoint(this.lat + 0.1, this.lon))*10;
- };
- /**
- * Returns longitude conversion based on current projection
- * @returns {Float} conversion
- */
- LatLonPoint.prototype.lonConv = function() {
- return this.distance(new LatLonPoint(this.lat, this.lon + 0.1))*10;
- };
- //////////////////////////
- //
- // BoundingBox
- //
- //////////////////////////
- /**
- * BoundingBox creates a new bounding box object
- * @name mxn.BoundingBox
- * @constructor
- * @param {double} swlat the latitude of the south-west point
- * @param {double} swlon the longitude of the south-west point
- * @param {double} nelat the latitude of the north-east point
- * @param {double} nelon the longitude of the north-east point
- * @exports BoundingBox as mxn.BoundingBox
- */
- var BoundingBox = mxn.BoundingBox = function(swlat, swlon, nelat, nelon) {
- //FIXME throw error if box bigger than world
- //alert('new bbox ' + swlat + ',' + swlon + ',' + nelat + ',' + nelon);
- this.sw = new LatLonPoint(swlat, swlon);
- this.ne = new LatLonPoint(nelat, nelon);
- };
- /**
- * getSouthWest returns a LatLonPoint of the south-west point of the bounding box
- * @returns the south-west point of the bounding box
- * @type LatLonPoint
- */
- BoundingBox.prototype.getSouthWest = function() {
- return this.sw;
- };
- /**
- * getNorthEast returns a LatLonPoint of the north-east point of the bounding box
- * @returns the north-east point of the bounding box
- * @type LatLonPoint
- */
- BoundingBox.prototype.getNorthEast = function() {
- return this.ne;
- };
- /**
- * isEmpty finds if this bounding box has zero area
- * @returns whether the north-east and south-west points of the bounding box are the same point
- * @type boolean
- */
- BoundingBox.prototype.isEmpty = function() {
- return this.ne == this.sw; // is this right? FIXME
- };
- /**
- * contains finds whether a given point is within a bounding box
- * @param {LatLonPoint} point the point to test with
- * @returns whether point is within this bounding box
- * @type boolean
- */
- BoundingBox.prototype.contains = function(point){
- return point.lat >= this.sw.lat && point.lat <= this.ne.lat && point.lon >= this.sw.lon && point.lon <= this.ne.lon;
- };
- /**
- * toSpan returns a LatLonPoint with the lat and lon as the height and width of the bounding box
- * @returns a LatLonPoint containing the height and width of this bounding box
- * @type LatLonPoint
- */
- BoundingBox.prototype.toSpan = function() {
- return new LatLonPoint( Math.abs(this.sw.lat - this.ne.lat), Math.abs(this.sw.lon - this.ne.lon) );
- };
- /**
- * extend extends the bounding box to include the new point
- */
- BoundingBox.prototype.extend = function(point) {
- if(this.sw.lat > point.lat) {
- this.sw.lat = point.lat;
- }
- if(this.sw.lon > point.lon) {
- this.sw.lon = point.lon;
- }
- if(this.ne.lat < point.lat) {
- this.ne.lat = point.lat;
- }
- if(this.ne.lon < point.lon) {
- this.ne.lon = point.lon;
- }
- return;
- };
- //////////////////////////////
- //
- // Marker
- //
- ///////////////////////////////
- /**
- * Marker create's a new marker pin
- * @name mxn.Marker
- * @constructor
- * @param {LatLonPoint} point the point on the map where the marker should go
- * @exports Marker as mxn.Marker
- */
- var Marker = mxn.Marker = function(point) {
- this.api = null;
- this.location = point;
- this.onmap = false;
- this.proprietary_marker = false;
- this.attributes = [];
- this.invoker = new mxn.Invoker(this, 'Marker', function(){return this.api;});
- mxn.addEvents(this, [
- 'openInfoBubble', // Info bubble opened
- 'closeInfoBubble', // Info bubble closed
- 'click' // Marker clicked
- ]);
- };
- mxn.addProxyMethods(Marker, [
- 'fromProprietary',
- 'hide',
- 'openBubble',
- 'show',
- 'toProprietary',
- 'update'
- ]);
- Marker.prototype.setChild = function(some_proprietary_marker) {
- this.proprietary_marker = some_proprietary_marker;
- some_proprietary_marker.mapstraction_marker = this;
- this.onmap = true;
- };
- Marker.prototype.setLabel = function(labelText) {
- this.labelText = labelText;
- };
- /**
- * addData conviniently set a hash of options on a marker
- */
- Marker.prototype.addData = function(options){
- for(var sOptKey in options) {
- if(options.hasOwnProperty(sOptKey)){
- switch(sOptKey) {
- case 'label':
- this.setLabel(options.label);
- break;
- case 'infoBubble':
- this.setInfoBubble(options.infoBubble);
- break;
- case 'icon':
- if(options.iconSize && options.iconAnchor) {
- this.setIcon(options.icon, options.iconSize, options.iconAnchor);
- }
- else if(options.iconSize) {
- this.setIcon(options.icon, options.iconSize);
- }
- else {
- this.setIcon(options.icon);
- }
- break;
- case 'iconShadow':
- if(options.iconShadowSize) {
- this.setShadowIcon(options.iconShadow, [ options.iconShadowSize[0], options.iconShadowSize[1] ]);
- }
- else {
- this.setIcon(options.iconShadow);
- }
- break;
- case 'infoDiv':
- this.setInfoDiv(options.infoDiv[0],options.infoDiv[1]);
- break;
- case 'draggable':
- this.setDraggable(options.draggable);
- break;
- case 'hover':
- this.setHover(options.hover);
- this.setHoverIcon(options.hoverIcon);
- break;
- case 'hoverIcon':
- this.setHoverIcon(options.hoverIcon);
- break;
- case 'openBubble':
- this.openBubble();
- break;
- case 'groupName':
- this.setGroupName(options.groupName);
- break;
- default:
- // don't have a specific action for this bit of
- // data so set a named attribute
- this.setAttribute(sOptKey, options[sOptKey]);
- break;
- }
- }
- }
- };
- /**
- * setInfoBubble sets the html/text content for a bubble popup for a marker
- * @param {String} infoBubble the html/text you want displayed
- */
- Marker.prototype.setInfoBubble = function(infoBubble) {
- this.infoBubble = infoBubble;
- };
- /**
- * setInfoDiv sets the text and the id of the div element where to the information
- * useful for putting information in a div outside of the map
- * @param {String} infoDiv the html/text you want displayed
- * @param {String} div the element id to use for displaying the text/html
- */
- Marker.prototype.setInfoDiv = function(infoDiv,div){
- this.infoDiv = infoDiv;
- this.div = div;
- };
- /**
- * setIcon sets the icon for a marker
- * @param {String} iconUrl The URL of the image you want to be the icon
- */
- Marker.prototype.setIcon = function(iconUrl, iconSize, iconAnchor) {
- this.iconUrl = iconUrl;
- if(iconSize) {
- this.iconSize = iconSize;
- }
- if(iconAnchor) {
- this.iconAnchor = iconAnchor;
- }
- };
- /**
- * setIconSize sets the size of the icon for a marker
- * @param {String} iconSize The array size in pixels of the marker image
- */
- Marker.prototype.setIconSize = function(iconSize){
- if(iconSize) {
- this.iconSize = iconSize;
- }
- };
- /**
- * setIconAnchor sets the anchor point for a marker
- * @param {String} iconAnchor The array offset of the anchor point
- */
- Marker.prototype.setIconAnchor = function(iconAnchor){
- if(iconAnchor) {
- this.iconAnchor = iconAnchor;
- }
- };
- /**
- * setShadowIcon sets the icon for a marker
- * @param {String} iconUrl The URL of the image you want to be the icon
- */
- Marker.prototype.setShadowIcon = function(iconShadowUrl, iconShadowSize){
- this.iconShadowUrl = iconShadowUrl;
- if(iconShadowSize) {
- this.iconShadowSize = iconShadowSize;
- }
- };
- Marker.prototype.setHoverIcon = function(hoverIconUrl){
- this.hoverIconUrl = hoverIconUrl;
- };
- /**
- * setDraggable sets the draggable state of the marker
- * @param {Bool} draggable set to true if marker should be draggable by the user
- */
- Marker.prototype.setDraggable = function(draggable) {
- this.draggable = draggable;
- };
- /**
- * setHover sets that the marker info is displayed on hover
- * @param {Bool} hover set to true if marker should display info on hover
- */
- Marker.prototype.setHover = function(hover) {
- this.hover = hover;
- };
- /**
- * Markers are grouped up by this name. declutterGroup makes use of this.
- */
- Marker.prototype.setGroupName = function(sGrpName) {
- this.groupName = sGrpName;
- };
- /**
- * setAttribute: set an arbitrary key/value pair on a marker
- * @arg(String) key
- * @arg value
- */
- Marker.prototype.setAttribute = function(key,value) {
- this.attributes[key] = value;
- };
- /**
- * getAttribute: gets the value of "key"
- * @arg(String) key
- * @returns value
- */
- Marker.prototype.getAttribute = function(key) {
- return this.attributes[key];
- };
- ///////////////
- // Polyline ///
- ///////////////
- /**
- * Instantiates a new Polyline.
- * @name mxn.Polyline
- * @constructor
- * @param {Point[]} points Points that make up the Polyline.
- * @exports Polyline as mxn.Polyline
- */
- var Polyline = mxn.Polyline = function(points) {
- this.api = null;
- this.points = points;
- this.attributes = [];
- this.onmap = false;
- this.proprietary_polyline = false;
- this.pllID = "mspll-"+new Date().getTime()+'-'+(Math.floor(Math.random()*Math.pow(2,16)));
- this.invoker = new mxn.Invoker(this, 'Polyline', function(){return this.api;});
- };
- mxn.addProxyMethods(Polyline, [
- 'fromProprietary',
- 'hide',
- 'show',
- 'toProprietary',
- 'update'
- ]);
- /**
- * addData conviniently set a hash of options on a polyline
- */
- Polyline.prototype.addData = function(options){
- for(var sOpt in options) {
- if(options.hasOwnProperty(sOpt)){
- switch(sOpt) {
- case 'color':
- this.setColor(options.color);
- break;
- case 'width':
- this.setWidth(options.width);
- break;
- case 'opacity':
- this.setOpacity(options.opacity);
- break;
- case 'closed':
- this.setClosed(options.closed);
- break;
- case 'fillColor':
- this.setFillColor(options.fillColor);
- break;
- default:
- this.setAttribute(sOpt, options[sOpt]);
- break;
- }
- }
- }
- };
- Polyline.prototype.setChild = function(some_proprietary_polyline) {
- this.proprietary_polyline = some_proprietary_polyline;
- this.onmap = true;
- };
- /**
- * in the form: #RRGGBB
- * Note map24 insists on upper case, so we convert it.
- */
- Polyline.prototype.setColor = function(color){
- this.color = (color.length==7 && color[0]=="#") ? color.toUpperCase() : color;
- };
- /**
- * Stroke width of the polyline
- * @param {Integer} width
- */
- Polyline.prototype.setWidth = function(width){
- this.width = width;
- };
- /**
- * A float between 0.0 and 1.0
- * @param {Float} opacity
- */
- Polyline.prototype.setOpacity = function(opacity){
- this.opacity = opacity;
- };
- /**
- * Marks the polyline as a closed polygon
- * @param {Boolean} bClosed
- */
- Polyline.prototype.setClosed = function(bClosed){
- this.closed = bClosed;
- };
- /**
- * Fill color for a closed polyline as HTML color value e.g. #RRGGBB
- * @param {String} sFillColor HTML color value #RRGGBB
- */
- Polyline.prototype.setFillColor = function(sFillColor) {
- this.fillColor = sFillColor;
- };
- /**
- * setAttribute: set an arbitrary key/value pair on a polyline
- * @arg(String) key
- * @arg value
- */
- Polyline.prototype.setAttribute = function(key,value) {
- this.attributes[key] = value;
- };
- /**
- * getAttribute: gets the value of "key"
- * @arg(String) key
- * @returns value
- */
- Polyline.prototype.getAttribute = function(key) {
- return this.attributes[key];
- };
- /**
- * Simplifies a polyline, averaging and reducing the points
- * @param {Integer} tolerance (1.0 is a good starting point)
- */
- Polyline.prototype.simplify = function(tolerance) {
- var reduced = [];
- // First point
- reduced[0] = this.points[0];
- var markerPoint = 0;
- for (var i = 1; i < this.points.length-1; i++){
- if (this.points[i].distance(this.points[markerPoint]) >= tolerance)
- {
- reduced[reduced.length] = this.points[i];
- markerPoint = i;
- }
- }
- // Last point
- reduced[reduced.length] = this.points[this.points.length-1];
- // Revert
- this.points = reduced;
- };
- ///////////////
- // Radius //
- ///////////////
- /**
- * Creates a new radius object for drawing circles around a point, does a lot of initial calculation to increase load time
- * @returns a new Radius
- * @type Radius
- * @constructor
- * @classDescription Radius
- * @param {Object} Center LatLonPoint of the radius
- * @param {quality} Number of points that comprise the approximated circle (20 is a good starting point)
- */
- var Radius = mxn.Radius = function(center, quality) {
- this.center = center;
- var latConv = center.latConv();
- var lonConv = center.lonConv();
- // Create Radian conversion constant
- var rad = Math.PI / 180;
- this.calcs = [];
- for(var i = 0; i < 360; i += quality){
- this.calcs.push([Math.cos(i * rad) / latConv, Math.sin(i * rad) / lonConv]);
- }
- };
- /**
- * Returns polyline of a circle around the point based on new radius
- * @param {Radius} radius
- * @param {Colour} colour
- * @returns {Polyline} Polyline
- */
- Radius.prototype.getPolyline = function(radius, colour) {
- var points = [];
- for(var i = 0; i < this.calcs.length; i++){
- var point = new LatLonPoint(
- this.center.lat + (radius * this.calcs[i][0]),
- this.center.lon + (radius * this.calcs[i][1])
- );
- points.push(point);
- }
- // Add first point
- points.push(points[0]);
- var line = new Polyline(points);
- line.setColor(colour);
- return line;
- };
- })();
|