Show:

File: ia\data\MapData.js

  1. /**
  2. * Contains information about a map file which has been published
  3. * through the InstantAtlas publisher.
  4. *
  5. * @author J Clare
  6. * @class ia.MapData
  7. * @extends ia.EventDispatcher
  8. * @constructor
  9. */
  10. ia.MapData = function()
  11. {
  12. ia.MapData.baseConstructor.call(this);
  13. this._layerCount = -1;
  14. this._visibleLayers = new Array();
  15. this._callbackFnc = undefined;
  16. this._layerHash = new Object();
  17.  
  18. this.tilePath = "./";
  19. this.useGoogleMaps = false;
  20. this.path = "";
  21. };
  22. ia.extend(ia.EventDispatcher, ia.MapData);
  23.  
  24. /**
  25. * The template number.
  26. *
  27. * @property template
  28. * @type String
  29. */
  30. ia.MapData.prototype.template;
  31.  
  32. /**
  33. * The version number.
  34. *
  35. * @property version
  36. * @type String
  37. */
  38. ia.MapData.prototype.version;
  39.  
  40. /**
  41. * The maps bounding box.
  42. *
  43. * @property mapBBox
  44. * @type ia.BoundingBox
  45. */
  46. ia.MapData.prototype.mapBBox;
  47.  
  48. /**
  49. * All layers.
  50. *
  51. * @property layers
  52. * @type ia.LayerBase[]
  53. */
  54. ia.MapData.prototype.layers;
  55.  
  56. /**
  57. * Base layers.
  58. *
  59. * @property baseLayers
  60. * @type ia.LayerBase[]
  61. */
  62. ia.MapData.prototype.baseLayers;
  63.  
  64. /**
  65. * The current base layer.
  66. *
  67. * @property baseLayer
  68. * @type ia.LayerBase
  69. */
  70. ia.MapData.prototype.baseLayer;
  71.  
  72. /**
  73. * None Base layers.
  74. *
  75. * @property noneBaseLayers
  76. * @type ia.LayerBase[]
  77. */
  78. ia.MapData.prototype.noneBaseLayers;
  79.  
  80. /**
  81. * Icon layers.
  82. *
  83. * @property iconLayers
  84. * @type ia.LayerBase[]
  85. */
  86. ia.MapData.prototype.iconLayers;
  87.  
  88. /**
  89. * The path to tiles for tile layers.
  90. *
  91. * @property tilePath
  92. * @type String
  93. */
  94. ia.MapData.prototype.tilePath;
  95.  
  96. /**
  97. * Set to true if using google maps.
  98. *
  99. * @property useGoogleMaps
  100. * @type Boolean
  101. * @default false
  102. */
  103. ia.MapData.prototype.useGoogleMaps;
  104.  
  105. /**
  106. * The google map type.
  107. *
  108. * @property googleMapType
  109. * @type String
  110. */
  111. ia.MapData.prototype.googleMapType;
  112.  
  113. /**
  114. * The google map api key.
  115. *
  116. * @property googleApiKey
  117. * @type String
  118. */
  119. ia.MapData.prototype.googleApiKey;
  120. /**
  121. * The url of the data source.
  122. *
  123. * @property url
  124. * @type String
  125. */
  126. ia.MapData.prototype.url;
  127.  
  128. /**
  129. * The directory path to the data source.
  130. *
  131. * @property path
  132. * @type String
  133. * @default ""
  134. */
  135. ia.MapData.prototype.path;
  136.  
  137. /**
  138. * Loads and parses the source file then calls the given function with the ReportConfig object
  139. * as the first parameter.
  140. *
  141. * @method parseData
  142. * @param {String} url The url to the data.
  143. * @param {Function} callbackFunction The call back function.
  144. */
  145. ia.MapData.prototype.loadSource = function(url, callbackFunction)
  146. {
  147. var me = this;
  148. this.url = url;
  149. this.path = ia.File.getFileDirectory(url);
  150.  
  151. ia.File.load(
  152. {
  153. url: url,
  154. dataType: "json",
  155. onSuccess:function(json)
  156. {
  157. me.parseData(json, callbackFunction);
  158. }
  159. });
  160. };
  161.  
  162. /**
  163. * Returns the layer that corresponds to the id.
  164. *
  165. * @method getLayer
  166. * @param {String} id The layer id.
  167. * @return {ia.LayerBase} The layer for the given id.
  168. */
  169. ia.MapData.prototype.getLayer = function(id)
  170. {
  171. return this._layerHash[id];
  172. };
  173.  
  174. /**
  175. * Updates the data.
  176. *
  177. * @method parseData
  178. * @param {JSON} data The raw data.
  179. * @param {Function} callbackFunction The call back function.
  180. */
  181. ia.MapData.prototype.parseData = function(data, callbackFunction)
  182. {
  183. this._layerCount = -1;
  184. this.useGoogleMaps = false;
  185. this._callbackFnc = callbackFunction;
  186.  
  187. // delete any previous layers
  188. for (var id in this._layerHash)
  189. {
  190. delete this._layerHash[id];
  191. };
  192.  
  193. this._visibleLayers = new Array();
  194. this.layers = new Array();
  195. this.baseLayers = new Array();
  196. this.noneBaseLayers = new Array(); // Image and contextual.
  197. var imageLayers = new Array();
  198. var referenceLayers = new Array();
  199. var pointLayers = new Array();
  200. var lineLayers = new Array();
  201. var polygonLayers = new Array();
  202. this._layerHash = new Object();
  203. // Map properties.
  204. if (data.template !== undefined) this.template = data.template;
  205. if (data.version !== undefined) this.version = data.version;
  206. if (data.boundingBox !== undefined)
  207. {
  208. var bb = data.boundingBox.split(" ");
  209. this.mapBBox = new ia.BoundingBox(parseFloat(bb[0]),
  210. parseFloat(bb[1]),
  211. parseFloat(bb[2]),
  212. parseFloat(bb[3]));
  213. }
  214. // Layers.
  215. var layers = data.layers;
  216. if (layers !== undefined)
  217. {
  218. // Check for google layer first.
  219. var n = layers.length;
  220. for (var i = 0; i < n; i++)
  221. {
  222. var layerData = layers[i];
  223. if (layerData.type === "google-layer" && navigator.onLine)
  224. {
  225. this.useGoogleMaps = true;
  226. this.googleMapType = layerData.mapType;
  227. this.googleApiKey = layerData.apiKey;
  228. }
  229. }
  230. for (var i = 0; i < n; i++)
  231. {
  232. var layerData = layers[i];
  233.  
  234. // Ignore background layers when using google maps.
  235. if (layerData.geometry === "image" && this.useGoogleMaps === false)
  236. {
  237. var layer;
  238.  
  239. if (layerData.type === "tile-layer")
  240. {
  241. var layer = new ia.TileLayer(this.path+layerData.url);
  242. layer.path = this.tilePath;
  243. this._parseLayerProperties(layerData, layer);
  244. }
  245. else if (layerData.type === "ags-layer" && navigator.onLine)
  246. {
  247. var layer = new ia.AGSLayer();
  248. this._parseLayerProperties(layerData, layer);
  249. }
  250. else if (layerData.type === "wms-layer" && navigator.onLine)
  251. {
  252. var layer = new ia.WMSLayer();
  253. this._parseLayerProperties(layerData, layer);
  254. }
  255. if (layerData.isReference) referenceLayers[referenceLayers.length] = layer;
  256. else imageLayers[imageLayers.length] = layer;
  257.  
  258. }
  259. if (layerData.geometry !== "image")
  260. {
  261. var layer;
  262. var isFeatureServiceLayer = (layerData.idField !== undefined);
  263.  
  264. if (layerData.type === "base-layer")
  265. {
  266. if (isFeatureServiceLayer)
  267. layer = new ia.FeatureServiceLayer(layerData.url);
  268. else
  269. layer = new ia.FeatureLayer(this.path+layerData.url);
  270. this.baseLayers[this.baseLayers.length] = layer;
  271. // Make first base layer the active layer.
  272. if (this.baseLayers.length === 1) this.baseLayer = layer;
  273. }
  274. else if (layerData.type === "contextual-layer")
  275. {
  276. if (isFeatureServiceLayer)
  277. layer = new ia.FeatureServiceLayer(layerData.url);
  278. else
  279. layer = new ia.FeatureLayer(this.path+layerData.url);
  280. }
  281. else if (layerData.type === "rss-layer")
  282. {
  283. layer = new ia.GeoRSSLayer(layerData.url);
  284. }
  285.  
  286. this._parseLayerProperties(layerData, layer);
  287. // Remove extra base layers from visible layers list
  288. // so theyre not loaded at startup. And set to invisible.
  289. if (layerData.type === "base-layer" && this.baseLayers.length > 1)
  290. {
  291. var layer = this._visibleLayers.pop();
  292.  
  293. // This was originally commented out but it caused a bug
  294. // where if the second base layer was point data you couldnt
  295. // select the first base layer in the map.
  296. layer.setVisible(false);
  297. }
  298. if (layerData.type !== "base-layer")
  299. {
  300. if (layer.geometry === "point") pointLayers[pointLayers.length] = layer;
  301. else if (layer.geometry === "line") lineLayers[lineLayers.length] = layer;
  302. else if (layer.geometry === "polygon") polygonLayers[polygonLayers.length] = layer;
  303. }
  304.  
  305. this._layerHash[layer.id] = layer;
  306. }
  307. }
  308. // None base layers.
  309. this.noneBaseLayers = imageLayers.concat(polygonLayers)
  310. .concat(lineLayers)
  311. .concat(pointLayers)
  312. .concat(referenceLayers);
  313. // Add the base layers in the correct position.
  314. for (var i = 0; i < this.baseLayers.length; i++)
  315. {
  316. var layer = this.baseLayers[i];
  317. if (layer.geometry === "point") pointLayers.unshift(layer);
  318. else if (layer.geometry === "line") lineLayers.unshift(layer);
  319. else if (layer.geometry === "polygon") polygonLayers.unshift(layer);
  320. }
  321. this.layers = imageLayers.concat(polygonLayers)
  322. .concat(lineLayers)
  323. .concat(pointLayers)
  324. .concat(referenceLayers);
  325. }
  326.  
  327. if (this.useGoogleMaps && ia.googleMapsLoaded === false)
  328. {
  329. var script = document.createElement("script");
  330. script.type = "text/javascript";
  331. if (this.googleApiKey !== "")
  332. script.src = "http://maps.googleapis.com/maps/api/js?key="+this.googleApiKey+"&sensor=false&callback=ia.initGoogleMaps";
  333. else
  334. script.src = "http://maps.google.com/maps/api/js?sensor=false&callback=ia.initGoogleMaps";
  335. document.body.appendChild(script);
  336. }
  337. else this.loadVisibleLayers();
  338. };
  339.  
  340. /**
  341. * Parses layer properties.
  342. *
  343. * @method _parseLayerProperties
  344. * @param {JSON} data The raw data.
  345. * @param {ia.LayerBase} layer The layer.
  346. * @private
  347. */
  348. ia.MapData.prototype._parseLayerProperties = function(data, layer)
  349. {
  350. layer.id = data.id;
  351. layer.name = data.name;
  352. layer.showInLayerList = data.showInLayerList;
  353. // Visibility
  354. if (data.visible !== undefined)
  355. {
  356. layer.setVisible(data.visible);
  357.  
  358. // Base layer is included whether its visible or not so that we can read in whether its an evaluation version.
  359. if (data.visible === true || data.type === "base-layer") this._visibleLayers[this._visibleLayers.length] = layer;
  360. }
  361.  
  362. // Feature layers
  363. if (data.minLabelExtent !== undefined) layer.minLabelExtent = data.minLabelExtent;
  364. if (data.maxLabelExtent !== undefined) layer.maxLabelExtent = data.maxLabelExtent;
  365. if (data.showLabels !== undefined) layer.showLabels = data.showLabels;
  366. if (data.showDataTips !== undefined) layer.showDataTips = data.showDataTips;
  367. if (data.iconPath !== undefined && data.iconPath !== "")
  368. {
  369. layer.iconPath = data.iconPath;
  370. if (layer.iconPath.indexOf("http") === -1 && layer.iconPath.indexOf("javascript") === -1)
  371. layer.iconPath = ia.IAS_PATH + layer.iconPath;
  372. }
  373.  
  374. // AGOL FeatureServer layers.
  375. if (data.idField !== undefined) layer.idField = data.idField;
  376. if (data.nameField !== undefined) layer.nameField = data.nameField;
  377. if (data.srs !== undefined) layer.srs = data.srs;
  378. if (data.featureIds !== undefined) layer.featureIds = data.featureIds;
  379. if (data.objectIds !== undefined) layer.objectIds = data.objectIds;
  380. if (data.boundingBox !== undefined)
  381. {
  382. var bb = data.boundingBox.split(" ");
  383. layer.bBox = new ia.BoundingBox(parseFloat(bb[0]),
  384. parseFloat(bb[1]),
  385. parseFloat(bb[2]),
  386. parseFloat(bb[3]));
  387. }
  388.  
  389. // Styles
  390. layer.geometry = data.geometry;
  391. if (data.geometry !== "image")
  392. {
  393. var style = layer.style;
  394. if (data.symbolSize !== undefined) layer.symbolSize = data.symbolSize;
  395. if (data.fillColor !== undefined)
  396. {
  397. // Convert to rgba.
  398. style.fillStyle = ia.Color.toRGBA(data.fillColor, data.fillOpacity);
  399. }
  400. if (data.borderThickness !== undefined) style.lineWidth = data.borderThickness;
  401. if (data.borderColor !== undefined)
  402. {
  403. // Convert to rgba.
  404. var alpha = 1;
  405. if (style.lineWidth === 0) alpha = 0
  406. style.strokeStyle = ia.Color.toRGBA(data.borderColor, alpha);
  407. }
  408. layer.style = style;
  409. }
  410. // WMS / AGS layers.
  411. if (data.url !== undefined) layer.url = data.url;
  412. if (data.layers !== undefined) layer.layers = data.layers;
  413. if (data.srs !== undefined) layer.srs = data.srs;
  414. if (data.version !== undefined) layer.version = data.version;
  415. if (data.params !== undefined) layer.params = data.params;
  416. if (data.requiresAxisSwitch !== undefined) layer.requiresAxisSwitch = data.requiresAxisSwitch;
  417. // Tile layers
  418. if (data.minExtent !== undefined) layer.minExtent = data.minExtent;
  419. if (data.maxExtent !== undefined) layer.maxExtent = data.maxExtent;
  420. };
  421.  
  422. /**
  423. * Loads the visible data layers.
  424. *
  425. * @method loadVisibleLayers
  426. */
  427. ia.MapData.prototype.loadVisibleLayers = function()
  428. {
  429. this._layerCount++;
  430. var me = this;
  431.  
  432. // Ensures all layers are loaded before moving on.
  433. if (this._visibleLayers.length > this._layerCount)
  434. {
  435. var layer = this._visibleLayers[this._layerCount];
  436. layer.addEventListener(ia.Event.LAYER_READY, function ()
  437. {
  438. me.loadVisibleLayers();
  439. });
  440. layer.loadSource();
  441. }
  442. else
  443. {
  444. // callback function
  445. this._callbackFnc.call(null, this);
  446. me.dispatchEvent(new ia.DataEvent(ia.DataEvent.MAP_DATA_CHANGED, me));
  447. }
  448. };