PageSourceSearch

https://www.bsdcity-development.com/wp-content/themes/eraindonesia…/page-builder/primary-listing.js?ver=1.12.3

js bsdcity-development.com collected 2026-10-03 00:39:46 UTC 7,944 bytes, 231 lines download raw bytes

1/**
2 * Primary Listing Page Builder Section
3 * Handles loading and displaying primary property listings in grid or slider layout
4 */
5
6(function() {
7    'use strict';
8
9    document.addEventListener('DOMContentLoaded', function() {
10        // Initialize all primary listing sections on the page
11        const sections = document.querySelectorAll('.primary-listing-section');
12        sections.forEach(section => {
13            initPrimaryListingSection(section);
14        });
15    });
16
17    function initPrimaryListingSection(section) {
18        if (!section) return;
19
20        const isSlider = section.dataset.layoutStyle === 'slider';
21        const params = section.dataset.defaultParams;
22        
23        if (!params) {
24            console.error('Primary Listing: No params found');
25            return;
26        }
27
28        // Load properties
29        loadPrimaryListingProperties(section, params, isSlider);
30    }
31
32    function getPrimaryListingApiUrl() {
33        const baseUrl = (typeof global_params !== 'undefined' && global_params.url) ? global_params.url : '';
34        return baseUrl + '/wp-json/bank-expo/v1/primary/filter';
35    }
36
37    function setQueryPage(queryString, page) {
38        const searchParams = new URLSearchParams(queryString);
39        searchParams.set('page', String(page));
40        return searchParams.toString();
41    }
42
43    function requestPrimaryListingPage(queryString, page) {
44        const apiEndpoint = getPrimaryListingApiUrl();
45        const fullUrl = `${apiEndpoint}?${setQueryPage(queryString, page)}`;
46
47        return fetch(fullUrl).then(response => {
48            if (!response.ok) {
49                return response.text().then(text => {
50                    console.error('Primary Listing: Error response:', text);
51                    throw new Error(`HTTP ${response.status}: ${text}`);
52                });
53            }
54            return response.json();
55        });
56    }
57
58    function fetchPrimaryListingRows(queryString, fetchAllPages, maxPages) {
59        return requestPrimaryListingPage(queryString, 1).then(firstResponse => {
60            if (!firstResponse || !firstResponse.data || !Array.isArray(firstResponse.data.rows_html)) {
61                throw new Error('Invalid data structure');
62            }
63
64            const firstRows = firstResponse.data.rows_html;
65            if (!fetchAllPages) {
66                return firstRows;
67            }
68
69            const totalPage = parseInt(firstResponse.data.total_page, 10) || 1;
70            const pagesToFetch = Math.min(totalPage, Math.max(1, maxPages || 1));
71
72            if (pagesToFetch <= 1) {
73                return firstRows;
74            }
75
76            return fetchPrimaryListingPagesSequentially(queryString, 2, pagesToFetch).then(extraRows => {
77                return firstRows.concat(extraRows);
78            });
79        });
80    }
81
82    function fetchPrimaryListingPagesSequentially(queryString, fromPage, toPage) {
83        let chain = Promise.resolve([]);
84
85        for (let page = fromPage; page <= toPage; page++) {
86            const pageNum = page;
87            chain = chain.then(rows =>
88                requestPrimaryListingPage(queryString, pageNum).then(response => {
89                    if (response && response.data && Array.isArray(response.data.rows_html)) {
90                        return rows.concat(response.data.rows_html);
91                    }
92                    return rows;
93                })
94            );
95        }
96
97        return chain;
98    }
99
100    function loadPrimaryListingProperties(section, encodedParams, isSlider) {
101        let params;
102
103        try {
104            params = atob(encodedParams);
105        } catch (e) {
106            console.error('Primary Listing: Invalid base64 params:', e);
107            showError(section, 'Invalid parameters');
108            return;
109        }
110
111        const fetchAllPages = section.dataset.fetchAllPages === '1';
112        const maxPages = parseInt(section.dataset.maxPages, 10) || 20;
113
114        fetchPrimaryListingRows(params, fetchAllPages, maxPages)
115            .then(rowsHtml => {
116                if (!rowsHtml.length) {
117                    console.warn('Primary Listing: No rows returned');
118                    showError(section, 'No properties available');
119                    return;
120                }
121                renderPropertiesFromHTML(section, rowsHtml, isSlider);
122            })
123            .catch(error => {
124                console.error('Primary Listing: Error loading properties:', error);
125                showError(section, 'Error loading properties: ' + error.message);
126            });
127    }
128
129    function renderPropertiesFromHTML(section, htmlArray, isSlider) {
130        const wrapper = isSlider 
131            ? section.querySelector('.primary-listing-wrapper')
132            : section.querySelector('.primary-listing-grid-wrapper');
133        
134        if (!wrapper) {
135            console.error('Primary Listing: Wrapper not found');
136            return;
137        }
138
139        // Clear loading state
140        wrapper.innerHTML = '';
141
142        if (htmlArray.length === 0) {
143            wrapper.innerHTML = '<div class="no-properties"><p>No properties available at this time.</p></div>';
144            return;
145        }
146
147        // Render each property HTML
148        htmlArray.forEach((cardHtml) => {
149            const tempDiv = document.createElement('div');
150            tempDiv.innerHTML = cardHtml.trim();
151            const card = tempDiv.firstElementChild;
152            
153            if (card) {
154                if (isSlider) {
155                    const slideDiv = document.createElement('div');
156                    slideDiv.className = 'swiper-slide primary-listing-slide';
157                    slideDiv.appendChild(card);
158                    wrapper.appendChild(slideDiv);
159                } else {
160                    const cardWrapper = document.createElement('div');
161                    cardWrapper.className = 'primary-listing-card-wrapper';
162                    cardWrapper.appendChild(card);
163                    wrapper.appendChild(cardWrapper);
164                }
165            }
166        });
167
168        // Initialize Swiper if slider layout
169        if (isSlider) {
170            initializePrimaryListingSwiper(section);
171        }
172        
173        // Initialize card galleries (for image sliders within cards)
174        if (typeof window.reinitializeCardGalleries === 'function') {
175            setTimeout(function() {
176                window.reinitializeCardGalleries();
177            }, 100);
178        }
179    }
180
181    function initializePrimaryListingSwiper(section) {
182        const swiperContainer = section.querySelector('.primary-listing-swiper');
183        const prevBtn = section.querySelector('.nav-prev');
184        const nextBtn = section.querySelector('.nav-next');
185
186        if (!swiperContainer) return;
187
188        new Swiper(swiperContainer, {
189            slidesPerView: 'auto',
190            spaceBetween: 0,
191            allowTouchMove: true,
192            grabCursor: true,
193            navigation: {
194                nextEl: nextBtn,
195                prevEl: prevBtn,
196            },
197            breakpoints: {
198                320: {
199                    slidesPerView: 1
200                },
201                768: {
202                    slidesPerView: 1.5
203                },
204                1024: {
205                    slidesPerView: 2.2
206                }
207            }
208        });
209    }
210
211    function showError(section, message) {
212        const wrapper = section.querySelector('.primary-listing-wrapper') || 
213                       section.querySelector('.primary-listing-grid-wrapper');
214        
215        if (wrapper) {
216            wrapper.innerHTML = `<div class="error-message"><p>${escapeHtml(message)}</p></div>`;
217        }
218    }
219
220    function escapeHtml(text) {
221        const map = {
222            '&': '&amp;',
223            '<': '&lt;',
224            '>': '&gt;',
225            '"': '&quot;',
226            "'": '&#039;'
227        };
228        return String(text).replace(/[&<>"']/g, m => map[m]);
229    }
230
231})();

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.