1XA.component.map = (function ($, document) { 2 3 "use strict"; 4 5 var api = {}, 6 maps = [], 7 searchEndpoint, 8 searchResultsSignatures = [], 9 key, 10 urlHelperModel, 11 apiModel, 12 queryModel, 13 mapsConnector, 14 scriptsLoaded = false, 15 initialize, 16 searchResults, 17 pushMapData, 18 resultsLoaded, 19 myLocationChanged, 20 myLocationData, 21 mapViews = [], 22 MapModel, 23 MapView; 24 25 resultsLoaded = function (data) { 26 searchResults = data; 27 }; 28 29 myLocationChanged = function (data) { 30 myLocationData = data; 31 }; 32 33 initialize = function () { 34 var i, mapsCount = maps.length; 35 for (i = 0; i < mapsCount; i++) { 36 //crate Backbone.js views - one view per component on the page 37 mapViews.push(new MapView({el: maps[i], model: new MapModel()})); 38 } 39 if (typeof (XA.component.search) !== "undefined") { 40 pushMapData(); 41 } 42 }; 43 44 pushMapData = function() { 45 var notInitializedMaps, 46 resultsExists = typeof searchResults !== "undefined", 47 myLocationExists = typeof myLocationData !== "undefined"; 48 49 if (resultsExists || myLocationExists) { 50 //in case that results were loaded before initialization of view and model, trigger another event with 51 //previously loaded results 52 //this will happen just once - while initialization 53 //remember about checking if all maps are already rendered 54 notInitializedMaps = mapViews.filter(function (view) { 55 if (view.model.get("showed") === false) { 56 return true; 57 } 58 return false; 59 }); 60 61 if (notInitializedMaps.length > 0) { 62 setTimeout(pushMapData, 1000); 63 } else { 64 if (resultsExists) { 65 XA.component.search.vent.trigger("internal-results-loaded", searchResults); 66 } 67 if (myLocationExists) { 68 XA.component.search.vent.trigger("internal-my-location-coordinates-changed", myLocationData); 69 } 70 } 71 } 72 }; 73 74 MapModel = Backbone.Model.extend({ 75 defaults: { 76 dataProperties: {}, 77 dynamicPoiList: [], 78 showed: false, 79 myLocation: ["", ""], 80 id: null, 81 loadMore: false 82 }, 83 initialize: function() { 84 var sig = this.get("dataProperties").searchResultsSignature, 85 hash = queryModel.parseHashParameters(window.location.hash), 86 param = typeof (sig) !== "undefined" && sig !== "" ? sig + "_g" : "g"; 87 88 if (typeof (XA.component.search) !== "undefined") { 89 XA.component.search.vent.on("results-loaded", this.updateDynamicPoiList.bind(this)); 90 XA.component.search.vent.on("internal-results-loaded", this.updateDynamicPoiList.bind(this)); 91 XA.component.search.vent.on("my-location-coordinates-changed", this.changeMyLocation.bind(this)); 92 XA.component.search.vent.on("internal-my-location-coordinates-changed", this.changeMyLocation.bind(this)); 93 XA.component.search.vent.on("hashChanged", this.hashChanged.bind(this)); 94 } 95 96 if (hash.hasOwnProperty(param) && hash[param] !== "") { 97 //if Location Filter component is on the page it could already fill "g" hash parameter 98 this.set("myLocation", hash[param].split("|")); 99 } 100 }, 101 getPoiVariant: function (poiTypeId, poiVariantId) { 102 var mapping = this.get("dataProperties").typeToVariantMapping, 103 typeId; 104 105 if (typeof poiTypeId !== "undefined" && poiTypeId != null) { 106 typeId = "{" + poiTypeId.toUpperCase() + "}"; 107 if (mapping.hasOwnProperty(typeId)) { 108 return mapping[typeId]; 109 } else { 110 return poiVariantId; 111 } 112 } 113 return poiVariantId; 114 }, 115 updateDynamicPoiList: function(searchResults) { 116 var dynamicPoiList = [], 117 signature = this.get("dataProperties").searchResultsSignature, 118 geolocationData = searchResults.data.filter(function (result) { 119 if (result.hasOwnProperty("Geospatial")) { 120 return true; 121 } else { 122 return false; 123 } 124 }), 125 i, 126 poi; 127 128 if (signature !== searchResults.searchResultsSignature) { 129 return; 130 } 131 132 //save information that those POIs comes from load more action
133 this.set("loadMore", searchResults.loadMore); 134 135 for (i = 0; i < geolocationData.length; i++) { 136 poi = geolocationData[i]; 137 138 //don't show POIs which doesn't have Latitude and Longitude 139 if (poi.Geospatial.Latitude === 0 || poi.Geospatial.Longitude === 0) { 140 continue; 141 } 142 143 dynamicPoiList.push({ 144 id: poi.Id, 145 type: "Dynamic", 146 title: poi.Name, 147 latitude: poi.Geospatial.Latitude, 148 longitude: poi.Geospatial.Longitude, 149 icon: poi.Geospatial.PoiIcon, 150 poiTypeId: poi.Geospatial.PoiTypeId, 151 poiVariantId: this.getPoiVariant(poi.Geospatial.PoiTypeId, poi.Geospatial.PoiVariantId) 152 }); 153 } 154 155 this.set("dynamicPoiList", dynamicPoiList); 156 }, 157 changeMyLocation: function (myLocationData) { 158 var sig = this.get("dataProperties").searchResultsSignature; 159 if (sig === myLocationData.sig) { 160 this.set("myLocation", myLocationData.coordinates); 161 } 162 }, 163 hashChanged: function (hash) { 164 var sig = this.get("dataProperties").searchResultsSignature, 165 location = hash[sig !== "" ? sig + "_g" : "g"], 166 myLocationDataSignature = typeof myLocationData !== "undefined" ? myLocationData.sig : "", 167 parts; 168 169 if (sig === myLocationDataSignature && typeof location !== "undefined" && location !== null && location !== "") { 170 parts = location.split("|"); 171 if (parts.length > 1) { 172 this.set("myLocation", [parts[0], parts[1]]); 173 } 174 } 175 } 176 }); 177 178 MapView = Backbone.View.extend({ 179 initialize : function () { 180 var dataProperties = this.$el.data(), 181 properties = dataProperties.properties; 182 183 if (this.model) { 184 this.model.set({dataProperties: properties}); 185 this.model.set({id: this.$el.find(".map-canvas").prop("id")}); 186 } 187 188 this.render(); 189 this.model.on("change:dynamicPoiList", this.renderDynamicPois, this); 190 this.model.on("change:myLocation", this.updateMyLocationPoi, this); 191 if (typeof (XA.component.search) !== "undefined") { 192 XA.component.search.vent.on("center-map", this.handleCenterMap.bind(this)); 193 } 194 this.updateMyLocationPoi(); 195 196 }, 197 render : function () { 198 var that = this, 199 showed = this.model.get("showed"), 200 canvas = document.getElementById(this.model.get("id")); 201 202 if (!showed && canvas !== null) { 203 this.getCentralPoint(function (viewBounds, ctx) { 204 if (typeof viewBounds !== "undefined") { 205 var context = typeof ctx !== "undefined" ? ctx : this, 206 id = context.model.get("id"), 207 properties = context.model.get("dataProperties"), 208 mapOptions = { 209 canvasId: id, 210 zoom: typeof(properties.zoom) === "number" ? properties.zoom : context.parseZoom(properties.zoom, 15), 211 mode: properties.mode, 212 poiCount: properties.pois.length, 213 key: properties.key, 214 disableMapScrolling: properties.disableMapScrolling, 215 disableMapZoomOnScroll: properties.disableMapZoomOnScroll 216 }; 217 218 mapsConnector.showMap(id, mapOptions, viewBounds); 219 context.renderPoiList(id, properties.pois); 220 221 context.model.set("showed", true); 222 } 223 }); 224 } 225 }, 226 renderDynamicPois: function() { 227 var dataProperties = this.model.get("dataProperties"), 228 dynamicPoiList = this.model.get("dynamicPoiList"), 229 properties = this.model.get("dataProperties"), 230 id = this.model.get("id"), 231 i; 232 233 if (!this.model.get("loadMore")) { 234 mapsConnector.clearMarkers(id); 235 } 236 237 for (i = 0; i < dynamicPoiList.length; i++) { 238 mapsConnector.renderDynamicPoi(id, dynamicPoiList[i], this.getGeoPoiContent.bind(this)); 239 } 240 241 //if user want to see all POIs then after adding dynamic POIs we have to recalculate map center point 242 if (dataProperties.centralPointMode === "MidOfPoi") { 243 mapsConnector.updateMapPosition(this.model.get("id"), this.parseZoom(properties.zoom, 15)); 244 } 245 }, 246 renderPoiList: function(mapId, poiList) { 247 var i, 248 poi, 249 myLocation, 250 poiCount = poiList.length, 251 properties = this.model.get("dataProperties"), 252 sig = properties.searchResultsSignature, 253 hash = queryModel.parseHashParameters(window.location.hash), 254 param = sig !== "" ? sig + "_g" : "g"; 255 256 for (i = 0; i < poiCount; i++) { 257 poi = poiList[i]; 258 259 if (poi.Type === "MyLocation") { 260 myLocation = this.model.get("myLocation"); 261 poi.Latitude = myLocation[0]; 262 poi.Longitude = myLocation[1]; 263 264 if (!hash.hasOwnProperty(param) || (hash.hasOwnProperty(param) && hash[param] === "")) { 265 //if there is no "g" param then it's mean that there is no Location Filter on the map 266 //in this case we have take coordinated from the browser to display My Location POI 267 this.getCurrentPosition(function (coordinates) { 268 this.model.set("myLocation", coordinates); 269 }); 270 } else if (hash.hasOwnProperty(param)) { 271 this.model.set("myLocation", hash[param].split("|")); 272 } 273 } else if (poi.Latitude === "" || poi.Longitude === "") { 274 continue; 275 } 276 277 mapsConnector.renderPoi(mapId, { 278 id: poi.Id.Guid, 279 title: poi.Title, 280 description: poi.Description, 281 latitude: poi.Latitude, 282 longitude: poi.Longitude, 283 icon: poi.PoiIcon, 284 html: poi.Html, 285 type: poi.Type 286 }); 287 } 288 }, 289 getPoiContent: function(poiId, poiTypeId, poiVariantId, renderPoiContentCallback) { 290 var properties = this.model.get("dataProperties"), 291 url = urlHelperModel.createGetPoiContentUrl({endpoint: properties.variantsEndpoint}, poiId, poiVariantId); 292 293 apiModel.getData({ 294 callback: renderPoiContentCallback, 295 url: url, 296 excludeSiteName: true 297 }); 298 }, 299 getGeoPoiContent: function (poiId, poiTypeId, poiVariantId, renderPoiContentCallback) { 300 var myLocation = this.model.get("myLocation"), 301 latitude = myLocation[0], 302 longitude = myLocation[1], 303 properties = this.model.get("dataProperties"), 304 hash = queryModel.parseHashParameters(window.location.hash), 305 units = hash.o, 306 url = urlHelperModel.createGetGeoPoiContentUrl({ endpoint: properties.variantsEndpoint }, poiId, poiVariantId, latitude + "," + longitude, units, properties.itemId); 307 308 apiModel.getData({ 309 callback: renderPoiContentCallback, 310 url: url, 311 excludeSiteName: true 312 }); 313 314 }, 315 getCentralPoint: function (callback) { 316 var properties = this.model.get("dataProperties"), 317 that = this; 318 319 switch (properties.centralPointMode) { 320 case "Auto": { 321 if (properties.centralPoint !== "") { 322 callback.call(that, [properties.latitude, properties.longitude]); 323 } else if (properties.pois.length > 0) { 324 callback.call(that, [properties.pois[0].Latitude, properties.pois[0].Longitude]); 325 } else { 326 this.getCurrentPosition(callback); 327 } 328 break; 329 } 330 case "MidOfPoi": { 331 callback.call(that, this.getPoisCentralPoint()); 332 break; 333 } 334 case "Location":{ 335 this.getCurrentPosition(callback); 336 break; 337 } 338 } 339 }, 340 getCurrentPosition: function (callback) { 341 var that = this; 342 XA.component.locationService.detectLocation( 343 function (location) { 344 callback.call(that, location, that); 345 }, 346 function (errorMessage) { 347 callback.call(that, [0, 0], that); 348 console.log(errorMessage); 349 } 350 ); 351 }, 352 getPoisCentralPoint: function () { 353 var i, 354 poi, 355 poisCoords = [], 356 myLocation = this.model.get("myLocation"), 357 properties = this.model.get("dataProperties"), 358 count = properties.pois.length; 359 360 for (i = 0; i < count; i++) { 361 poi = properties.pois[i]; 362 if (poi.TemplateId.Guid === "7dd9ece5-9461-498d-8721-7cbea8111b5e") { 363 if (myLocation[0] !== "" && myLocation[1] !== "") { 364 poi.Latitude = myLocation[0]; 365 poi.Longitude = myLocation[1]; 366 this.model.set("dataProperties", properties); 367 poisCoords.push({latitude: poi.Latitude, longitude: poi.Longitude}); 368 } 369 } else { 370 poisCoords.push({latitude: poi.Latitude, longitude: poi.Longitude}); 371 } 372 } 373 374 return mapsConnector.getCentralPoint(poisCoords);
375 }, 376 handleCenterMap: function (data) { 377 var centerMap = this.model.get("dataProperties").centerOnFoundPoi === "1", 378 animate = this.model.get("dataProperties").animateFoundPoi === "1"; 379 this.centerOnMap(data, centerMap, animate); 380 }, 381 centerOnMap: function (data, centerMap, animate) { 382 if (data.sig === this.model.get("dataProperties").searchResultsSignature) { 383 mapsConnector.centerMap(this.model.get("id"), data, centerMap, animate); 384 } 385 }, 386 updateMyLocationPoi: function () { 387 var properties = this.model.get("dataProperties"), 388 myLocation = this.model.get("myLocation"); 389 390 //check if there is something in my location 391 if (myLocation[0] !== "" && myLocation[1] !== 0) { 392 //my location was changed so update position of My Location marker 393 mapsConnector.updateMyPoiLocation(this.model.get("id"), myLocation, this.parseZoom(properties.zoom, 15)); 394 } else if (properties.latitude !== "" && properties.longitude !== "") { 395 var data = {}; 396 data.sig = properties.searchResultsSignature; 397 data.coordinates = [properties.latitude, properties.longitude]; 398 this.centerOnMap(data, true, false); 399 } 400 }, 401 parseZoom: function (str, defaultValue) { 402 var retValue = defaultValue; 403 if(str !== null) { 404 if(str.length > 0) { 405 if (!isNaN(str)) { 406 retValue = parseInt(str); 407 } 408 } 409 } 410 return retValue; 411 } 412 }); 413 414 api.init = function() { 415 var i, 416 mapElements = $(".map.component:not(.initialized)"), 417 count = mapElements.length; 418 419 if (typeof (XA.component.search) !== "undefined") { 420 queryModel = XA.component.search.query; 421 urlHelperModel = XA.component.search.url; 422 apiModel = XA.component.search.ajax; 423 424 //if the page was reloaded there could be situation that search results will load results faster then map initialization 425 //so that we have to save them and pass to the models when they will be created 426 XA.component.search.vent.on("results-loaded", resultsLoaded); 427 //the same with "my location", sometimes Location Filter component can change location before map was initialized 428 XA.component.search.vent.on("my-location-coordinates-changed", myLocationChanged); 429 } 430 mapsConnector = XA.connector.mapsConnector; 431 432 if (count > 0) { 433 for (i = 0; i < count; i++) { 434 var $map = $(mapElements[i]); 435 var properties = $map.data("properties"); 436 key = properties.key; 437 searchEndpoint = properties.endpoint; 438 searchResultsSignatures.push(properties.searchResultsSignature) 439 $map.addClass("initialized"); 440 maps.push($map); 441 } 442 443 if (!scriptsLoaded) { 444 mapsConnector.loadScript(key, XA.component.map.scriptsLoaded); 445 } else { 446 initialize(); 447 } 448 } 449 }; 450 451 api. scriptsLoaded = function() { 452 console.log("Maps api loaded"); 453 scriptsLoaded = true; 454 initialize(); 455 }; 456 457 api.getSearchEndpoint = function() { 458 return searchEndpoint; 459 }; 460 461 api.getSignatures = function() { 462 return searchResultsSignatures; 463 } 464 465 return api; 466 467}(jQuery, document)); 468 469XA.register("map", XA.component.map);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.