PageSourceSearch

https://prosrealtyaz.com/Widgets/ListingSearch/ListingSearch.js?v=enEWT7j1cgMYR7_BW_TO_LiD09QX-UvQskuYf7vYbJg

js prosrealtyaz.com collected 2026-09-27 12:55:47 UTC 36,420 bytes, 965 lines download raw bytes

1Widgets.ListingSearch = function (options = null) {
2    let rawData = null;
3    this.className = "defaultListingSearchContainer";
4    this.currentDisplay = null;
5    this.currentScrollId = null;
6    Widgets.BaseWidget.call(this, "/Widgets/ListingSearch/ListingSearch", this.className);
7
8    //custom overriding options
9    BaseHelper.MergeIntoObject(this, options);
10
11    this._setup = function () {
12        Widgets.BaseWidget.prototype._setup.call(this);
13        this.isRefreshing = false;
14        this.pBar = new PaginationBar(0, 3);
15        this.pBar.init();
16        this.defaultImageUrl = "/img/no-housephoto.jpg"
17        this.fetchCount = 50;
18        this.pendingRawDataList = [];
19
20        this.dataTask = null;
21        this.currentUuid = null;
22
23        this.currentData = null;
24        this.prevListingRequest = {
25            request: null,
26            response:null
27        }
28        this.prevMapRequest = {
29            requst: null,
30            response:null
31        }
32        this.onPaginationChange = null;
33    };
34
35    this.getLoadData = async function () {
36        let result = Widgets.BaseWidget.prototype.getLoadData.call(this);
37
38        let json_response = await BaseHelper.MakeAJAXGetRequest("/api/Website/IsListHubSite");
39        let response = JSON.parse(json_response);
40        this.IsListHub = response["IsListHub"];
41        //console.log("this.IsListHub", this.IsListHub);
42
43        this.ListingSearchItemMarkup = await BaseHelper.MakeAJAXGetRequest("/Widgets/ListingSearch/ListingSearchItem");
44        this.ListingSearchFillerItemMarkup = await BaseHelper.MakeAJAXGetRequest("/Widgets/ListingSearch/ListingSearchFillerItem");
45        return result;
46    };
47
48    this.getRawData = async () => {
49        return new Promise((resolve, reject) => {
50            if (this.rawData != null) {
51                resolve(this.rawData);
52            }
53            if (this.isRefreshing) {
54                this.pendingRawDataList.push((rawData) => {
55                    resolve(rawData);
56                });
57            }
58            else {
59                resolve(this.rawData);
60            }
61        });
62    };
63
64    // Returns a populated div.
65    this.GetPopulatedCard = function (data, heartKey) {
66        let div = document.createElement("div");
67
68        div.innerHTML = this.ListingSearchItemMarkup;
69
70        this.populateSearchListingItem(div, data, true, heartKey);
71
72        div.firstChild.attributes["data-listingid"].value = data.ListingID;
73
74        return div.firstChild;
75    };
76
77    //returns a card to use as a filler while loading.
78    this.GetFillerCard = function () {
79        let div = document.createElement("div");
80        div.innerHTML = this.ListingSearchFillerItemMarkup;
81        return div.firstChild;
82    }
83
84    this.setFilters = (filterArr) => {
85        if (this.currentData == null) {
86            this.currentData = this.getDefaultData();
87        }
88        this.currentData.page = 0;
89        this.currentData.data = null;
90        let sortFilter = null;
91        for (let i = 0; i < filterArr.length; i++) {
92            let f = filterArr[i];
93            if (f.name == "SortResult") {
94                sortFilter = f;
95                break;
96            }
97        }
98        if (sortFilter == null) {
99            this.currentData.orderBy = "ListingDate";
100            this.currentData.orderSort = "DESC";
101        }
102        else {
103            let sfValue = sortFilter.value;
104            if (sfValue == "lowest") {
105                this.currentData.orderBy = "ListPrice";
106                this.currentData.orderSort = "ASC";
107            }
108            else if (sfValue == "highest") {
109                this.currentData.orderBy = "ListPrice";
110                this.currentData.orderSort = "DESC";
111            }
112            else if (sfValue == "lotsize") {
113                this.currentData.orderBy = "LotSize";
114                this.currentData.orderSort = "DESC";
115            }
116            else if (sfValue == "openhouse") {
117                this.currentData.orderBy = "OpenHouseUpcomingStartDate";
118                this.currentData.orderSort = "ASC";
119            }
120            else {
121                this.currentData.orderBy = "ListingDate";
122                this.currentData.orderSort = "DESC";
123            }
124        }
125        this.currentData.filterArr = filterArr;
126    };
127
128    this.setMapRequest = (request) => {
129        if (this.currentData == null) {
130            this.currentData = this.getDefaultData();
131        }
132        this.currentData.page = 0;
133        this.currentData.data = null;
134        this.currentData.mapRequest = request;
135    };
136
137
138    this.getDefaultData = () => {
139        let data = {
140            filterArr: null,
141            page: 0,
142            fetch: this.fetchCount,
143            orderBy: "ListingDate",
144            orderSort: "DESC",
145            isMap: false,
146            data: null
147        }
148        return data;
149    };
150
151    this.getMaxPage = (maxPage) => {
152        return maxPage;
153    };
154
155    this.populateGrid = (listings) => {
156        this.clearGrid();
157        if (this.currentData == null || listings == null) {
158            return;
159        }
160        this.currentData.data = listings;
161        let pData = listings.PaginatedData;
162        let currentPage = pData.offset / pData.fetch;
163        this.pBar.currentPage = currentPage;
164        let maxPage = this.getMaxPage(pData.maxPages);
165        this.pBar.setMaxPage(maxPage);
166        this.pBar.refresh();
167        this.currentPropTypeList = this.getCurrentPropTypeList();
168        if (BaseHelper.isNullOrUndefined(this.ListingIDLookupHeart)) {
169            this.ListingIDLookupHeart = {};
170        }
171        else {
172            for (let key in this.ListingIDLookupHeart) {
173                delete this.ListingIDLookupHeart[key]["ListingSearch"];
174            }
175        }
176        if (pData != null && pData.data != null) {
177            pData.data.forEach((record) => {
178                let div = this.GetPopulatedCard(record, "ListingSearch");
179                this.ListingSearchItemContainer.appendChild(div);
180
181                //remove the background src before appending to element and add the unveil src to element
182                let imgTop = div.querySelector(".card-img-top");
183                let src = imgTop.getAttribute("image-src");
184                //imgTop.setAttribute("data-src", src);
185                //imgTop.setAttribute("data-lazyload", false);
186                //imgTop.removeAttribute("style");
187
188                imgTop.setAttribute("style", "background-image:url('" + src + "'),url('/img/no-housephoto.jpg');");
189            });
190        }
191
192        window.addEventListener("scroll", () => {
193            this.onScroll();
194        });
195    };
196
197    this.onScroll = () => {
198        let scrollId = this.currentScrollId = BaseHelper.getUuid();
199        //console.log("scroll");
200        //window.setTimeout(() => {
201        //    if (this.currentScrollId == scrollId) {
202        //        let imgList = this.ListingSearchItemContainer.querySelectorAll(".card-img-top[data-lazyload=false]");
203        //        for (let i = 0; i < imgList.length; i++) {
204        //            let img = imgList[i];
205        //            let windowSides = BaseHelper.getWindowSides()
206        //            let boundSides = BaseHelper.getBoundSides(img.getBoundingClientRect())
207        //            if (BaseHelper.isScrolledIntoViewSides(windowSides, boundSides)) {
208        //                let src = img.getAttribute("image-src");
209        //                img.setAttribute("style", "background-image:url('" + src + "'),url('/img/no-housephoto.jpg');");
210        //                img.setAttribute("data-lazyload", true);
211        //            }
212        //        }
213        //    }
214        //}, 200);
215    };
216
217   
218
219    //this.clearSavedListings = () => {
220    //  if (
221    //    this.currentData == null ||
222    //    this.currentData.data == null ||
223    //    this.currentData.data.PaginatedData == null ||
224    //    this.currentData.data.PaginatedData.data == null) {
225    //    return;
226    //  }
227    //  let data = this.currentData.data.PaginatedData.data;
228    //  data.forEach((d) => {
229    //    d.SiteUserSavedListingStatusTblID = null;
230    //  })
231    //  this.populateGrid(this.currentData.data);
232    //};
233
234    this.getValueOrEmpty = (str) => {
235        if (str == null) {
236            return "";
237        }
238        else {
239            return str;
240        }
241    };
242
243
244    this.getUrlAddress = (record) => {
245        if (!BaseHelper.displayAddress(record)) {
246            return "";
247        }
248        let streetNumber = record["StreetNumber"];
249        let streetName = record["StreetName"];
250        let unitNumber = record["UnitNumber"];
251        let city = record["City"];
252        let state = record["State"];
253        let zip = record["Zip"];
254        let fullAddress = this.getValueOrEmpty(streetNumber) + " " + this.getValueOrEmpty(streetName) + " " + this.getValueOrEmpty(unitNumber) + " " + this.getValueOrEmpty(city) + " " + this.getValueOrEmpty(state) + " " + this.getValueOrEmpty(zip);
255        // Remove special characters, but keep letters, numbers, and spaces
256        fullAddress = fullAddress.replaceAll(/[^A-Za-z0-9\s]/g, "");
257        //replace multiple spaces with single space
258        fullAddress = fullAddress.replaceAll(/\s+/g, ' ');
259        // Trim leading/trailing spaces before converting spaces to underscores
260        fullAddress = fullAddress.trim();
261
262        // Replace spaces with underscores
263        fullAddress = fullAddress.replaceAll(/\s/g, "_");
264
265        return fullAddress;
266    };
267
268    this.getCurrentPropTypeList = () => {
269        if (this.currentData == null || this.currentData.filterArr == null || this.currentData.filterArr.length == null) {
270            return null;
271        }
272        let filterArr = this.currentData.filterArr;
273        for (let i = 0; i < filterArr.length; i++) {
274            f = filterArr[i];
275            if (f.name == "PropTypeList") {
276                return f.value;
277            }
278        }
279        return null;
280    };
281
282    this.isNewlyListed = function (record) {
283        if (record == null || record.ListingDate == null) {
284            return false;
285        }
286        let dtListing = new Date(record.ListingDate);
287        if (isNaN(dtListing)) {
288            return false;
289        }
290        let now = new Date();
291        let dayDiff = (now - dtListing) / (1000 * 3600 * 24);
292        if (dayDiff <= 7) {
293            return true;
294        }
295        return false;
296    };
297
298
299    this.isNewConstruction = function (record) {
300        if (record == null || record.PropType8 == null) {
301            return false;
302        }
303        if (record.PropType8 == 1) {
304            return true;
305        }
306        return false;
307    };
308
309    this.isComingSoon = function (record) {
310        if (record == null || record.ListingStatusTblID == null) {
311            return false;
312        }
313        if (record.ListingStatusTblID == 4) {
314            return true;
315        }
316        return false;
317    };
318
319
320    this.getOpenHouseDate = function (record) {
321        if (record == null) {
322            return null;
323        }
324        let tzOffset = parseInt(record.TimeZone);
325        let timezone = null;
326        let dtOpenHouse = new Date(record.OpenHouseUpcomingStartDate);
327        if (isNaN(dtOpenHouse) || dtOpenHouse.getFullYear() == 5000) {
328            return null;
329        }
330
331        if (record.LocalOpenHouseUpcomingStartDate != null && record.DayLightSaving != null && !isNaN(tzOffset)) {
332            if (tzOffset == 6) {
333                timezone = "Central";
334            }
335            else if (tzOffset == 7) {
336                timezone = "Mountain";
337            }
338            else if (tzOffset == 8) {
339                timezone = "Pacific";
340            }
341            else if (tzOffset == 9) {
342                timezone = "Alaskan";
343            }
344            dtOpenHouse = new Date(record.OpenHouseUpcomingStartDate);
345        }
346
347        return {
348            dtOpenHouse: dtOpenHouse,
349            timezone: timezone
350        }
351    };
352
353    this.SetSavedListing = async function (ListingID, save) {
354        let data = {
355            ListingID: ListingID,
356            Save: save == true ? 1 : 0
357        };
358        let json_response = await BaseHelper.MakeAJAXPostJSONRequest("/api/SiteUser/SetSiteUserListing", data, false);
359        let response = JSON.parse(json_response);
360        //console.log(response);
361        if (response.Status == 1) {
362            let hItemObj = this.ListingIDLookupHeart[ListingID];
363            if (hItemObj != null) {
364                for (let key in hItemObj) {
365                    heartItem = hItemObj[key];
366                    if (save == true) {
367                        this.ToggleHeart(heartItem, true);
368                    }
369                    else {
370                        this.ToggleHeart(heartItem, false);
371                    }
372                }
373            }
374        }
375        else {
376            this.PendingSavedListingID = ListingID;
377        }
378        if (this.onSavedListingComplete != null) {
379            this.onSavedListingComplete(this, response);
380        }
381    };
382
383    this.onSavedListingComplete = null;
384
385    this.clearHearts = function () {
386        for (let key in this.ListingIDLookupHeart) {
387            let hItemObj = this.ListingIDLookupHeart[key];
388            if (hItemObj != null) {
389                for (let hiKey in hItemObj) {
390                    hItem = hItemObj[hiKey];
391                    this.ToggleHeart(hItem, false);
392                }
393            }
394        }
395    };
396
397    this.populateHearts = function (data) {
398        this.clearHearts();
399        if (data != null && data.length > 0) {
400            data.forEach((savedListing) => {
401                let hItemObj = this.ListingIDLookupHeart[savedListing.ListingID];
402                if (hItemObj != null) {
403                    for (let key in hItemObj) {
404                        heart = hItemObj[key];
405                        this.ToggleHeart(heart, true);
406                    }
407                }
408            })
409        }
410    };
411
412    this.ToggleHeart = function (heartItem, saved) {
413        let heartPath = heartItem.path;
414        heartItem.heart.setAttribute("data-saved", saved == true ? 1 : 0);
415        if (saved) {
416            heartPath.setAttribute("stroke", "#FFF")
417            heartPath.setAttribute("fill-opacity", 1)
418            heartPath.setAttribute("fill", "#F00")
419        }
420        else {
421            heartPath.setAttribute("stroke", "#FFF")
422            heartPath.setAttribute("fill-opacity", 0.2)
423            heartPath.setAttribute("fill", "#000")
424        }
425    };
426
427    this.getListingName = (data) => {
428        if (data.IdxFeedTypeID == 10) {
429            return data.MlsStatus;
430        }
431        //return data.ListingStatus;
432        if (data.IdxFeedTypeID == 215) {
433            return data.ListingStatus;
434        }
435        let result = data.ListingStatusName;
436        if (data.ListingStatusCategoryTypeTblID == 2) {
437            if (data.ListingStatusCategoryFullName != null) {
438                result = data.ListingStatusCategoryFullName;
439            }
440        }
441        return result;
442    };
443
444    this.getListingColor = (data) => {
445        let result = data.ListingStatusCategoryColor;
446        if (data.ListingStatusTblID == 4 || result == null) {
447            result = data.ListingStatusColor;
448        }
449        return result;
450    };
451
452    // Populates a ListingSearchItem with listing data.
453    this.populateSearchListingItem = (siContainer, record, canOpenInNewWindow, heartKey) => {
454        try {
455            let box = siContainer.querySelector("a.box");
456            box.href = "/prop-details/" + record.ListingID + "/" + this.getUrlAddress(record);
457            //box.setAttribute("class", "img");
458            if (canOpenInNewWindow != undefined && canOpenInNewWindow == true) {
459                box.setAttribute("target", "_blank");
460            }
461
462            let spanSearchResultPrice = siContainer.querySelector(".search-result-price");
463            let spanSearchResultAddress = siContainer.querySelector(".srAddress");
464            let liSearchResultBedrooms = siContainer.querySelector(".search-result-bedrooms");
465            let liSearchResultBathrooms = siContainer.querySelector(".search-result-bathrooms");
466            let liSearchResultSqft = siContainer.querySelector(".search-result-sqft");
467            let liSearchResultAcres = siContainer.querySelector(".search-result-lot");
468            let spanSearchResultCityStateZip = siContainer.querySelector(".srCity");
469            let spanSearchResultPropType = siContainer.querySelector(".search-result-proptype");
470            let propSaleStatus = siContainer.querySelector(".propSaleStatus");
471            let propSaleStatusText = siContainer.querySelector(".propSaleStatus span");
472            let spanNewlyListed = siContainer.querySelector("span.NewlyListed");
473            let spanComingSoon = siContainer.querySelector("span.ComingSoon");
474            let spanNewConstruction = siContainer.querySelector("span.NewConstruction");
475            let spanOpenHouseDate = siContainer.querySelector("span.OpenHouseDate");
476            let spanOpenHouseDateText = siContainer.querySelector("span.OpenHouseDate span");
477            let divCardImageTop = siContainer.querySelector("div.card-img-top");
478            let heartContainer = siContainer.querySelector(".heart-container");
479            let svgHeart = siContainer.querySelector(".heart-container .svgHeart");
480            let svgHeartPath = siContainer.querySelector(".heart-container .svgHeart path");
481            let divOfficeName = siContainer.querySelector(".card-body .officeName");
482            if (record["IdxFeedTypeID"] == 71 || record["IdxFeedTypeID"] == 72) {
483                let officeName = record["OfficeName"];
484                if (officeName != null) {
485                    officeName = officeName.toUpperCase();
486                }
487                divOfficeName.innerText = officeName;
488            }
489
490            let heartItem = {
491                "record": record,
492                "heartContainer": heartContainer,
493                "heart": svgHeart,
494                "path": svgHeartPath
495            };
496
497            if (this.ListingIDLookupHeart != null) {
498                if (this.ListingIDLookupHeart[record.ListingID] == null) {
499                    this.ListingIDLookupHeart[record.ListingID] = {};
500                }
501                this.ListingIDLookupHeart[record.ListingID][heartKey] = heartItem;
502                if (record.SiteUserSavedListingStatusTblID == 1) {
503                    this.ToggleHeart(heartItem, true);
504                }
505                else {
506                    this.ToggleHeart(heartItem, false);
507                }
508            }
509
510            heartContainer.addEventListener("click", (e) => {
511                let saved = heartItem.heart.getAttribute("data-saved");
512                if (saved == 1) {
513                    saved = false;
514                    this.SetSavedListing(record.ListingID, false)
515                }
516                else {
517                    saved = true;
518                    this.SetSavedListing(record.ListingID, true)
519                }
520            });
521
522            let imgfeedLogo = siContainer.querySelector(".feedLogo");
523            if (this.isComingSoon(record)) {
524                spanComingSoon.style.display = "inline-block";
525            }
526            else if (this.isNewlyListed(record)) {
527                spanNewlyListed.style.display = "inline-block";
528            }
529            else if (this.isNewConstruction(record)) {
530                spanNewConstruction.style.display = "inline-block";
531            }
532
533            let openHouseDate = this.getOpenHouseDate(record);
534            if (openHouseDate != null && openHouseDate.dtOpenHouse != null) {
535                spanOpenHouseDate.style.display = "inline-block";
536                let dtOh = openHouseDate.dtOpenHouse;
537                spanOpenHouseDateText.innerText = (dtOh.getMonth() + 1) + "/" + dtOh.getDate()
538            }
539            let streetAddress = "";
540            if (BaseHelper.displayAddress(record)) {
541                let addressParts = [];
542                addressParts.push(record["StreetNumber"]);
543                addressParts.push(record["StreetDirPrefix"]);
544
545                let streetName = record["StreetName"];
546                let streetSuffix = record["StreetSuffix"];
547
548                addressParts.push(streetName);
549                if (streetName == null) {
550                    addressParts.push(streetSuffix);
551                }
552                else if (
553                    streetSuffix
554                    && !streetName.toUpperCase().endsWith(streetSuffix.toUpperCase())
555                ) {
556                    addressParts.push(streetSuffix);
557                }
558                addressParts.push(record["StreetDirSuffix"]);
559                addressParts.push(record["UnitNumber"]);
560                let filteredAddress = addressParts.filter(part => part);
561                streetAddress = BaseHelper.toTitleCase(filteredAddress.join(" "));
562                if (record["StreetNumber"] == null && record["StreetName"] == null && record["AddressLine"] != null) {
563                    streetAddress = BaseHelper.toTitleCase(record["AddressLine"].split(',')[0]);
564                }
565            }
566            let listPrice = ""
567            if (record.ListingStatusTblID == 8 && (record.ClosePrice == null || record.State == "TX")) {
568                listPrice = "$Unknown"
569            }
570            else {
571                listPrice = record.SortPrice == null ? "" : BaseHelper.dollarFormatter.format(record.SortPrice);
572            }
573            let houseSize = "--";
574            let lotSize = "--";
575            houseSize = BaseHelper.getHouseSize(record);
576            lotSize = BaseHelper.getLotSize(record);
577            let CityStateZip = BaseHelper.toTitleCase(this.getValueOrEmpty(record.City)) + ", " + this.getValueOrEmpty(record.State) + ", " + BaseHelper.toTitleCase(this.getValueOrEmpty(record.Zip));
578            let bedroomCount = "--";
579            if (record.BedroomCount != null && record.BedroomCount != 0) {
580                bedroomCount = record.BedroomCount
581            }
582            let bathroomCount = "--";
583            if (record.BathroomCount != null && record.BathroomCount != 0) {
584                bathroomCount = record.BathroomCount
585            }
586            let housePhotoUrl;
587            if (canOpenInNewWindow) {
588                housePhotoUrl = "/api/listing/" + record.ListingID + "/mainphoto";
589            }
590            else {
591                housePhotoUrl = this.getHousePhotoUrl(record);
592            }
593            BaseHelper.setBackgroundImageWithFallback(divCardImageTop, housePhotoUrl,"/images/photos-coming-soon.svg", "/img/no-housephoto.jpg");
594            //divCardImageTop.style = "background-image: url('" + housePhotoUrl + "'), url('/img/no-housephoto.jpg');";
595            divCardImageTop.setAttribute("image-src", housePhotoUrl);
596            divCardImageTop.setAttribute("role", "img");
597            divCardImageTop.setAttribute("aria-label", "Photo for " + streetAddress + ", " + CityStateZip);
598            spanSearchResultPrice.innerText = listPrice
599            spanSearchResultAddress.innerText = streetAddress.trim();
600            
601            liSearchResultBedrooms.prepend(bedroomCount + " ");
602            liSearchResultBathrooms.prepend(bathroomCount + " ");
603            liSearchResultSqft.innerText = houseSize;
604            liSearchResultAcres.innerText = lotSize;
605            spanSearchResultCityStateZip.innerText = CityStateZip;
606            spanSearchResultPropType.innerText = this.getValueOrEmpty(record.PropertyTypeName);
607            let color = this.getListingColor(record);
608            let name = this.getListingName(record);
609            propSaleStatus.style.color = this.getValueOrEmpty(color);
610            propSaleStatusText.innerText = this.getValueOrEmpty(name);
611
612            if (record["IdxFeedLogoImagePath"] == null) {
613                imgfeedLogo.style.display = "none";
614            }
615            else {
616                imgfeedLogo.src = record["IdxFeedLogoImagePath"];
617                imgfeedLogo.style.display = "block";
618                imgfeedLogo.setAttribute("alt", record.ListingMlsName);
619            }
620        }
621        catch (e) {
622            console.log(e);
623        }
624    };
625
626    this.getHousePhotoUrl = (record) => {
627        let providerID = record.IdxFeedProviderID;
628
629        //trestle
630        if (providerID != 1 && providerID != 4) {
631            let result = record.ListingMediaPreferredUrl;
632
633            if (result == null) {
634                result = record.ListingMediaFirstUrl;
635            }
636
637            if (result == null) {
638                return this.defaultImageUrl
639            }
640
641            return result;
642        }
643
644        //mlsgrid
645        let url = record.FirstPhotoURL;
646        let key = record.FirstMediaKey;
647        let type = record.FirstMediaType;
648        let origin = record.OriginatingSystemName
649        if (this.currentData == null || this.currentData.data == null || this.currentData.data.AzureStorageBaseUrl == null || providerID == null || BaseHelper.isStringNullOrWhiteSpace(url) || BaseHelper.isStringNullOrWhiteSpace(key)) {
650            return this.defaultImageUrl;
651        }
652
653        let base = this.currentData.data.AzureStorageBaseUrl + "/images/";
654
655        if (providerID == 1) {
656            let provider = null;
657            provider = "MlsGrid/";
658            let parts = url.split('/');
659            let fileName = parts[parts.length - 1];
660            let result = base + provider + key + "-" + fileName;
661            return result;
662        }
663        else if (providerID == 4) {
664            let provider = null;
665            provider = "MetroList2022/";
666            let result = base + provider + origin.replaceAll(' ', '_') + "-" + record.ListingKey + "-" + key
667            return result;
668        }
669        else {
670            return this.defaultImageUrl
671        }
672    };
673
674    this.clearGrid = (listings) => {
675        this.ListingSearchItemContainer.innerHTML = "";
676    };
677        this.findListings = async (request) => {
678        let response = await BaseHelper.MakeAJAXPostJSONRequest("/api/Listing/FindListings", request);
679        return response;
680    };
681    //-------------------------------------------------------------------------------------------------
682    this.getListingRequest = (filterArr, page, fetch, orderBy, orderSort, count) => {
683        let data =
684        {
685            filterArr: filterArr,
686            page: page,
687            fetch: fetch,
688            orderBy: orderBy,
689            orderSort: orderSort,
690            count: count
691        };
692        if (data.filterArr == null) {
693            data.filterArr = this.currentData.filterArr;
694        }
695        return JSON.parse(JSON.stringify(data));
696    };
697
698    this.makeListingRequest = () => {
699        let page = this.pBar.currentPage
700        let data = this.currentData;
701        let count = -1;
702        if (this.currentData.data != null && this.currentData.data.PaginatedData != null) {
703            count = this.currentData.data.PaginatedData.count
704        }
705        let request = this.getListingRequest(data.filterArr, page, data.fetch, data.orderBy, data.orderSort, count);
706        return request;
707    }
708
709    this.findListings = async (request) => {
710        let response = await BaseHelper.MakeAJAXPostJSONRequest("/api/Listing/FindListings", request);
711        return response;
712    };
713
714    this.getListingData = async (request) => {
715        if (this.currentData == null || this.currentData.filterArr == null) {
716            return;
717        }
718        let response = await this.findListings(request);
719        if (this.IsListHub) {
720            let listHubResponse = JSON.parse(response);
721            let listingKeyObj = [];
722            listHubResponse.PaginatedData.data.forEach((d) => {
723                let item = {
724                    lkey: d.ListingKey
725                }
726                listingKeyObj.push(item); //switched from key to lkey 01-23-2025               
727            })
728            lh('submit', 'SEARCH_DISPLAY', listingKeyObj);
729        }
730        return {
731            request: request,
732            response: response
733        };
734    };
735    //-------------------------------------------------------------------------------------------------
736    this.getAreaRequest = (mapRequest, page) => {
737        let request = JSON.parse(JSON.stringify(mapRequest));
738        request.page = page;
739        return request;
740    };
741
742    this.makeAreaRequest = () => {
743        return this.getAreaRequest(this.currentData.mapRequest, this.pBar.currentPage);
744    }
745
746    this.getArea = async (request) => {
747        let cpyRequest = JSON.parse(JSON.stringify(request));
748        if (cpyRequest.filters != null) {
749            cpyRequest.filters = JSON.stringify(request.filters);
750        }
751        let response = await $.post("/api/Listing/listingSearcharea", cpyRequest);
752        return response;
753    };
754
755    this.getMapData = async (request) => {
756        if (this.currentData == null || this.currentData.mapRequest == null) {
757            return;
758        }
759        let response = await this.getArea(request);
760        if (this.IsListHub) {
761            let listHubResponse = JSON.parse(response);
762            let listingKeyObj = [];
763            listHubResponse.PaginatedData.data.forEach((d) => {
764                let item = {
765                    lkey: d.ListingKey
766                }
767                listingKeyObj.push(item); //switched from key to lkey 01-23-2025               
768            })
769            lh('submit', 'SEARCH_DISPLAY', listingKeyObj);
770        }
771        return {
772            request: request,
773            response: response
774        };
775    };
776    //--------------------------------------------------------------------------------------------
777    this.getKeywordData = async () => {
778        if (this.currentData == null || this.currentData.filterArr == null) {
779            return;
780        }
781        let data = this.currentData;
782        let response = await this.getSearchKeywords(data.filterArr);
783        return response;
784    };
785
786    this.isNewRequest = async () => {
787        if (this.currentData?.mapRequest != null) {
788            result = await this.getMapData();
789        }
790        else if (this.currentData?.filterArr != null) {
791            result = await this.getListingData();
792        }
793        return true;
794    };
795
796    this.getData = async (request) => {
797        let result = null;
798
799        if (this.currentData?.mapRequest != null) {
800            result = await this.getMapData(request);
801        }
802        else if (this.currentData?.filterArr != null) {
803            result = await this.getListingData(request);
804        }
805        return result;
806    };
807
808    this.getRequest = () => {
809        let result = null;
810        if (this.currentData?.mapRequest != null) {
811            result = this.makeAreaRequest();
812        }
813        else if (this.currentData?.filterArr != null) {
814            result = this.makeListingRequest();
815        }
816        return result;
817    };
818
819    this.hasRequestChanged = async () => {
820        let result = null;
821        if (this.currentData?.mapRequest != null) {
822            result = await this.getMapData(this.pBar.currentPage);
823        }
824        else if (this.currentData?.filterArr != null) {
825            result = await this.getListingData(this.pBar.currentPage);
826        }
827        return result;
828    };
829
830    this.refresh = async () => {
831        if (this.currentData == null) {
832            return null;
833        }
834        this.isRefreshing = true;
835        //give the latest call of refresh a unique id
836        let uuid = this.currentUuid = BaseHelper.getUuid() 
837        //-----------------------------------------------------------------
838        //store the request, if it was previously retrieved, then just reuse it.
839        let request = this.getRequest();
840        if (this.prevRequest != null && JSON.stringify(this.prevRequest) == JSON.stringify(request)) {
841            return {
842                type: "current",
843                data: this.rawData
844            };
845        }
846        //-----------------------------------------------------------------
847        this.ToggleLoading(true); //display loading circle
848        let dataTask = this.dataTask = this.getData(request); //get the needed to refresh the display
849        let result = await this.dataTask; //wait for the data to come in.
850        
851        while (this.dataTask != dataTask) { 
852            //if refresh called again before the data was retrieved, await the latest task
853            dataTask = this.dataTask;
854            result = await dataTask;
855        }
856
857        //check if the current instance is the latest refresh call.
858        //if it wasnt, just return the data without refreshing the page.
859        if (this.currentUuid != uuid) {
860            return {
861                type: "copy",
862                data: this.rawData
863            };
864        }
865
866        //if current instance is the latest refresh call, refresh the page.
867        //only need to refresh the page once with the latest data.
868        let response = result.response;
869        this.rawData = JSON.parse(response);
870        this.isRefreshing = false;
871        this.ToggleLoading(false);
872        //-----------------------------------------------------------------
873        this.populateGrid(this.rawData);
874        this.prevRequest = request;
875        this.pendingRawDataList.forEach((pendingRawData) => {
876            pendingRawData(this.rawData);
877        });
878        this.pendingRawDataList = [];
879        if (this.onRefreshComplete != null) {
880            this.onRefreshComplete(this);
881        }
882        this.onScroll();
883        return {
884            type: "latest",
885            data: this.rawData
886        };
887    };
888
889    this.onRefreshComplete = null;
890
891    this.getSearchKeywords = async (filterArr) => {
892        let data =
893        {
894            filterArr: filterArr,
895        };
896
897        if (data.filterArr == null) {
898            data.filterArr = this.currentData.filterArr;
899        }
900
901        let result = await BaseHelper.MakeAJAXPostJSONRequest("/api/Listing/GetSearchKeywords", data);
902
903        return result;
904    };
905
906
907
908    this.onTemplateLoad = function () {
909        this.ListingSearchItemContainer = this.element.querySelector(".ListingSearchItemContainer")        
910        this.ListingSearchPagination = this.element.querySelector(".ListingSearchPagination");
911        //-------------------------------------------------------------------------
912        //Update loading screen
913        this.fillerContainer = document.createElement("div");
914        this.ListingSearchFillerContainer = document.createElement("div");
915
916        this.fillerContainer.setAttribute("class", "container");
917        this.ListingSearchFillerContainer.setAttribute("class", "ListingSearchFillerContainer row row-cols-1 row-cols-sm-2 row-cols-lg-3 g-3");
918
919        this.fillerContainer.appendChild(this.ListingSearchFillerContainer);
920
921        this.div_loading.innerHTML = "";
922        this.div_loading.appendChild(this.fillerContainer);
923        //-------------------------------------------------------------------------
924        this.ListingSearchPagination.appendChild(this.pBar.element);
925
926        for (let i = 0; i < 20; i++) {
927            let div = this.GetFillerCard();
928            this.ListingSearchFillerContainer.appendChild(div);
929        }
930        this.pBar.onChange = (e) => {
931            if (this.currentData != null) {
932                //refresh and display new page if the current page is different than the page in pBar
933                if (this.currentData.page != this.pBar.currentPage) {
934                    this.currentData.page = this.pBar.currentPage;
935                    this.refresh();
936                }
937            }
938        }
939        //this.btnPrevPage.addEventListener("click", this.onPrevPage);
940        //this.btnNextPage.addEventListener("click", this.onNextPage);
941    };
942
943
944    this.changePage = (diff) => {
945        if (this.currentData == null) {
946            return
947        }
948        this.setPage(this.currentData.page + 1);
949    };
950
951    this.setPage = (page) => {
952        this.currentData.page = page;
953        if (this.currentData == null || this.currentData.data == null || this.currentData.data.PaginatedData == null) {
954            return
955        }
956        let pData = this.currentData.data.PaginatedData;
957        if (this.currentData.page < 0) {
958            this.currentData.page = 0;
959        }
960        if (this.currentData.page >= pData.maxPages) {
961            this.currentData.page = pData.maxPages - 1;
962        }
963    };
964}
965Widgets.ListingSearch.prototype = new Widgets.ListingSearch();

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.