1/** 2 * 3 * simply-rets-client.js - Copyright (c) 2014-2015 SimplyRETS 4 * 5 * This file provides the client side javascript for the 6 * SimplyRETS Wordpress plugin. 7 * 8 * License: GPLv3 (http://www.gnu.org/licenses/gpl.html) 9 * 10**/ 11 12 13var $_ = jQuery; // reassign jQuery 14 15 16/* Single Listing Details Image Slider (Classic) */ 17var classicGalleryToggle = function() { 18 19 $_(".sr-slider-input").click(function() { 20 21 var imgSrc = $_("input[name='slide_switch']:checked").val(); 22 var imgAct = $_(".sr-slider-img-act"); 23 24 imgAct.fadeOut("fast", function() { 25 26 imgAct.attr('src', imgSrc); 27 imgAct.fadeIn("fast"); 28 29 }); 30 31 }); 32 33}; 34 35 36/* Open/Close Listing Image Gallery (Classic) */ 37var classicGalleryTextToggle = function() { 38 39 $_('#sr-toggle-gallery').click(function() { 40 $_('.sr-slider label').toggle(100); 41 if($_(this).text() == 'Hide photos') { 42 $_(this).text('Show more photos'); 43 } else { 44 $_(this).text('Hide photos'); 45 } 46 }); 47 48}; 49 50 51/** Hide 'Amenities' in advanced search form when "Land" is selected */ 52var advSearchFormToggler = function() { 53 54 if($_('#sr-search-ptype select').val() == 'Land') { 55 $_('.sr-adv-search-amenities-wrapper').hide(); 56 } 57 58 $_('#sr-search-ptype select').change(function() { 59 if($_(this).val() == 'Land') { 60 $_('.sr-adv-search-amenities-wrapper').hide(); 61 $_('input[name="sr_features[]"]').each(function() { 62 $_(this).attr('checked', false); 63 }); 64 } else { 65 $_('.sr-adv-search-amenities-wrapper').show(); 66 } 67 }); 68 69}; 70 71 72 73/** [sr_listings_slider] default number of items */ 74var listingSliderCarousel = function() { 75 76 $_(".sr-listing-carousel").each(function() { 77 $_(this).owlCarousel({ items: 4 }) 78 }); 79 80} 81 82 83var scrollToAnchor = function(aid) { 84 var aTag = $_("#"+ aid); 85 $_('html,body').animate({scrollTop: aTag.offset().top},'slow'); 86} 87 88 89var buildPrettyLink = function(mlsId, address, root, vendor) { 90 return root 91 + "/listings/" 92 + mlsId + "/" 93 + address 94 + (vendor ? ("?sr_vendor=" + vendor) : ""); 95} 96 97var buildUglyLink = function(mlsId, address, root, vendor) { 98 return root 99 + "?sr-listings=sr-single" 100 + "&listing_id=" + mlsId 101 + "&listing_title=" + address 102 + (vendor ? ("&sr_vendor=" + vendor) : ""); 103} 104 105var normalizeListingPhotoUrl = function(url) { 106 var forceHttps = document 107 .getElementById("sr-map-search") 108 .dataset 109 .forceImageHttps 110 111 if (forceHttps) { 112 return url.replace(/^http:\/\//i, 'https://') 113 } else { 114 return url 115 } 116} 117 118 119var genMarkerPopup = function( 120 listing, 121 linkStyle, 122 siteRoot, 123 idxImg, 124 officeOnThumbnails, 125 agentOnThumbnails, 126 statusText, 127 mlsTrademark, 128 vendor 129) { 130 131 var stat = statusText ? listing.mls.statusText : listing.mls.status; 132 var mlsText = Boolean(mlsTrademark) ? "MLS®" : "MLS" 133 var beds = listing.property.bedrooms || "n/a"; 134 var baths = getBathroomsDisplay(); 135 var style = listing.property.style || "Res" ; 136 var type = listing.property.type || "Res"; 137 var sqft = listing.property.area || "n/a"; 138 var mlnum = listing.listingId || "n/a"; 139 var price = listing.listPrice || "Unknown"; 140 var addr = listing.address.full || "Unknown"; 141 var photo = listing.photos.length > 1 142 ? normalizeListingPhotoUrl(listing.photos[0]) 143 : 'https://s3-us-west-2.amazonaws.com/simplyrets/trial/properties/defprop.jpg'; 144 var office = officeOnThumbnails && listing.office.name 145 ? listing.office.name 146 : "" 147 var agent = agentOnThumbnails && listing.agent.firstName 148 ? listing.agent.firstName + ' ' + listing.agent.lastName 149 : "" 150 151 var link = linkStyle === "pretty" 152 ? buildPrettyLink(listing.mlsId, listing.address.full, siteRoot, vendor) 153 : buildUglyLink(listing.mlsId, listing.address.full, siteRoot, vendor); 154 155 var markup = '' + 156 '<div class="sr-iw-inner">' + 157 ' <h4 class="sr-iw-addr">' + addr + '<small> $' + price + '</small></h4>' + 158 ' <div class="sr-iw-inner__img">' + 159 ' <a href="' + link + '">' + 160 ' <img id="sr-iw-inner__img-img" src="' + photo +'">' + 161 ' </a>' + 162 ' </div>' + 163 ' <div class="sr-iw-inner__primary">' + 164 ' <p>' + beds + ' Beds | ' + baths + ' | ' + stat + '</p>' + 165 ' </div>' + 166 ' <hr>' + 167 ' <div class="sr-iw-inner__secondary">' + 168 ' <p><strong>Price: </strong>$' + price + '</p>' + 169 ' <p><strong>' + mlsText + ' #: </strong>' + mlnum + '</p>' + 170 ' <p><strong>Area: </strong>' + sqft + '</p>' + 171 ' <p><strong>Property Type: </strong>' + type + '</p>' + 172 ' <p><strong>Property Style: </strong>' + style + '</p>' +
173 (office ? '<p><strong>Listing office: </strong>'+ office + '</p>' : '') + 174 (agent ? '<p><strong>Listing agent: </strong>'+ agent + '</p>' : '') + 175 ' <img src="' + idxImg + '"/>' + 176 ' </div>' + 177 ' <hr>' + 178 ' <div class="sr-iw-inner__view-details">' + 179 ' <a class="sr-iw-inner__details-link" href="' + link + '">View Details</a>' + 180 ' </div>' + 181 '</div>'; 182 183 return markup; 184 185 function getBathroomsDisplay() { 186 if (listing.property.bathrooms) { 187 var s = listing.property.bathrooms > 1 ? "s" : ""; 188 return listing.property.bathrooms + " Bath" + s; 189 } else if (listing.property.bathsFull) { 190 var s = listing.property.bathsFull > 1 ? "s" : ""; 191 return listing.property.bathsFull + " Full Bath" + s; 192 } else { 193 return "n/a Baths"; 194 } 195 } 196} 197 198 199var makeMapMarkers = function( 200 map, 201 listings, 202 linkStyle, 203 siteRoot, 204 idxImg, 205 officeOnThumbnails, 206 agentOnThumbnails, 207 statusText, 208 mlsTrademark, 209 vendor 210) { 211 212 var markers = []; 213 var bounds = new google.maps.LatLngBounds(); 214 215 $_.each(listings, function(idx, listing) { 216 217 var lat = listing.geo.lat, 218 lng = listing.geo.lng; 219 220 if(lat && lng) { 221 222 var bound = new google.maps.LatLng(listing.geo.lat, listing.geo.lng); 223 224 var popup = genMarkerPopup( 225 listing, 226 linkStyle, 227 siteRoot, 228 idxImg, 229 officeOnThumbnails, 230 agentOnThumbnails, 231 statusText, 232 mlsTrademark, 233 vendor 234 ); 235 236 var window = new google.maps.InfoWindow({ 237 content: popup 238 }); 239 240 var marker = new google.maps.Marker({ 241 position: bound, 242 map: map, 243 title: listing.address.full 244 }); 245 246 marker.addListener('click', function() { 247 if(window.getMap()) { 248 window.close(map, marker); 249 } else { 250 window.open(map, marker); 251 } 252 }); 253 254 bounds.extend(bound); 255 markers.push(marker); 256 } 257 258 }); 259 260 return { 261 bounds: bounds, 262 markers: markers, 263 } 264 265} 266 267 268var replaceListingMarkup = function(markup) { 269 var root = $_('.sr-map-search-list-view'); 270 if(root.length) 271 root.html(markup); 272} 273 274 275var updatePagination = function(that) { 276 277 var prevEl = null, 278 nextEl = null, 279 pagWrapper = $_('.sr-pagination'); 280 281 if(pagWrapper.length) { 282 283 pagWrapper.empty(); // clear the current pagination elements 284 285 var prev = "<a href=\"#\">Prev</a> | "; 286 var next = "<a href=\"#\">Next</a>"; 287 288 var pag; 289 if(that.offset === 0) { 290 pag = next; 291 } else { 292 pag = prev + next; 293 } 294 295 if(that.offset === 0 && that.listings.length < that.limit) { 296 pag = null; 297 } 298 299 if(that.offset > 0 && that.listings.length < that.limit) { 300 pag = prev; 301 } 302 303 pagWrapper.append(pag); 304 305 var childs = pagWrapper.children(); 306 if(childs.length >= 1) { 307 $_.each(childs, function(c) { 308 if(childs[c].text === "Next") { 309 nextEl = childs[c]; 310 } 311 if(childs[c].text === "Prev") { 312 prevEl = childs[c]; 313 } 314 }); 315 } 316 } 317 318 return { 319 prev: prevEl, 320 next: nextEl 321 } 322} 323 324 325function normalizeParameters(params) { 326 var obj = {} 327 328 Object.keys(params).map(function(key) { 329 if (key === "subtypetext") 330 return obj.subTypeText = params[key] 331 if (key === "exteriorfeatures") 332 return obj.exteriorFeatures = params[key] 333 if (key === "mingaragespaces") 334 return obj.minGarageSpaces = params[key] 335 if (key === "maxgaragespaces") 336 return obj.maxGarageSpaces = params[key] 337 if (key === "salesagent") 338 return obj.salesAgent = params[key] 339 if (key === "speciallistingconditions") 340 return obj.specialListingConditions = params[key] 341 342 return obj[key] = params[key] 343 }) 344 345 return obj 346} 347 348var getSearchFormValues = function() { 349 350 var keyword = $_('.sr-int-map-search-wrapper #sr-search-keywords > input[type="text"]').val(), 351 ptype = $_('.sr-int-map-search-wrapper #sr-search-ptype select').val(), 352 minprice = $_('.sr-int-map-search-wrapper #sr-search-minprice input').val(), 353 maxprice = $_('.sr-int-map-search-wrapper #sr-search-maxprice input').val(), 354 minbeds = $_('.sr-int-map-search-wrapper #sr-search-minbeds input').val(), 355 maxbeds = $_('.sr-int-map-search-wrapper #sr-search-maxbeds input').val(), 356 minbaths = $_('.sr-int-map-search-wrapper #sr-search-minbaths input').val(), 357 maxbaths = $_('.sr-int-map-search-wrapper #sr-search-maxbaths input').val(), 358 sort = $_('.sr-int-map-search-wrapper .sr-sort-wrapper select').val(); 359 360 var defParamsData = document.getElementById("sr-map-search").dataset.defaultParameters 361 var defLimit = document.getElementById("sr-map-search").dataset.limit 362 363 var defParams; 364 try { 365 defParams = JSON.parse(defParamsData) 366 } catch(e) { 367 defParams = {} 368 } 369
370 // Merge the default parameters on the short-code with the 371 // user-selected parameters. If the user hasn't selected a value 372 // for an input, fallback to the default. 373 var params = Object.assign({}, normalizeParameters(defParams), { 374 q: keyword || defParams.q, 375 type: ptype || defParams.type, 376 sort: sort, 377 minprice: minprice || defParams.minprice, 378 maxprice: maxprice || defParams.maxprice, 379 minbeds: minbeds || defParams.minbeds, 380 maxbeds: maxbeds || defParams.maxbeds, 381 minbaths: minbaths || defParams.minbaths, 382 maxbaths: maxbaths || defParams.maxbaths, 383 }, { limit: defLimit }) 384 385 var query = "?"; 386 387 Object.keys(params).map(function(key) { 388 var p = params[key] 389 if (!p) return 390 391 if (p.indexOf(";") !== -1) { 392 p.split(";").map(function(v) { 393 var val = encodeURIComponent(v.trim()) 394 query += (key + "=" + val + "&") 395 }) 396 } else { 397 var val = encodeURIComponent(p.trim()) 398 query += (key + "=" + val + "&") 399 } 400 }) 401 402 return query 403} 404 405 406/** 407 * Our SimplyRETSMap Class 408 * Holds some state for working with the map: 409 */ 410function SimplyRETSMap() { 411 412 var vendor = document.getElementById('sr-map-search').dataset.vendor 413 var limit = document.getElementById('sr-map-search').dataset.limit 414 415 this.element = 'sr-map-search'; 416 this.bounds = []; 417 this.markers = []; 418 this.listings = []; 419 this.polygon = null; 420 this.rectangle = null; 421 this.popup = null; 422 this.drawCtrl = null; 423 this.loaded = false; 424 this.options = { zoom: 8 } 425 this.pagination = null; 426 this.offset = 0; 427 this.linkStyle = 'default'; 428 this.siteRoot = window.location.href 429 this.vendor = vendor; 430 this.limit = limit; 431 432 this.map = new google.maps.Map( 433 document.getElementById('sr-map-search'), this.options 434 ); 435 436 this.loadMsg = new google.maps.InfoWindow({ 437 map: null, 438 content: "Loading..." 439 }); 440 441 return this; 442} 443 444 445/** 446 * SimplyRETSMap prototype methods 447 */ 448 449 450/** `rec`: google.maps.OverlayType === RECTANGLE */ 451SimplyRETSMap.prototype.getRectanglePoints = function(rec) { 452 453 var latLngs = []; 454 var bounds = new google.maps.LatLngBounds(); 455 456 var b = rec.getBounds(); 457 var nE = [ b.getNorthEast().lat(), b.getNorthEast().lng() ];
458 var nW = [ b.getNorthEast().lat(), b.getSouthWest().lng() ]; 459 var sE = [ b.getSouthWest().lat(), b.getNorthEast().lng() ]; 460 var sW = [ b.getSouthWest().lat(), b.getSouthWest().lng() ]; 461 462 $_.map([nE, nW, sE, sW], function(o) { 463 latLngs.push({ 464 name: "points", 465 value: o[0] + "," + o[1] 466 }); 467 bounds.extend(new google.maps.LatLng(o[0], o[1])); 468 }); 469 470 this.bounds = bounds; 471 this.map.fitBounds(this.bounds); 472 473 return latLngs; 474} 475 476SimplyRETSMap.prototype.getPolygonPoints = function(polygon) { 477 478 var paths = polygon.getPaths(); 479 var points = []; 480 var bounds = new google.maps.LatLngBounds(); 481 482 for (var p = 0; p < paths.getLength(); p++) { 483 484 var path = paths.getAt(p); 485 486 for (var i = 0; i < path.getLength(); i++) { 487 488 points.push( 489 [ path.getAt(i).lat(), path.getAt(i).lng() ] 490 ); 491 492 bounds.extend( 493 new google.maps.LatLng( 494 path.getAt(i).lat(), path.getAt(i).lng() 495 ) 496 ); 497 498 } 499 } 500 501 var latLngs = $_.map(points, function(o) { 502 return { 503 name: "points", 504 value: o[0] + "," + o[1] 505 } 506 }); 507 508 this.bounds = bounds; 509 this.map.fitBounds(this.bounds); 510 511 return latLngs; 512 513} 514 515 516SimplyRETSMap.prototype.addEventListener = function(source, event, fn) { 517 return google.maps.event.addListener(source, event, fn); 518} 519 520SimplyRETSMap.prototype.searchFormValues = function() { 521 return getSearchFormValues(); 522}; 523 524SimplyRETSMap.prototype.clearMarkers = function() { 525 if(this.markers.length > 0) 526 this.setMapOnMarkers(null); 527} 528 529SimplyRETSMap.prototype.clearPolygon = function() { 530 if(this.polygon !== null) 531 this.setMapOnPolygon(null); 532} 533 534SimplyRETSMap.prototype.setDrawCtrlOptions = function(opts) { 535 return this.drawCtrl.setOptions(opts); 536} 537 538 539SimplyRETSMap.prototype.handlePolygonDraw = function(that, overlay) { 540 541 that.clearMarkers(); 542 that.clearPolygon(); 543 that.setDrawCtrlOptions({ drawingMode: null }); 544 545 var pts = that.getPolygonPoints(overlay); 546 var query = that.searchFormValues(); 547 548 that.shape = 'polygon'; 549 that.polygon = overlay; 550 that.markers = []; 551 552 return { 553 points: pts, 554 query: query 555 } 556} 557 558 559SimplyRETSMap.prototype.handleRectangleDraw = function(that, overlay) { 560 561 that.clearMarkers(); 562 that.clearPolygon(); 563 that.setDrawCtrlOptions({ drawingMode: null }); 564 565 var pts = that.getRectanglePoints(overlay); 566 var query = that.searchFormValues(); 567 568 that.shape = "rectangle"; 569 that.polygon = overlay; 570 that.markers = []; 571 572 return { 573 points: pts, 574 query: query 575 } 576} 577 578 579SimplyRETSMap.prototype.handleFormSubmit = function(e) { 580 e.preventDefault(); 581 582 this.clearMarkers(); 583 584 var params = this.searchFormValues(); 585 var points = this.shape === "rectangle" ? this.getRectanglePoints(this.polygon) 586 : this.shape === "polygon" ? this.getPolygonPoints(this.polygon) 587 : []; 588 589 return { 590 query: params, 591 points: points 592 } 593 594} 595 596 597SimplyRETSMap.prototype.setMapOnMarkers = function(map) { 598 599 for(var i = 0; i < this.markers.length; i++) { 600 this.markers[i].setMap(map); 601 } 602 603 return true; 604} 605 606 607SimplyRETSMap.prototype.setMapOnPolygon = function(map) { 608 609 this.polygon.setMap(map); 610 611 return true; 612} 613 614 615SimplyRETSMap.prototype.handleRequest = function(that, data) { 616 617 // Remove data from map before request 618 that.setMapOnMarkers(null); 619 that.setLoadMsgMap(null); 620 621 // New map data, empty 622 that.bounds = []; 623 that.listings = []; 624 625 var idxImg = document.getElementById('sr-map-search').dataset.idxImg; 626 var officeOnThumbnails = document.getElementById('sr-map-search').dataset.officeOnThumbnails; 627 var agentOnThumbnails = document.getElementById('sr-map-search').dataset.agentOnThumbnails; 628 var linkStyle = data.permalink_structure === "" ? "default" : "pretty"; 629 var statusText = data.show_mls_status_text; 630 var mlsTrademark = data.show_mls_trademark_symbol; 631 632 that.siteRoot = data.site_root 633 that.linkStyle = linkStyle; 634 635 var listings = data.result.response.length > 0 636 ? data.result.response 637 : []; 638 var markers = makeMapMarkers( 639 that.map, 640 listings, 641 that.linkStyle, 642 that.siteRoot, 643 idxImg, 644 officeOnThumbnails, 645 agentOnThumbnails, 646 statusText, 647 mlsTrademark, 648 that.vendor 649 ); 650 651 that.bounds = markers.bounds; 652 that.markers = markers.markers; 653 that.listings = listings; 654 655 if(listings.length < 1) 656 that.offset = 0; 657 658 if (!this.shape) { 659 that.map.fitBounds(that.bounds); 660 } 661 662 replaceListingMarkup(data.markup); 663 664 var pagination = updatePagination(that); 665 666 that.pagination = pagination; 667 668 that.initPaginationEventHandlers(that, that.pagination); 669 670} 671 672SimplyRETSMap.prototype.initPaginationEventHandlers = function(that, pag) { 673 674 if(pag.next !== null) { 675 676 $_(pag.next).on('click', function(e) { 677 678 e.preventDefault(); 679 680 var params = that.handleFormSubmit(e), 681 points = params.points, 682 query = params.query; 683 684 that.sendRequest(points, query, 'next').done(function(data) { 685 that.handleRequest(that, data); 686 }); 687 688 }); 689 } 690 691 if(pag.prev !== null) { 692 693 $_(pag.prev).on('click', function(e) { 694 695 e.preventDefault(); 696 697 var params = that.handleFormSubmit(e), 698 points = params.points, 699 query = params.query; 700 701 that.sendRequest(points, query, 'prev').done(function(data) { 702 that.handleRequest(that, data); 703 }); 704 705 }); 706 } 707 708} 709 710 711SimplyRETSMap.prototype.setLoadMsgMap = function(map) { 712 713 if(!this.polygon && !this.rectangle) return; 714 715 this.loadMsg.setPosition(this.map.getCenter());
716 this.loadMsg.setMap(map); 717 718} 719 720 721SimplyRETSMap.prototype.sendRequest = function(points, params, paginate) { 722 723 this.setLoadMsgMap(this.map); 724 725 /** Update pagination */ 726 if(paginate !== null && paginate !== undefined) { 727 728 if(paginate === "next") { 729 scrollToAnchor('sr-search-wrapper'); 730 this.offset = Number(this.offset) + Number(this.limit); 731 } else if(paginate === "prev") { 732 scrollToAnchor('sr-search-wrapper'); 733 this.offset = Number(this.offset) - Number(this.limit); 734 } else if (paginate === "reset") { 735 this.offset = 0 736 } 737 } 738 739 var offset = this.offset; 740 var vendor = this.vendor 741 742 /** URL Encode them all */ 743 var pointsQ = $_.param(points); 744 var query = params 745 + (vendor ? ("vendor=" + vendor + "&") : "") 746 + "offset=" + offset + "&" 747 + pointsQ 748 749 var req = $_.ajax({ 750 type: 'post', 751 url: sr_ajaxUrl, // defined in <head> 752 data: { 753 action: 'update_int_map_data', // server controller 754 parameters: query, 755 vendor: vendor 756 }, 757 }); 758 759 return req; 760 761} 762 763SimplyRETSMap.prototype.setDrawingManager = function() { 764 765 var that = this; 766 767 // Enable the drawing tools toolbar 768 var drawingManager = new google.maps.drawing.DrawingManager({ 769 map: this.map, 770 drawingControl: true, 771 drawingControlOptions: { 772 position: google.maps.ControlPosition.TOP_CENTER, 773 drawingModes: [ 774 google.maps.drawing.OverlayType.POLYGON, 775 google.maps.drawing.OverlayType.RECTANGLE 776 ] 777 }, 778 // markerOptions: { icon: 'custom/icon/here.png' }, 779 rectangleOptions: { 780 editable: true, 781 fillOpacity: 0.1, 782 fillColor: 'green', 783 strokeColor: 'green' 784 }, 785 polygonOptions: { 786 editable: true, 787 fillOpacity: 0.1, 788 fillColor: 'green', 789 strokeColor: 'green' 790 }, 791 }); 792 793 this.drawCtrl = drawingManager; 794 795 this.addEventListener(drawingManager, 'rectanglecomplete', function(overlay) { 796 var q = that.handleRectangleDraw(that, overlay); 797 798 overlay.addListener("click", function() { 799 that.shape = null 800 that.bounds = [] 801 overlay.setMap(null) 802 }) 803 804 that.sendRequest(q.points, q.query).done(function(data) { 805 that.handleRequest(that, data); 806 }); 807 808 }); 809 810 this.addEventListener(drawingManager, 'polygoncomplete', function(overlay) { 811 var q = that.handlePolygonDraw(that, overlay); 812 813 overlay.addListener("click", function() { 814 that.shape = null 815 that.bounds = [] 816 overlay.setMap(null) 817 }) 818 819 that.sendRequest(q.points, q.query).done(function(data) { 820 that.handleRequest(that, data); 821 }); 822 823 }); 824 825 return drawingManager; 826 827}; 828 829 830SimplyRETSMap.prototype.initEventListeners = function() { 831 832 var that = this; 833 834 // fetch initial listings when map is loaded 835 this.addEventListener(this.map, 'idle', function() { 836 if(!that.loaded) { 837 var query = that.searchFormValues() 838 839 that.sendRequest([], query).done(function(data) { 840 that.handleRequest(that, data); 841 that.loaded = true; 842 }); 843 } 844 }); 845 846 847 // Watch the search form for submission 848 $_('.sr-int-map-search-wrapper form input.submit').on('click', function(e) { 849 var params = that.handleFormSubmit(e), 850 points = params.points, 851 query = params.query; 852 853 that.sendRequest(points, query, "reset").done(function(data) { 854 that.handleRequest(that, data); 855 }); 856 857 }); 858 859 return; 860 861}; 862 863 864var startMap = function() { 865 866 var map = new SimplyRETSMap(); 867 map.setDrawingManager(); 868 map.initEventListeners(); 869 870} 871 872 873$_(document).ready(function() { 874 875 classicGalleryToggle(); 876 classicGalleryTextToggle(); 877 advSearchFormToggler(); 878 listingSliderCarousel(); 879 880 if(document.getElementById('sr-map-search')) { 881 882 if(typeof google === 'object' && typeof google.maps === 'object') { 883 // google.maps exists - start map 884 startMap(); 885 886 } else { 887 var key = document.getElementById('sr-map-search').dataset.apiKey; 888 889 // if google.maps doesn't exist - load it, then start map
890 var url = "https://maps.googleapis.com/maps/api/js?" 891 + "libraries=drawing&callback=startMap" 892 + "&key=" + key; 893 894 var script = document.createElement("script"); 895 896 script.type = "text/javascript"; 897 script.src = url; 898 899 document.body.appendChild(script); 900 901 } 902 } 903 904 document.querySelectorAll(".utcToLocal").forEach(function(i) { 905 i.innerText = new Date(i.innerText).toLocaleString() 906 }) 907 908}); 909 910/** 911 * Polyfills for browser compatibility 912 */ 913 914// Object.assign polyfill for older browsers 915// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign 916if (typeof Object.assign !== 'function') { 917 Object.defineProperty(Object, "assign", { 918 value: function assign(target, varArgs) { 919 'use strict'; 920 if (target === null || target === undefined) { 921 throw new TypeError('Cannot convert undefined or null to object'); 922 } 923 924 var to = Object(target); 925 926 for (var index = 1; index < arguments.length; index++) { 927 var nextSource = arguments[index]; 928 929 if (nextSource !== null && nextSource !== undefined) { 930 for (var nextKey in nextSource) { 931 if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { 932 to[nextKey] = nextSource[nextKey]; 933 } 934 } 935 } 936 } 937 return to; 938 }, 939 writable: true, 940 configurable: true 941 }); 942}
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.