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.