PageSourceSearch

https://www.roomlala.ca/assets/module/favorite-0efc123fea02d5a1255ee4fbaaf99f4e.js

js roomlala.ca collected 2026-10-06 07:25:28 UTC 3,775 bytes, 113 lines download raw bytes

1import Notify from '../utils/Notify.js'
2import JsonUtils from '../utils/JsonUtils.js'
3
4// import '../../scss/module/_favorite.scss'
5import Ajax from '../utils/Ajax.js'
6import Header from './Header.js'
7
8// TODO ts
9export default class Favorite {
10    static init() {
11        const favoriteButtons = document.getElementsByClassName('favorite-button')
12        for (let _favoriteButton of favoriteButtons) {
13            _favoriteButton.classList.remove('invisible') // inp improvement
14            this.initListeners(_favoriteButton)
15        }
16    }
17
18    static initListeners(_button) {
19        _button.addEventListener('click', () => {
20            this.clickHandler(_button)
21        })
22        const _detailsHitArea = _button.closest('.ad-details-top-icon--favorite')
23        if (_detailsHitArea && _detailsHitArea !== _button) {
24            _detailsHitArea.addEventListener('click', (event) => {
25                if (event.target.closest('.favorite-button')) {
26                    return
27                }
28                this.clickHandler(_button)
29            })
30        }
31        if (window.APP_IS_CONNECTED) {
32            _button.addEventListener('mouseout', () => {
33                this.mouseOutHandler(_button)
34            })
35        }
36    }
37
38    static clickHandler(_button) {
39        const listingCode = this.getListingCode(_button)
40        const isAlreadyFavorite = _button.classList.contains('active')
41
42        if (!window.APP_IS_CONNECTED) {
43            Header.requireHeaderNotConnected().openSignupModal()
44            return
45        }
46
47        if (0 === listingCode) {
48            throw new Error('Favorite.clickHandler: listingCode is 0')
49        }
50        const _icon = this.getIconTag(_button)
51        if (!_icon) {
52            throw new Error('Favorite.clickHandler: icon tag not found')
53        }
54        const _favFullPhoto = document.getElementById('js-favorite-full-photo-url')
55        const _favEmptyPhoto = document.getElementById('js-favorite-empty-photo-url')
56        if (!_favFullPhoto || !_favEmptyPhoto) {
57            throw new Error('Favorite.clickHandler: photo url tags not found')
58        }
59
60        _button.classList.toggle('active')
61        _icon.src = _button.classList.contains('active')
62            ? _favFullPhoto.value
63            : _favEmptyPhoto.value
64        _button.classList.add('click-in-progress') // to keep color until mouseout
65
66        const data = {
67            listingCode,
68            favorite: isAlreadyFavorite ? 0 : 1,
69        }
70        Ajax.post({
71            url: document.getElementById('js-modify-favorite-url').value, // exposed_listing_search_favorite
72            data,
73            /**
74             * @param {string} response.status
75             * @param {?string} response.successMessage
76             */
77            onResult: (response) => {
78                const data = JsonUtils.parse(response, 'favorite', { listingCode })
79                if ('ok' !== data.status) {
80                    return
81                }
82                if (!data.successMessage) {
83                    return
84                }
85                Notify.success(data.successMessage)
86            },
87        })
88    }
89
90    // to keep color until mouseout
91    static mouseOutHandler(_button) {
92        _button.classList.remove('click-in-progress')
93    }
94
95    static getListingCode(_button) {
96        const listingCode = parseInt(
97            _button?.dataset?.code
98            || _button?.parentElement?.dataset?.code
99            || _button?.closest('[data-code]')?.dataset?.code
100            || '0',
101        )
102
103        return Number.isNaN(listingCode) ? 0 : listingCode
104    }
105
106    static getIconTag(_button) {
107        if (_button instanceof HTMLImageElement) {
108            return _button
109        }
110
111        return _button.querySelector('img')
112    }
113}

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.