PageSourceSearch

https://timessquare.com.hk/wp-content/themes/timessquaretheme2020/…?ver=202609241742281790271748.1786

js timessquare.com.hk collected 2026-09-24 17:43:33 UTC 28,515 bytes, 705 lines download raw bytes

1/**
2 * Created by waimansing on 11/1/2021.
3 */
4$(document).ready(function () {
5    const setCookie = (cname, cvalue, exdays = 1) => {
6        const d = new Date();
7        d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
8        let expires = "expires=" + d.toUTCString();
9        // document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
10        document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/;sameSite=None;secure=true";
11//        Cookies.set(cname, cvalue, {sameSite: 'None', secure: true, expires: expires});
12    }
13
14    function getCookie(cname) {
15        let name = cname + "=";
16        let ca = document.cookie.split(';');
17        for (let i = 0; i < ca.length; i++) {
18            let c = ca[i];
19            while (c.charAt(0) === ' ') {
20                c = c.substring(1);
21            }
22            if (c.indexOf(name) === 0) {
23                return c.substring(name.length, c.length);
24            }
25        }
26        return "";
27    }
28
29    const logout = (targetHref = '') => {
30        // console.log('logout');
31        setCookie("SessionKey", '', -1);
32        setCookie("MemberNo", '', -1);
33        changeLocation(targetHref);
34    }
35
36    const getLang = () => {
37        return document.getElementsByTagName('html')[0]?.getAttribute('lang')?.toLowerCase();
38    }
39    const getLangInt = () => {
40        const lang = getLang();
41        if (lang.startsWith('en')) {
42            return 1;
43        } else if (lang.startsWith('zh-cn')) {
44            return 3;
45        }
46        return 2;
47    }
48
49    const getErrorMsg = (data) => {
50        const lang = getLang();
51        const langKey = lang.startsWith('en') ? 'Message' : lang === 'zh-cn' ? 'MessageSC' : 'MessageTC';
52        return data[langKey] ?? data.message;
53    }
54
55    const displaySuccessMsg = () => {
56        const msg = {
57            'Message': 'Success',
58            'MessageSC': '成功',
59            'MessageTC': '成功',
60        }
61        return getErrorMsg(msg);
62    }
63
64    const buttonCountdown = (btn, count = 61) => {
65        const text = btn.text();
66        btn.attr('disabled', true);
67        const resendInterval = setInterval(() => {
68            if (count-- >= 0) {
69                btn.attr('disabled', true);
70                btn.text(`${count}s`);
71            } else {
72                btn.text(text);
73                btn.attr('disabled', false);
74                clearInterval(resendInterval);
75            }
76        }, 1000);
77    }
78
79    const openModal = (id, actionFn) => {
80        $(id).addClass('hr-show');
81        if (actionFn) actionFn();
82    }
83
84    const changeLocation = (targetLoc) => {
85        const currentPage = window.location || window.document.location;
86        try {
87            const url = new URL(targetLoc);
88            if (currentPage.hostname === url.hostname) {
89                window.location = url;
90                return
91            }
92        } catch (e) {
93        }
94        window.location.reload();
95    }
96    const formChangePage = (formId) => {
97        const targetLoc = $(formId).attr("data-target");
98        changeLocation(targetLoc);
99    }
100
101    const generateQRCode = (elemId, text, width = 140, height = 140) => {
102        new QRCode(document.getElementById(elemId), {
103            text: text,
104            width: width,
105            height: height,
106        });
107    }
108
109    const groupArrayByKey = (array, groupKeys, countKey, stackKey, stackResultKey, otherStackKeyArray) => {
110        const groupedArray = [];
111        // console.log(groupKeys);
112        array.forEach((a) => {
113            const index = groupedArray.findIndex((g) => {
114                return groupKeys.reduce((prev, key) => prev && g[key] === a[key], true);
115            });
116            // console.log(a, index);
117            // exist
118            if (index > -1) {
119                const count = groupedArray[index][countKey];
120                groupedArray[index][countKey] = count + 1;
121                const stacked = groupedArray[index][stackResultKey];
122                stacked.push(a[stackKey])
123                groupedArray[index][stackResultKey] = stacked;
124
125                otherStackKeyArray.forEach((otherStackKey) => {
126                    const _otherStackedKey = "_" + otherStackKey;
127                    const otherStackedArray = groupedArray[index][_otherStackedKey] ?? [];
128                    otherStackedArray.push(a[otherStackKey])
129                    groupedArray[index][_otherStackedKey] = otherStackedArray;
130                })
131            } else {
132                a[countKey] = 1;
133                groupedArray.push(a);
134                a[stackResultKey] = [a[stackKey]];
135                otherStackKeyArray.forEach((otherStackKey) => {
136                    a["_" + otherStackKey] = [a[otherStackKey]];
137                })
138            }
139        })
140        return groupedArray;
141    }
142
143    const generateRewards = (rewards) => {
144        const img = rewards['ImageURL'];
145        const name = rewards['Name'];
146        const till = rewards['EffectiveTo'];
147        const id = rewards['RewardId'];
148        const lang = getLangInt();
149        const _redeem_til = lang === 1 ? "Redemption Until:" : (lang === 3 ? "兑换期至:" : '兌換期至:');
150        const _more = lang === 1 ? "MORE DETAILS" : (lang === 3 ? "详情" : '詳情');
151
152        return `<div class='hrdm-reward-card'>
153<img class="hrdmc-img" src="${img}" alt="${name}">
154<div class="hrdmc-wrapper">
155<div class="hrdmc-name font-h fs-21 fw-600">${name}</div>
156<div class="hrdmc-details">
157<div class="hrdmc-details-l">
158<div class="hrdmc-until font-h fs-16 fw-600">${_redeem_til}</div>
159<div class="hrdmc-until-date font-h fs-16 fw-300">${till}</div>
160</div>
161<div class="hrdmc-details-r hrdmc-view-details-click" data-reward-id='${id}'>
162<div class="font-h fs-16 fw-600">${_more}</div>
163<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewB
163ox="0 0 20.738 20.738">
164  <g transform="translate(-1782.714 -1638.547)">
165    <path data-name="Icon material-arrow_back" d="M20.738,9.073H4.964L12.21,1.828,10.369,0,0,10.369,10.369,20.738,12.2,18.911,4.964,11.665H20.738Z" transform="translate(1803.452 1659.286) rotate(180)"/>
166  </g>
167</svg>
168</div>
169</div>
170</div>
171</div>`;
172    }
173
174    const generateGift = (gift, node) => {
175        const img = gift['ImageURL'];
176        const qty = gift['_count'];
177        // const til = gift['ExpiryDate'];
178        const expiryList = {};
179        gift['_ExpiryDate'].forEach((date) => {
180            if (date in expiryList) {
181                expiryList[date] += 1;
182            } else {
183                expiryList[date] = 1;
184            }
185        });
186        const til = Object.keys(expiryList).map((key) => `${key} (${expiryList[key]})`).join(", ");
187        const name = gift['RewardName'];
188        const status = gift['Status'].toLowerCase();
189        const stackedGifts = gift['_gift'].join(',');
190        const lang = getLangInt();
191        const _qty = lang === 1 ? "QTY" : (lang === 3 ? "数量" : '數量');
192        const _redeem_til = lang === 1 ? "Redemption Until:" : (lang === 3 ? "兑换期至:" : '兌換期至:');
193        const _use = lang === 1 ? "USE NOW" : '使用';
194        const _use_date = lang === 1 ? "Use Date:" : (lang === 3 ? "使用时间:" : '使用時間:');
195        const _expired_date = lang === 1 ? "Expired Date:" : '使用期限:';
196        const _view_details = lang === 1 ? "View Details" : (lang === 3 ? '查看详情' : '查看詳情');
197
198        let innerNode = "";
199        if (status === 'active') {
200            innerNode = `<div class="hrdmc-gift-qty"><b>${_qty}:</b><br/>${qty}</div>
201<div class="hrdmc-gift-til"><b>${_redeem_til}</b> ${til}</div>
202<div class="hrdmc-gift-btn">
203    <button class="btn-explore-more hr-login hrdmc-use-coupon" data-name="${name}" data-qty="${qty}" data-gift="${stackedGifts}">${_use}</button>
204    <div class="hrdmc-view-more hrdmc-view-details-click" data-gift-id="${stackedGifts.split(",")[0]}">
205        ${_view_details}
206        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 20.738 20.738">
207            <g transform="translate(-1782.714 -1638.547)">
208                <path data-name="Icon material-arrow_back" d="M20.738,9.073H4.964L12.21,1.828,10.369,0,0,10.369,10.369,20.738,12.2,18.911,4.964,11.665H20.738Z" transform="translate(1803.452 1659.286) rotate(180)"/>
209            </g>    
210        </svg>
211    </div>
212</div>`
213        } else {
214            const usedDate = gift['_DateUsed'].join(" // ");
215            const text = status === 'used' ? `<b>${_use_date}</b> ${usedDate}` : `<b>${_expired_date}</b> ${til}`
216            innerNode = `<div>${text}</div>`;
217        }
218
219        const refNo = gift['_ReferenceNo'].filter(n => n).join(", ");
220        const refNoText = (status === 'used' && refNo) ? `<br/>(Ref#: ${refNo})` : '';
221
222        const finalNode = `<div class="hrdmc-gift-wrapper --${status}">
223<img class="hrdmc-gift-img" src="${img}" alt="${name}">
224<div class="hrdmc-gift-r font-h fs-21">
225<div class="hrdmc-gift-name fw-600">${name}${refNoText}</div>
226${innerNode}
227</div>
228</div>`;
229        node.append(finalNode);
230    }
231
232    const binaryHideField = (field1, field2, showField1) => {
233        field1.css('display', showField1 ? 'block' : 'none');
234        field2.css('display', showField1 ? 'none' : 'block');
235    }
236
237    const dataHandler = (action, resData, formData) => {
238        switch (action) {
239            case "login":
240                setCookie('SessionKey', resData['SessionKey']);
241                setCookie('MemberNo', resData['MemberNo']);
242                formChangePage("#login-form");
243                break;
244            case "register":
245                // console.log(formData);
246                openModal('#verifyModal', () => {
247                    const mobileNo = formData['MobileNoDistrict'] + formData['MobileNo'];
248                    $('#hr-ver-mob').val(mobileNo);
249                    $('#hr-ver-mob2').val(mobileNo);
250
251                    const emailAddress = formData['EmailAddress'];
252                    $('#hr-ver-email').val(emailAddress);
253                    $('#hr-ver-email2').val(emailAddress);
254
255                    const mobileWrapper = $('#hr-ver-mob-wrapper');
256                    const emailWrapper = $('#hr-ver-email-wrapper');
257                    const isLocalMobile = mobileNo.startsWith('+852-');
258                    binaryHideField(mobileWrapper, emailWrapper, isLocalMobile);
259
260                    const memberNo = resData['MemberNo'];
261                    $('#hr-ver-member-no2').val(memberNo);
262
263                    if (!isLocalMobile) {
264                        $("#hr-ver-resend-btn").click();
265                    }
266                })
267                break;
268            case "verify":
269                const verifyForm = $("#verify-form");
270
271                const targetLoc = verifyForm.attr("data-target");
272                verifyForm.find(".display-error").text(displaySuccessMsg());
273                setTimeout(() => {
274                    changeLocation(targetLoc);
275                }, 1500);
276                break;
277            case "resend":
278                const resendFormSubmit = $("#resend-form").find('.form-submit');
279                buttonCountdown(resendFormSubmit);
280                break;
281            // change password
282            case 'change':
283                break;
284            case 'gift_list':
285                const allGift = resData['Gifts'];
286                const validGift = $('#hrdm-valid');
287                const usedGift = $('#hrdm-used');
288                const expiredGift = $('#hrdm-expired');
289                validGift.text('');
290                usedGift.text('');
291                expiredGift.text('');
292                if (allGift && allGift.length > 0) {
293                    let sortedGift = allGift.sort((a, b) => a['ExpiryDate'].localeCompare(b['ExpiryDate']));
294                    const groupedGift = groupArrayByKey(
295                        sortedGift,
296                        ['Status', 'RewardId'/*'TimeStampVal'*/],
297                        '_count',
298                        'GiftId',
299                        '_gift',
300                        ["ReferenceNo", "ExpiryDate", "DateUsed"]
301                    );
302                    console.log(groupedGift);
303                    groupedGift.forEach((gift) => {
304                        const node = gift['Status'] === 'Active' ? validGift :
305                            (gift['Status'] === 'Used' ? usedGift : expiredGift);
306                        generateGift(gift, node);
307                    })
308                } else {
309                    const lang = getLangInt();
310                    const _no_gift = lang === 1 ? "No available gifts" : (lang === 3 ? "没有纪录" : '沒有紀錄');
311                    $('#hrdm-no-gift').text(_no_gift);
312                }
313                break;
314            case 'reward': {
315                const allRewards = resData['Rewards'];
316                const target = $('.hrd-content-reward');
317                const touristTarget = $('.hrd-content-tourist-reward');
318                const touristRewards = allRewards?.filter((r) => r.Tags.toLowerCase().includes("tourist")) ?? [];
319                const normalRewards = allRewards?.filter((r) => !r.Tags.toLowerCase().includes("tourist")) ?? [];
320
321                const lang = getLangInt();
322                const _noReward = lang === 1 ? 'Coming soon. Stay tuned!' :
323                    (lang === 3 ? "惊喜优惠即将登场,密切留意。" : '驚喜優惠即將登場,密切留意。');
324
325                if (touristRewards.length > 0) {
326                    const html = touristRewards.reduce((p, c) => p + generateRewards(c), '');
327                    touristTarget.html(html);
328                } else {
329                    touristTarget.text(_noReward);
330                }
331
332                if (normalRewards.length > 0) {
333                    // console.log(allRewards);
334                    const html = normalRewards.reduce((p, c) => p + generateRewards(c), '');
335                    target.html(html);
336                    // noGiftDiv.text('');
337                } else {
338                    target.text(_noReward);
339                    // noGiftDiv.text(_noReward);
340                }
341            }
342                break;
343            case 'reward_detail':
344            case 'gift_detail':
345                // console.log(resData);
346                openModal('#rewardDetailsModal');
347                $('.hrd-general').css('display', 'none');
348                $('.hrdh-img').css('display', 'none');
349                $('.hrd-reward').css('display', '');
350                $('.hrd-content-details form').css('display', action === 'gift_detail' ? 'none' : "");
351
352                const image = $('.hrdr-img');
353                image.css('display', '');
354                const lang = getLangInt();
355                const _now_til = lang === 1 ? "NOW TILL " : "直至";
356                $('.hrdr-date').text(`${_now_til}${resData['EffectiveTo'] ?? resData['ExpiryDate']}`);
357                $('.hrdr-title').text(resData['Name'] ?? resData['RewardName']);
358                image[0].src = resData['ImageURL'];
359                $('.hrdr-content').html(resData['Description']);
360                $('.hrdr-tnc-content').html(resData['TAC'] ?? resData['RewardTAC']);
361                $('.hrd-head-wrapper').addClass('--reward');
362                $('.hrdr-redeem-input').val(resData['RewardId']);
363                break;
364            case 'reserve_reward':
365                $('.hrdrm-loading').css('display', 'none');
366                $('.hrdrm-ok').css('display', '');
367                setTimeout(() => {
368                    memberDataSessionChanged('hrdh-wallet');
369                }, 800);
370                break;
371            case 'use':
372                $("#hr-use-submit").attr("disabled", true);
373                $("#hr-use-error").text(`Success. Reference No.: ${resData['ReferenceNo']}`);
374                handleMemberDataHeaderActionClick('hrdh-wallet');
375                $(".hr-modal-cross").attr("data-fresh", "wallet");
376                break;
377            case 'otp': {
378                const lang = getLangInt();
379                const _sent = lang === 1 ? "One-time password has been sent to your mailbox" :
380                    (lang === 3 ? "一次性密码已发送到你的电子邮箱内" : "一次性密碼已發送到你的電子郵箱內");
381                $("#hr-reset-error").text(_sent);
382                buttonCountdown($("#hr-otp-btn"));
383            }
384                break;
385            case 'reset': {
386                const lang = getLangInt();
387                const _sent = lang === 1 ? "New password has been sent to your mailbox" :
388                    (lang === 3 ? "新密码已发送到你的电子邮箱内" : "新密碼已發送到你的電子郵箱內");
389                $("#hr-reset-error").text(_sent);
390            }
391                break;
392        }
393    }
394
395    const callAjaxAction = (formAction, targetAction, formData = undefined, mForm = undefined, errorDiv = undefined, submitBtn = undefined) => {
396        const lang = getLangInt();
397
398        const originSubmitText = submitBtn?.text();
399        submitBtn?.html('<div class="lds-ring"><div></div><div></div><div></div><div></div></div>');
400
401        jQuery.ajax({
402            url: sbiajaxurl + "?action=" + formAction,
403            data: {data: formData, lang: lang},
404            type: 'POST',
405            success: (data) => {
406                if (data.includes('{')) {
407                    const i = data.indexOf('{');
408                    data = data.slice(i);
409                }
410                data = data.replace(/\d*$/, "");
411                try {
412                    data = JSON.parse(data);
413                    //   console.log(data, data['code'], data['code'] === 0);
414                    if (data['code'] === 0) {
415                        // console.log(targetAction, data['data'], formData);
416                        dataHandler(targetAction, data['data'], formData);
417                        if (!submitBtn?.data('preserve')) {
418                            mForm?.reset();
419                        }
420                        if (targetAction === 'change') {
421                            errorDiv.text(getErrorMsg(data));
422                        }
423                    } else {
424                        const errorMessage = getErrorMsg(data);
425                        if (errorDiv) errorDiv.text(errorMessage);
426                        if (targetAction === 'reserve_reward') {
427                            const failWrapper = $('.hrdrm-no');
428                            failWrapper.css('display', '');
429                            $('.hrdrm-loading').css('display', 'none');
430                            failWrapper.find('.hrdrm-content').text(errorMessage);
431                        } else if (targetAction === 'gift_list') {
432                            logout();
433                        }
434                    }
435                } catch (e) {
436                    // console.error(e);
437                    errorDiv?.text('Internal server error. Please retry again later.');
438                }
439            },
440            error: (err) => {
441                try {
442                    err = JSON.parse(err);
443                    errorDiv?.text(getErrorMsg(err) ?? err?.message ?? 'Server error. Please retry again later');
444                } catch (e) {
445                    console.error(e);
446                    errorDiv?.text(`Internal Server error. Please retry again later.`);
447                }
448            },
449            complete: () => {
450                submitBtn?.attr("disabled", false);
451                submitBtn?.text(originSubmitText);
452            }
453        });
454    };
455
456
457
458    // register tourist
459    $("#tourist-terms").click((e) => {
460        e.preventDefault();
461        openModal("#tourist-tnc-modal");
462    });
463    $("#form-hr-register").on('change', '#hr-country', function () {
464        let selectedValue = $(this).find("option:selected").val();
465        // console.log(selectedValue);
466        const touristCheckBox = $("#hr-tourist-tnc-checkbox");
467        if (parseInt(selectedValue) === 1) {
468            $("#hr-tourist-tnc").hide();
469            touristCheckBox.prop("checked", false);
470            touristCheckBox.removeAttr("required");
471            // $("input#form-P_AGREE_TOURIST").removeAttr("required");
472        } else {
473            $("#hr-tourist-tnc").show();
474            touristCheckBox.attr("required", "required");
475        }
476    });
477
478
479    document.querySelectorAll('form.submitForm').forEach((e) => {
480        e.addEventListener('submit', (e) => {
481            // console.log(e);
482            e.preventDefault();
483            // e.stopPropagation();
484            const mForm = $(e.target);
485            var errorDiv = mForm.find('.display-error');
486            errorDiv.text('');
487
488            var submitBtn = $(e.submitter);
489            submitBtn.attr("disabled", true);
490
491            const formData = mForm.serializeArray().reduce((o, kv) => ({...o, [kv.name]: kv.value}), {});
492            var formAction = submitBtn.data('name') ?? mForm.attr('name');
493            var targetAction = submitBtn.attr('data-type') ?? mForm.attr('data-type');
494
495            // console.log(formAction, targetAction);
496
497            // special handle for otp
498            if (targetAction === 'reset' && formData.OneTimePassword === '') {
499                const optBtn = $("#hr-otp-btn");
500                if (optBtn.attr('disabled') !== 'disabled') {
501                    formAction = 'post_hr_otp';
502                    targetAction = 'otp';
503                    submitBtn.attr("disabled", false);
504                    submitBtn = optBtn;
505                }
506            } else if (targetAction === 'register') {
507                const countryInt = formData['Country'];
508                console.log(countryInt);
509                if (+countryInt >= 4) {
510                    formData['Country'] = 4;
511                    formData['OtherArea'] = $("#hr-country option:selected").text();
512                }
513            }
514
515            callAjaxAction(formAction, targetAction, formData, mForm[0], errorDiv, submitBtn);
516
517            return false;
518        }, {passive: false})
519    })
520
521    // open modals
522    $('[data-bs-toggle="modal"]').each((i, el) => {
523        // console.log(el);
524        const target = el.getAttribute('data-bs-target');
525        if (target) {
526            const targetNode = $(target);
527            el.addEventListener('click', () => {
528                targetNode.addClass('hr-show');
529            })
530        }
531    });
532    $('.hr-modal-cross, .hr-modal-close').each((i, el) => {
533        el.addEventListener('click', () => {
534            const parentModal = $(el).parents('.hr-modal');
535            parentModal?.removeClass('hr-show');
536            parentModal?.find('form')?.trigger('reset');
537            $("#hr-use-error").text("");
538        })
539    });
540
541    // member details page
542    const memberDataSessionChanged = (id) => {
543        const walletDisplay = id === 'hrdh-wallet' ? '' : 'none';
544        const rewardDisplay = id === 'hrdh-reward' ? '' : 'none';
545        const touristDisplay = id === 'hrdh-tourist' ? '' : 'none';
546
547        $('.hrd-back').attr('data-target', '');
548
549        $('.hrd-content-reward').css('display', rewardDisplay);
550        $('.hrd-title.--reward').css('display', rewardDisplay);
551
552        $('.hrd-content-tourist-reward').css('display', touristDisplay);
553        $('.hrd-title.--tourist').css('display', touristDisplay);
554
555        $('.hrd-content-wallet').css('display', walletDisplay);
556        $('.hrd-title.--wallet').css('display', walletDisplay);
557
558        $('#hrd-logout-text').text(getLangInt() === 1 ? 'logout' : '登出');
559
560        // remove reward session
561        $('.hrd-general').css('display', '');
562        $('.hrdh-img').css('display', '');
563        $('.hrd-head-wrapper').removeClass('--reward');
564
565        $('.hrd-content-details').css('display', 'none');
566        $('.hrd-reward').css('display', 'none');
567        $('.hrdr-img').css('display', 'none');
568    }
569
570    const handleMemberDataHeaderActionClick = (id) => {
571        switch (id) {
572            case 'hrdh-pwd':
573                openModal('#changePwdModal');
574                break;
575            case 'hrdh-wallet':
576                memberDataSessionChanged(id);
577                if ($('#hrdm-valid').children().length === 0) {
578                    $('#hrdm-no-gift').text();
579                    callAjaxAction('get_hr_gift', 'gift_list');
580                }
581                break;
582            case 'hrdh-reward':
583            case 'hrdh-tourist':
584                memberDataSessionChanged(id);
585                if ($('.hrd-content-reward').children().length === 0) {
586                    $('#hrdm-no-gift').text();
587                    callAjaxAction('get_hr_avail_reward', 'reward');
588                }
589                break;
590            case 'hrdh-shop':
591                window.open('https://eshop.timessquare.com.hk', '_blank');
592                break;
593            case 'hrdm-valid':
594                // callAjaxAction('get_hr_gift', 'valid');
595                break;
596            case 'hrdm-used':
597                // callAjaxAction('get_hr_redeemed_gift', 'used');
598                break;
599            case 'hrdm-expired':
600                // callAjaxAction('get_hr_redeemed_gift', 'expired');
601                break;
602        }
603    }
604
605    $('#hr-member-action').click((e) => {
606        let self = $(e.target);
607        if (!self.hasClass('hrdh-action')) {
608            self = self.parents('.hrdh-action');
609        }
610        // console.log(self, $(e.target));
611        if (self.length > 0) {
612            handleMemberDataHeaderActionClick(self[0].id);
613        }
614    });
615
616    // click reward details
617    $(document).on('click', '.hrdmc-view-details-click', (e) => {
618        let self = $(e.target);
619        if (!self.hasClass('hrdmc-view-details-click')) {
620            self = self.parents('.hrdmc-view-details-click');
621        }
622        if (self) {
623            const rewardId = self.data('reward-id');
624            const giftId = self.data('gift-id');
625            if (!rewardId && !giftId) return;
626
627            // change page header and content
628            $('.hrd-title').css('display', 'none');
629            $('.hrd-content-reward').css('display', 'none');
630            $('.hrd-content-tourist-reward').css('display', 'none');
631            $('.hrd-content-details').css('display', '');
632            // change redeem modal display
633            $('.hrdrm-result').css('display', 'none');
634            $('.hrdrm-loading').css('display', '');
635            $('.hrd-content-wallet').css('display', 'none');
636
637            $('#hrd-logout-text').text(getLangInt() === 1 ? 'Back' : '返回');
638            const formData = {};
639            window.scrollTo(0, 0);
640            // back to reward list for reward, wallet page for gift
641            $('.hrd-back').attr('data-target', rewardId ? 'reward' : 'wallet');
642
643            if (rewardId) {
644                formData['RewardId'] = rewardId;
645                callAjaxAction('get_hr_reward_detail', 'reward_detail', formData);
646            } else if (giftId) {
647                formData['GiftId'] = giftId;
648                callAjaxAction('get_hr_gift_detail', 'gift_detail', formData);
649            }
650        }
651    });
652
653    // click use coupon
654    $(document).on('click', '.hrdmc-use-coupon', (e) => {
655        let self = $(e.target);
656        const name = self.data('name');
657        $('.hrdm-use-name').text(name);
658
659        const qty = self.data('qty');
660        const gift = self.data('gift');
661
662        $("#hr-giftIds").val(gift);
663        const selectLabel = $("#hr-qty-label");
664        const labelText = selectLabel.text();
665        selectLabel.text(labelText.replace(/\d+/g, qty));
666        const select = $("#hr-qty");
667        select.empty();
668        for (let i = 1; i <= +qty; i++) {
669            const option = `<option value="${i}">${i}</option>`;
670            select.append(option);
671        }
672
673        $('#useModal').addClass('hr-show');
674
675    })
676
677    if ($('#hrdm-no-gift').length > 0) {
678        handleMemberDataHeaderActionClick('hrdh-wallet');
679    }
680
681    // qr code
682    const qrDiv = $("#hrdh-qr-code");
683    if (qrDiv.length > 0) {
684        generateQRCode('hrdh-qr-code', qrDiv.data('type'));
685    }
686
687    // back
688    const hrBack = $("#hrd-back");
689    if (hrBack.length > 0) {
690        hrBack.on('click', (e) => {
691            if ($(".hrd-general").css('display') === 'none') {
692                const self = $(e.target)
693                memberDataSessionChanged(`hrdh-${self.data('target') ?? 'reward'}`);
694            } else {
695                logout(hrBack.data('href'));
696            }
697        })
698    }
699
700    // default show exclusive rewards
701    if ($("#hrdh-reward").length > 0) {
702        handleMemberDataHeaderActionClick('hrdh-reward');
703    }
704
705});

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.