1var WPCM = (function (WPCM, $) { 2 // Window Completely Loaded 3 $(window).on("load", function () { 4 // Initialize models, collections, and views 5 WPCM.Locations = new WPCM.Collections.Locations(); 6 7 if ($("#closest_location").length) { 8 WPCM.User = new WPCM.Models.User(); 9 WPCM.ClosestLocation = new WPCM.Views.ClosestLocation({ 10 el: "#closest_location", 11 model: WPCM.User, 12 }); 13 } 14 15 if ($("#wpcm_zip").length) { 16 WPCM.LocationSearch = new WPCM.Views.SearchByZip({ 17 el: $("#wpcm_zip"), 18 collection: WPCM.Locations, 19 }); 20 } 21 22 if ($("#map").length) { 23 // Initialize Map 24 WPCM.Map = new WPCM.Views.Map({ 25 el: $("#map"), 26 collection: WPCM.Locations, 27 }); 28 29 if ($("#locations_list").length) { 30 WPCM.List = new WPCM.Views.List({ 31 el: $("#locations_list"), 32 collection: WPCM.Locations, 33 }); 34 } 35 36 if (typeof WPCM_LOCATION_ID !== "undefined") { 37 // Single location map 38 WPCM.Locations.fetch({ 39 data: { 40 location_id: WPCM_LOCATION_ID, 41 }, 42 }); 43 } else { 44 const urlParams = new URLSearchParams(window.location.search); 45 const wpcmZipcode = urlParams.get('zipcode'); 46 const wpcmDivision = urlParams.get('division'); 47 48 WPCM.Locations.fetch({ 49 data: { 50 zipcode: wpcmZipcode, 51 division: wpcmDivision, 52 }, 53 reset: true, 54 success: function (collection, response, options) { 55 WPCM.Locations.originalModels = collection.toJSON(); 56 WPCM.Locations.originalCollection = 57 new Backbone.Collection( 58 WPCM.Locations.originalModels 59 ); 60 61 $(document).trigger("cm:initial-locations-fetch"); 62 }, 63 }); 64 } 65 66 // Fake Marker 67 WPCM.ActiveLocation = new WPCM.Models.ActiveLocation(); 68 WPCM.FakeMarker = new WPCM.Views.FakeMarker({ 69 el: $(".js-fake-map-infowindow"), 70 model: WPCM.ActiveLocation, 71 }); 72 } 73 74 // NOTE: Custom filter trigger 75 $(document).on("cm:filter-by-id", (e, location_id) => { 76 WPCM.Locations.fetch({ 77 data: { 78 location_id: location_id, 79 }, 80 }); 81 }); 82 83 $(document).on("cm:filter-by-division", (e, division_id) => { 84 WPCM.Locations.fetch({ 85 data: { 86 division: division_id, 87 }, 88 }); 89 }); 90 }); 91 92 /** 93 * FEDS - No Need to Edit This Section 94 */ 95 WPCM.Models = WPCM.Models || {}; 96 WPCM.Collections = WPCM.Collections || {}; 97 WPCM.Views = WPCM.Views || {}; 98 WPCM = _.extend(WPCM, Backbone.Events); 99 100 WPCM.Models.Location = Backbone.Model.extend({ 101 urlRoot: "/wp-json/wpcm-locations/vl/view", 102 103 default: { 104 title: "", 105 address: "", 106 phone: "", 107 directions: "", 108 url: "", 109 hours: "", 110 }, 111 }); 112 113 WPCM.Models.User = Backbone.Model.extend({ 114 default: { 115 geo: { 116 latitude: 0, 117 longitude: 0, 118 }, 119 location: "", 120 }, 121 122 initialize: function () { 123 this.on("change:geo", this._setClosestLocation, this); 124 $(document).on( 125 "click", 126 "#get_geolocation", 127 $.proxy(this.getLocation, this) 128 ); 129 this.maybeSetLocation(); 130 }, 131 132 maybeSetLocation: function () { 133 // Checks PFX and cookie for geo info to set closest location 134 if (_.isEmpty(this.get("geo"))) { 135 if ( 136 typeof PersonalizeFX !== "undefined" && 137 typeof PersonalizeFX.uLoc.lat !== "undefined" 138 ) { 139 this.set("geo", { 140 latitude: PersonalizeFX.uLoc.lat, 141 longitude: PersonalizeFX.uLoc.lng, 142 }); 143 } else { 144 if (typeof Cookies.get("wpcm-geo") !== "undefined") { 145 const pos = Cookies.getJSON("wpcm-geo"); 146 this._setLocation({ 147 coords: { 148 latitude: pos.latitude, 149 longitude: pos.longitude, 150 }, 151 }); 152 } 153 } 154 } 155 if (!_.isEmpty(this.get("geo"))) { 156 this._setClosestLocation(); 157 } 158 }, 159 160 getLocation: function (e) { 161 e.preventDefault(); 162 this.askForLocation(); 163 }, 164 165 askForLocation: function () { 166 if (navigator.geolocation) { 167 navigator.geolocation.getCurrentPosition( 168 _.bind(this._setLocation, this), 169 _.bind(this._locationError) 170 ); 171 } else { 172 console.log("Geolocation is not supported in this browser."); 173 WPCM.trigger("User/Location/Error"); 174 } 175 }, 176 177 _setLocation: function (pos) { 178 if (typeof Cookies.get("wpcm-geo") == "undefined") { 179 Cookies.set( 180 "wpcm-geo", 181 { 182 latitude: pos.coords.latitude, 183 longitude: pos.coords.longitude, 184 }, 185 { expires: 30 } 186 ); 187 } 188 this.set("geo", { 189 latitude: pos.coords.latitude, 190 longitude: pos.coords.longitude, 191 }); 192 }, 193 194 _locationError: function (err) { 195 console.log(err); 196 console.warn("ERROR(" + err.code + "): " + err.message); 197 WPCM.trigger("User/Location/Error"); 198 }, 199 200 _setClosestLocation: function () { 201 const self = this; 202 // Fetch closest location, set cookie 203 if (typeof Cookies.get("wpcm-closest") == "undefined") { 204 $.get("/wp-json/wpcm-locations/v1/closest", { 205 latitude: this.get("geo").latitude, 206 longitude: this.get("geo").longitude, 207 }).done(function (response) { 208 self.set("location", response); 209 Cookies.set("wpcm-closest", response, { expires: 30 }); 210 }); 211 } else { 212 this.set("location", Cookies.getJSON("wpcm-closest")); 213 } 214 }, 215 }); 216 217 /** 218 * Active Location 219 */ 220 WPCM.Models.ActiveLocation = Backbone.Model.extend({ 221 defaults: { 222 location: null, 223 }, 224 }); 225 226 WPCM.Collections.Locations = Backbone.Collection.extend({ 227 url: "/wp-json/wpcm-locations/v1/view", 228 model: WPCM.Models.Location, 229 230 initialize: function () { 231 this.originalModels = []; 232 this.originalCollection = []; 233 }, 234 235 filter: function (filterVal) { 236 const filtered = this.originalCollection.filter(function ( 237 location 238 ) { 239 return _.contains(location.get("filteredAttribute"), filterVal); 240 }); 241 this.reset(filtered); 242 }, 243 244 clearFilter: function () { 245 this.reset(this.originalModels); 246 }, 247 }); 248 249 /**
250 * Renders the Marker Info Window Html 251 */ 252 WPCM.Views.Marker = Backbone.View.extend({ 253 template: null, 254 255 initialize: function () { 256 this.template = _.template($("#markerTemplate").html()); 257 }, 258 259 render: function () { 260 this.$el.html(this.template(this.model.toJSON())); 261 return this; 262 }, 263 }); 264 265 /** 266 * Renders out the Google Map 267 */ 268 WPCM.Views.Map = Backbone.View.extend({ 269 map: null, 270 infoWindow: null, 271 filterView: null, 272 markers: [], 273 274 defaults: { 275 // MAP STYLING: replace [] with the JS array from Snazzy Maps 276 styles: [], 277 mapTypeId: google.maps.MapTypeId.ROADMAP, 278 restriction: { 279 latLngBounds: { 280 north: 85, 281 south: -85, 282 west: -180, 283 east: 180, 284 }, 285 strictBounds: true, 286 } 287 }, 288 289 initialize: function (options) { 290 this.setElement(options.el); 291 this.map = new google.maps.Map( 292 document.getElementById("map"), 293 this.defaults 294 ); 295 this.infoWindow = new google.maps.InfoWindow({ content: "" }); 296 // Add Listeners to the Locations Collection 297 this.listenTo(this.collection, "reset", this.render); 298 this.listenTo(this.collection, "sync", this.render); 299 }, 300 301 addMarker: function (location, options = {}) { 302 const attrs = location.toJSON(), 303 self = this; 304 if (attrs.lat == "" || attrs.lng == "") { 305 //empty lat/lng from say a no-address location from the client, breaks the bounds 306 console.log(attrs); 307 return; 308 } 309 if ( 310 attrs.exclude_from_map && 311 !(options && options.singular_location) 312 ) { 313 const singular = 314 typeof WPCM_LOCATION_ID !== "undefined" && 315 String(attrs.id) === String(WPCM_LOCATION_ID); 316 if (!singular) { 317 return; 318 } 319 } 320 321 let pinType = "black"; 322 if (attrs.color_scheme) { 323 pinType = attrs.color_scheme; 324 } 325 326 const position = new google.maps.LatLng(attrs.lat, attrs.lng), 327 marker = new google.maps.Marker({ 328 animation: google.maps.Animation.DROP, 329 position: position, 330 title: attrs.post.post_title, 331 icon: { 332 url: `${WPCM.plugin_url}assets/img/map-pin-${pinType}.png`, 333 }, 334 }); 335 marker.setMap(this.map); 336 this.markers.push(marker); 337 this.bounds.extend(marker.position); 338 google.maps.event.addListener(marker, "click", function () { 339 self.infoWindow.setContent( 340 new WPCM.Views.Marker({ model: location }).render().el 341 ); 342 self.infoWindow.open(self.map, this); 343 344 // Update Active Location 345 WPCM.ActiveLocation.set("location", location); 346 }); 347 }, 348 349 render: function (collection) { 350 this.removeMarkers(); 351 this.bounds = new google.maps.LatLngBounds(); 352 if (!collection.isEmpty()) { 353 const singularPage = 354 typeof WPCM_LOCATION_ID !== "undefined" && 355 collection.length === 1; 356 collection.each( 357 function (loc) { 358 this.addMarker(loc, { 359 singular_location: singularPage, 360 }); 361 }, 362 this 363 ); 364 this.map.setCenter(this.bounds.getCenter()); 365 if (typeof WPCM_LOCATION_ID !== "undefined") { 366 // Single-location pages: keep a regional view. 367 // fitBounds on one marker zooms to street level. 368 const setSingleLocationZoom = () => { 369 this.map.setZoom(9); 370 }; 371 setSingleLocationZoom(); 372 google.maps.event.addListenerOnce( 373 this.map, 374 "idle", 375 setSingleLocationZoom 376 ); 377 } else { 378 this.map.fitBounds(this.bounds); 379 } 380 381 if (!_.isEmpty(WPCM.action.display)) { 382 const marker = _.findWhere(this.markers, { 383 title: WPCM.action.display, 384 }); 385 if (typeof marker !== "undefined") { 386 google.maps.event.trigger(marker, "click"); 387 this.map.setCenter(marker.getPosition()); 388 } 389 } 390 391 // If there's only one marker, automatically open infobox 392 if (1 === collection.length) { 393 google.maps.event.trigger(this.markers[0], "click"); 394 } 395 396 if ('1' == WPCM.group_clusters) { 397 const clusterSVG = window.btoa(`<svg fill="#000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240"> 398 <circle cx="120" cy="120" opacity=".6" r="70"></circle> 399 <circle cx="120" cy="120" opacity=".3" r="90"></circle> 400 <circle cx="120" cy="120" opacity=".2" r="110"></circle> 401 </svg>`); 402 403 // NOTE: Special case from this edit -> https://madeline.webfxph.com/website-thread/3606/?access_token=3b9f7856462f44bb8ad332ef4aad7276 404 const clusteredMarkers = this.markers.filter(marker => { 405 return marker.title.toLowerCase().includes('bronx'); 406 }); 407 408 const markerCluster = new markerClusterer.MarkerClusterer({ 409 map: this.map, 410 markers: clusteredMarkers, 411 renderer: { 412 render: ({ markers, _position: position }) => { 413 const markersCount = markers.length; 414 return new google.maps.Marker({ 415 position, 416 icon: { 417 url: `data:image/svg+xml;base64,${clusterSVG}`, 418 scaledSize: new google.maps.Size(60, 60), 419 }, 420 label: { 421 text: String(markersCount), 422 color: "#fff", 423 }, 424 zIndex: 1000 + markersCount, 425 }); 426 }, 427 }, 428 }); 429 } 430 } 431 return this; 432 }, 433 434 addModelToMap: function () { 435 const attrs = this.model.toJSON(); 436 const singularLocation = 437 typeof WPCM_LOCATION_ID !== "undefined" && 438 String(attrs.id) === String(WPCM_LOCATION_ID); 439 this.addMarker(this.model, { 440 singular_location: singularLocation, 441 }); 442 this.map.setCenter(new google.maps.LatLng(attrs.lat, attrs.lng)); 443 }, 444 445 removeMarkers: function () { 446 const self = this; 447 for (let i = 0; i < this.markers.length; i++) { 448 self.markers[i].setMap(null); 449 } 450 this.markers = []; 451 }, 452 }); 453 454 /**
455 * Renders out the List of locations 456 */ 457 WPCM.Views.List = Backbone.View.extend({ 458 template: null, 459 460 initialize: function (options) { 461 this.setElement(options.el); 462 this.listenTo(this.collection, "sync", this.render); 463 this.listenTo(this.collection, "reset", this.render); 464 }, 465 466 render: function (collection) { 467 this.$el.empty(); 468 if (!this.collection.isEmpty()) { 469 this.collection.each(this.addOne, this); 470 } else { 471 this.$el.append( 472 '<p class="col-sm-12 no-results">Sorry, we don\'t have any locations within your current search distance.</p>' 473 ); 474 } 475 return this; 476 }, 477 478 addOne: function (model) { 479 const item = new WPCM.Views.ListItem({ model: model }); 480 this.$el.append(item.render().el); 481 return this; 482 }, 483 }); 484 485 /** 486 * Renders each individual location in list 487 */ 488 WPCM.Views.ListItem = Backbone.View.extend({ 489 initialize: function (options) { 490 this.template = _.template($("#listItemTemplate").html()); 491 }, 492 493 render: function () { 494 this.setElement(this.template(this.model.toJSON())); 495 return this; 496 }, 497 }); 498 499 /** 500 * Renders out closest location widget 501 */ 502 WPCM.Views.ClosestLocation = Backbone.View.extend({ 503 template: null, 504 505 initialize: function (options) { 506 this.setElement(options.el); 507 this.template = _.template($("#closestLocationTemplate").html()); 508 this.model.on("change:location", this.render, this); 509 if (!_.isEmpty(this.model.get("location"))) { 510 this.render(); 511 } 512 }, 513 514 render: function (location) { 515 if (!_.isEmpty(this.model.get("location"))) { 516 this.$el.html(this.template(this.model.get("location"))); 517 } 518 return this; 519 }, 520 }); 521 522 /** 523 * Renders out closest location from zipcode 524 */ 525 WPCM.Views.SearchByZip = Backbone.View.extend({ 526 initialize: function (options) { 527 this.setElement(options.el); 528 if (!_.isEmpty(WPCM.action.zipcode)) { 529 this.$el.find(".wpcm-zip__form").trigger("submit"); 530 } 531 }, 532 533 events: { 534 "submit .wpcm-zip__form": "onSubmit", 535 }, 536 537 onSubmit: function (event) { 538 event.preventDefault(); 539 const zipcode = this.$el.find(".wpcm-zip__zipcode").val(); 540 const distance = this.$el.find(".wpcm-zip__distance").val(); 541 const imahuman = this.$el.find("#imahuman").val(); 542 const division = this.$el.find(".wpcm-zip__division").val(); 543 544 const data = { 545 zipcode: zipcode, 546 distance: distance, 547 imahuman: imahuman, 548 division: division, 549 }; 550 551 this.collection.fetch({ 552 reset: true, 553 data, 554 }); 555 556 this.syncFiltersToQueryString(data); 557 }, 558 559 syncFiltersToQueryString({ 560 zipcode, 561 division 562 }) { 563 const url = new URL(window.location.href); 564 url.searchParams.set('zipcode', zipcode); 565 url.searchParams.set('division', division); 566 history.pushState(null, '', url); 567 } 568 }); 569 570 WPCM.Views.FakeMarker = Backbone.View.extend({ 571 initialize: function () { 572 this.template = _.template($("#markerTemplate").html()); 573 this.listenTo(this.model, "change", this.render); 574 }, 575 576 render: function () { 577 this.$el.html(this.template(this.model.get("location").toJSON())); 578 return this; 579 }, 580 }); 581 582 return WPCM; 583})(WPCM || {}, jQuery);
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.