PageSourceSearch

https://www.thrifty.be/themes/thrifty/assets/revamp/js/rqr-qualifications.js?1784884114

js thrifty.be collected 2026-10-07 19:42:31 UTC 13,497 bytes, 344 lines download raw bytes

1// Qualifications & Requirements popup
2$(function () {
3    if (window.location.pathname !== "/review") {
4        return;
5    }
6
7    if (new URLSearchParams(window.location.search).get("country") === "es") {
8        return;
9    }
10
11    var modalHtml =
12        '<div class="rqr-qual-modal">' +
13        '<div class="rqr-qual-overlay"></div>' +
14        '<div class="rqr-qual-box">' +
15        '<div class="rqr-qual-header">' +
16        '<h3 class="rqr-qual-title">Qualifications &amp; Requirements</h3>' +
17        '<span class="rqr-qual-close" aria-label="Close">&times;</span>' +
18        "</div>" +
19        '<div class="rqr-qual-body">' +
20        '<div class="rqr-qual-list"></div>' +
21        '<div class="rqr-qual-loading">Loading...</div>' +
22        '<div class="rqr-qual-error hide">Sorry, this information is temporarily unavailable.</div>' +
23        "</div>" +
24        "</div>" +
25        "</div>";
26    $(modalHtml).appendTo("body");
27
28    var css =
29        ".rqr-qual-modal { display: none; position: fixed; inset: 0; z-index: 10001; }" +
30        ".rqr-qual-modal.show { display: block; }" +
31        ".rqr-qual-overlay { position: absolute; inset: 0; background: rgba(0,0,0,0.5); }" +
32        ".rqr-qual-box { position: relative; background: #fff; width: 90%; max-width: 600px; max-height: 80vh; margin: 6vh auto 0; border-radius: 12px; box-shadow: 0 10px 40px rgba(0,0,0,0.25); display: flex; flex-direction: column; overflow: hidden; }" +
33        ".rqr-qual-header { display: flex; align-items: center; justify-content: space-between; padding: 20px 24px; flex: 0 0 auto; }" +
34        ".rqr-qual-title { margin: 0; font-size: 1.3rem; font-weight: 700; }" +
35        ".rqr-qual-close { cursor: pointer; font-size: 1.4rem; line-height: 1; width: 36px; height: 36px; border-radius: 50%; background: #f0f0f0; display: flex; align-items: center; justify-content: center; }" +
36        ".rqr-qual-body { overflow-y: auto; padding: 0 24px 24px; }" +
37        ".rqr-qual-loading, .rqr-qual-error { padding: 10px 0; color: #666; }" +
38        ".rqr-qual-item { border-bottom: 1px solid #e5e5e5; }" +
39        ".rqr-qual-item:first-child { border-top: 1px solid #e5e5e5; }" +
40        ".rqr-qual-item-header { display: flex; align-items: center; justify-content: space-between; padding: 16px 0; cursor: pointer; }" +
41        ".rqr-qual-item-title { color: var(--bs-primary-color, #005eb8); font-weight: 700; font-size: 1rem; }" +
42        ".rqr-qual-item-chevron { transition: transform 0.2s ease; flex: 0 0 auto; margin-left: 12px; }" +
43        ".rqr-qual-item.open .rqr-qual-item-chevron { transform: rotate(180deg); }" +
44        ".rqr-qual-item-content { display: none; padding: 0 0 16px; color: #333; font-size: 0.9rem; line-height: 1.5; }" +
45        ".rqr-qual-item-content table { max-width: 100%; }" +
46        ".rqr-qual-item-content .rqr-qual-item-loading { color: #888; }";
47    $("<style>").text(css).appendTo("head");
48
49    var RQR_LABELS = {
50        en: {
51            title: "Qualifications &amp; Requirements",
52            loading: "Loading...",
53            error: "Sorry, this information is temporarily unavailable.",
54            noInfo: "No information available.",
55        },
56        fr: {
57            title: "Qualifications et exigences",
58            loading: "Chargement...",
59            error: "Désolé, ces informations sont temporairement indisponibles.",
60            noInfo: "Aucune information disponible.",
61        },
62        es: {
63            title: "Requisitos y condiciones",
64            loading: "Cargando...",
65            error: "Lo sentimos, esta información no está disponible temporalmente.",
66            noInfo: "No hay información disponible.",
67        },
68        de: {
69            title: "Qualifikationen &amp; Anforderungen",
70            loading: "Wird geladen...",
71            error: "Diese Informationen sind vorübergehend nicht verfügbar.",
72            noInfo: "Keine Informationen verfügbar.",
73        },
74        it: {
75            title: "Qualifiche e requisiti",
76            loading: "Caricamento...",
77            error: "Siamo spiacenti, queste informazioni non sono temporaneamente disponibili.",
78            noInfo: "Nessuna informazione disponibile.",
79        },
80        nl: {
81            title: "Kwalificaties en vereisten",
82            loading: "Laden...",
83            error: "Deze informatie is tijdelijk niet beschikbaar.",
84            noInfo: "Geen informatie beschikbaar.",
85        },
86        nb: {
87            title: "Kvalifikasjoner og krav",
88            loading: "Laster...",
89            error: "Beklager, denne informasjonen er midlertidig utilgjengelig.",
90            noInfo: "Ingen informasjon tilgjengelig.",
91        },
92        cs: {
93            title: "Kvalifikace a požadavky",
94            loading: "Načítání...",
95            error: "Tyto informace jsou dočasně nedostupné.",
96            noInfo: "Nejsou k dispozici žádné informace.",
97        },
98        zh: {
99            title: "èµ„æ ¼ä¸Žè¦æ±‚",
100            loading: "åŠ è½½ä¸­...",
101            error: "抱歉,此信息暂时不可用。",
102            noInfo: "æš‚æ— ç›¸å…³ä¿¡æ¯ã€‚",
103        },
104        ja: {
105            title: "è³‡æ ¼ãŠã‚ˆã³è¦ä»¶",
106            loading: "読み込み中...",
107            error: "ç”³ã—è¨³ã”ã–ã„ã¾ã›ã‚“ãŒã€ã“ã®æƒ…å ±ã¯ä¸€æ™‚çš„ã«ã”åˆ©ç”¨ã„ãŸã ã‘ã¾ã›ã‚“ã€‚",
108            noInfo: "åˆ©ç”¨å¯èƒ½ãªæƒ…å ±ãŒã‚ã‚Šã¾ã›ã‚“ã€‚",
109        },
110        ko: {
111            title: "자격 및 요구 사항",
112            loading: "로딩 중...",
113            error: "죄송합니다. 이 ì •ë³´ëŠ” ì¼ì‹œì ìœ¼ë¡œ ì´ìš©í•  수 없습니다.",
114            noInfo: "이용 가능한 ì •ë³´ê°€ 없습니다.",
115        },
116        zt: {
117            title: "è³‡æ ¼èˆ‡è¦æ±‚",
118            loading: "載入中...",
119            error: "很抱歉,此資訊暫時無法使用。",
120            noInfo: "目前沒有相關資訊。",
121        },
122        pl: {
123            title: "Kwalifikacje i wymagania",
124            loading: "Ładowanie...",
125            error: "Przepraszamy, te informacje są tymczasowo niedostępne.",
126            noInfo: "Brak dostępnych informacji.",
127        },
128    };
129
130    function getLabels() {
131        var lang =
132            typeof locale !== "undefined" && locale
133                ? locale.toLowerCase()
134                : "en";
135        return RQR_LABELS[lang] || RQR_LABELS.en;
136    }
137
138    function $modal() {
139        return $(".rqr-qual-modal");
140    }
141    function $list() {
142        return $(".rqr-qual-list");
143    }
144    function $loading() {
145        return $(".rqr-qual-loading");
146    }
147    function $error() {
148        return $(".rqr-qual-error");
149    }
150    var listLoaded = false;
151    var detailsCache = {};
152
153    function getLocationCode() {
154        return $('input[name="PickUpLocationCode"]').val() || pickupOagcode;
155    }
156
157    function getCountryCode() {
158        return (
159            $('input[name="PickUpLocationCountryCode"]').val() ||
160            pickupCountryCode
161        );
162    }
163
164    function openModal() {
165        var labels = getLabels();
166        $modal().addClass("show");
167        $modal().find(".rqr-qual-title").html(labels.title);
168        $loading().text(labels.loading);
169        $error().text(labels.error);
170        if (!listLoaded) {
171            loadList();
172        }
173    }
174
175    function closeModal() {
176        $modal().removeClass("show");
177    }
178
179    function loadList() {
180        $list().empty();
181        $error().addClass("hide");
182        $loading().removeClass("hide");
183
184        var apiBase = window.APP_BASE_URL || window.location.origin;
185        var url =
186            apiBase +
187            "/api/rental-requirements/list?locationCode=" +
188            encodeURIComponent(getLocationCode()) +
189            "&lang=" +
190            encodeURIComponent(locale) +
191            "&countryCode=" +
192            encodeURIComponent(getCountryCode()) +
193            "&vendor=" +
194            encodeURIComponent(vendor);
195
196        fetch(url, { credentials: "include" })
197            .then(function (res) {
198                return res.json();
199            })
200            .then(function (json) {
201                $loading().addClass("hide");
202                if (
203                    !json ||
204                    !json.success ||
205                    !json.data ||
206                    !json.data.data ||
207                    !json.data.data.policyList
208                ) {
209                    $error().removeClass("hide");
210                    return;
211                }
212                var items = [];
213                json.data.data.policyList.forEach(function (group) {
214                    (group.policygroups || []).forEach(function (item) {
215                        items.push(item);
216                    });
217                });
218                renderList(items);
219                listLoaded = true;
220            })
221            .catch(function () {
222                $loading().addClass("hide");
223                $error().removeClass("hide");
224            });
225    }
226
227    function renderList(items) {
228        var $target = $list();
229        items.forEach(function (item) {
230            var $item = $(
231                '<div class="rqr-qual-item" data-policy-id="' +
232                    item.policyId +
233                    '">' +
234                    '<div class="rqr-qual-item-header">' +
235                    '<span class="rqr-qual-item-title"></span>' +
236                    '<span class="rqr-qual-item-chevron">&#9660;</span>' +
237                    "</div>" +
238                    '<div class="rqr-qual-item-content"></div>' +
239                    "</div>",
240            );
241            $item.find(".rqr-qual-item-title").text(item.policyTitle);
242            $target.append($item);
243        });
244    }
245
246    function loadDetails($item) {
247        var policyId = $item.data("policy-id");
248        var $content = $item.find(".rqr-qual-item-content");
249
250        if (detailsCache[policyId]) {
251            $content.html(detailsCache[policyId]);
252            return;
253        }
254
255        var labels = getLabels();
256        $content.html(
257            '<div class="rqr-qual-item-loading">' + labels.loading + "</div>",
258        );
259
260        var apiBase = window.APP_BASE_URL || window.location.origin;
261        var url =
262            apiBase +
263            "/api/rental-requirements/details?requirementId=" +
264            encodeURIComponent(policyId) +
265            "&lang=" +
266            encodeURIComponent(locale) +
267            "&countryCode=" +
268            encodeURIComponent(getCountryCode());
269
270        fetch(url, { credentials: "include" })
271            .then(function (res) {
272                return res.json();
273            })
274            .then(function (json) {
275                var addressArray =
276                    json &&
277                    json.success &&
278                    json.data &&
279                    json.data.data &&
280                    json.data.data.addressArray;
281                if (!addressArray || !addressArray.length) {
282                    $content.html(
283                        '<div class="rqr-qual-item-loading">' +
284                            getLabels().noInfo +
285                            "</div>",
286                    );
287                    return;
288                }
289                var html = addressArray
290                    .slice()
291                    .sort(function (a, b) {
292                        return a.paragraphLevel - b.paragraphLevel;
293                    })
294                    .map(function (p) {
295                        return p.paragraphDescription;
296                    })
297                    .join("");
298                detailsCache[policyId] = html;
299                $content.html(html);
300            })
301            .catch(function () {
302                $content.html(
303                    '<div class="rqr-qual-item-loading">' +
304                        getLabels().error +
305                        "</div>",
306                );
307            });
308    }
309
310    document.addEventListener(
311        "click",
312        function (e) {
313            var trigger =
314                e.target.closest &&
315                e.target.closest(
316                    "a.rqr-qual-trigger, a.rqr-link, .booking-section .booking-check a",
317                );
318            if (!trigger) {
319                return;
320            }
321            e.preventDefault();
322            e.stopImmediatePropagation();
323            openModal();
324        },
325        true,
326    );
327
328    $(document).on("click", ".rqr-qual-close, .rqr-qual-overlay", function () {
329        closeModal();
330    });
331
332    $(document).on("click", ".rqr-qual-item-header", function (e) {
333        e.preventDefault();
334        e.stopPropagation();
335        var $item = $(this).closest(".rqr-qual-item");
336        var $content = $item.find(".rqr-qual-item-content");
337        var wasOpen = $item.hasClass("open");
338        $item.toggleClass("open");
339        $content.stop(true, true).slideToggle(200);
340        if (!wasOpen && $content.is(":empty")) {
341            loadDetails($item);
342        }
343    });
344});

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.