1/** 2 * ÐкÑивиÑÑÐµÑ ÑабоÑÑ Ð¸Ð·Ð±Ñанного на вÑÐµÑ ÑÑÑаниÑÐ°Ñ 3 */ 4new class Favorite extends RsJsCore.classes.component { 5 6 constructor(settings) { 7 super(); 8 let defaults = { 9 favorite: '.rs-favorite-page', //СелекÑÐ¾Ñ Ð±Ð»Ð¾ÐºÐ°, в коÑоÑом оÑобÑажаÑÑÑÑ ÑоваÑÑ Ð½Ð° ÑÑÑаниÑе избÑанного 10 favoriteBlock: '.rs-favorite-block', //Ðлок "избÑанное" 11 favoriteLink: '.rs-favorite-link', //СÑÑлка на front конÑÑÐ¾Ð»Ð»ÐµÑ 12 favoriteCount: '.rs-favorite-items-count', //ÐолиÑеÑÑво избÑаннÑÑ ÑоваÑов 13 favoriteButton: '.rs-favorite', //Ðнопка добавиÑÑ/ÑдалиÑÑ Ð¸Ð·Ð±Ñанное 14 inFavoriteClass: 'rs-in-favorite', //ÐлаÑÑ ÑказÑваÑÑий, ÑÑо ÑÐ¾Ð²Ð°Ñ Ð² избÑанном 15 activeClass: 'active', //ÐлаÑÑ, ÑказÑваÑÑий, ÑÑо в избÑанном еÑÑÑ ÑоваÑÑ 16 context: '[data-id]' 17 }; 18 this.settings = {...defaults, ...this.getExtendsSettings(), ...settings}; 19 } 20 21 /** 22 * ÐниÑиализиÑÑÐµÑ Ð¿Ð¾Ð´Ð¿Ð¸ÑÐºÑ Ð½Ð° ÑобÑÑÐ¸Ñ 23 */ 24 init() { 25 this.blocks = document.querySelectorAll(this.settings.favoriteBlock); 26 let favUrlElement = document.querySelector('[data-favorite-url]'); 27 this.addUrl = favUrlElement && favUrlElement.dataset.favoriteUrl; 28 if (this.addUrl) { 29 this.favoriteCounterElement = document.querySelector(this.settings.favoriteCount); 30 this.utils.on('click', this.settings.favoriteButton, event => this.toggleFavorite(event)) 31 this.utils.on('click', this.settings.favoriteLink, event => { 32 location.href = event.rsTarget.dataset.href; 33 }); 34 35 this.initFirstState(); 36 this.initUpdateTitle(); 37 } else { 38 console.error(lang.t('Ðе найден ÑÐ»ÐµÐ¼ÐµÐ½Ñ [data-favorite-url], ÑодеÑжаÑий ÑÑÑÐ»ÐºÑ Ð½Ð° конÑÑÐ¾Ð»Ð»ÐµÑ ÑпÑÐ°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð·Ð±ÑаннÑм')); 39 } 40 } 41 42 /** 43 * ÐеÑеклÑÑÐ°ÐµÑ ÑоÑÑоÑние ÑоваÑа. ÐомеÑаеÑ/ÐÑклÑÑÐ°ÐµÑ ÑÐ¾Ð²Ð°Ñ Ð¸Ð· избÑанного 44 * 45 * @param event 46 */ 47 toggleFavorite(event) { 48 let productId = event.rsTarget.closest('[data-id]').dataset.id; 49 50 if (event.rsTarget.classList.contains(this.settings.inFavoriteClass)) { 51 this.remove(productId); 52 } else { 53 this.add(productId); 54 } 55 56 event.preventDefault(); 57 } 58 59 /** 60 * ÐобавлÑÐµÑ ÑÐ¾Ð²Ð°Ñ Ð² избÑанное 61 * 62 * @param productId 63 */ 64 add(productId) { 65 this.toggleIcons(productId, true); 66 67 let data = new FormData(); 68 data.append('Act', 'add'); 69 data.append('product_id', productId); 70 71 this.utils.fetchJSON(this.addUrl, { 72 method:'POST', 73 body: data 74 }).then((response) => { 75 this.checkActive(response.count, productId, true); 76 }); 77 } 78 79 /** 80 * ÐеÑеклÑÑÐ°ÐµÑ ÑоÑÑоÑние кнопок в избÑанное 81 * 82 * @param productId 83 * @param active 84 */ 85 toggleIcons(productId, active) { 86 let items = document.querySelectorAll('[data-id="' + productId + '"] ' + this.settings.favoriteButton); 87 items.forEach((element) => { 88 if (active) { 89 element.classList.add(this.settings.inFavoriteClass); 90 } else { 91 element.classList.remove(this.settings.inFavoriteClass); 92 } 93 this.updateTitle(element); 94 }); 95 96 return items; 97 } 98 99 /** 100 * Удаление ÑоваÑа из избÑанного 101 * 102 * @param productId 103 */ 104 remove(productId) { 105 let isFavoritePage; 106 let items = this.toggleIcons(productId, false); 107 items.forEach((element) => { 108 isFavoritePage = element.closest(this.settings.favorite); 109 if (isFavoritePage) { 110 element.closest(this.settings.context).style.opacity = 0.5; 111 } 112 }); 113 114 if (items.length) { 115 let data = new FormData(); 116 data.append('Act', 'remove'); 117 data.append('product_id', productId); 118 119 this.utils.fetchJSON(this.addUrl, { 120 method:'POST', 121 body: data 122 }).then((response) => { 123 if (response.success) { 124 this.checkActive(response.count, productId, false); 125 126 if (isFavoritePage) { 127 this.updateBody(); 128 } 129 } 130 131 }); 132 } 133 } 134 135 /** 136 * ÐбновлÑÐµÑ ÑÑÑаниÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ajax 137 */ 138 updateBody() { 139 this.utils.fetchJSON(window.location.href) 140 .then((response) => { 141 let element = document.querySelector(this.settings.favorite); 142 if (element) { 143 let parent = element.parentNode; 144 element.insertAdjacentHTML('afterend', response.html); 145 element.remove(); 146 parent.dispatchEvent(new CustomEvent('new-content', {bubbles: true})); 147 this.initUpdateTitle(); 148 } 149 }); 150 } 151 152 /** 153 * УÑÑÐ°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°ÐµÑ Ð½ÑжнÑй title, в завиÑимоÑÑи Ð¾Ñ Ñого, добавлен ли в избÑанное ÑÐ¾Ð²Ð°Ñ 154 * 155 * @param element 156 */ 157 updateTitle(element) { 158 let title = element.classList.contains(this.settings.inFavoriteClass) 159 ? element.dataset.alreadyTitle : element.dataset.title; 160 if (typeof(title) != 'undefined') { 161 element.title = title; 162 } 163 } 164 165 /** 166 * ÐниÑиализиÑÑÐµÑ Ð½Ð°ÑалÑное ÑоÑÑоÑние кнопки РизбÑанное Ñ ÑÑеÑом кÑÑа HTML блока 167 */ 168 initFirstState() { 169 if (global.favoriteProducts) { 170 document.querySelectorAll(this.settings.favoriteButton).forEac
170h((element) => { 171 let productId = element.closest(this.settings.context).dataset.id; 172 if (productId) { 173 let isActive = global.favoriteProducts.indexOf(parseInt(productId)) > -1; 174 isActive ? element.classList.add(this.settings.inFavoriteClass) 175 : element.classList.remove(this.settings.inFavoriteClass); 176 } 177 }); 178 } 179 } 180 181 /** 182 * ÐниÑиализиÑÑÐµÑ Ð²ÑплÑваÑÑие подÑказки Ñ ÐºÐ½Ð¾Ð¿Ð¾Ðº Ð ÐзбÑанное 183 */ 184 initUpdateTitle() { 185 document.querySelectorAll(this.settings.favoriteButton + '[data-title]') 186 .forEach((element) => this.updateTitle(element)); 187 } 188 189 /** 190 * ÐобавлÑÐµÑ ÐºÐ»Ð°ÑÑ activeClass к блокÑ, еÑли еÑÑÑ Ñ Ð¾ÑÑ Ð¾Ð´Ð¸Ð½ ÑÐ¾Ð²Ð°Ñ Ð² избÑанном 191 * 192 * @param count 193 */ 194 checkActive(count, productId, productState, noFireOpener) { 195 this.blocks.forEach((block) => { 196 let counter = block.querySelector(this.settings.favoriteCount); 197 counter && (counter.innerHTML = count); 198 199 if (count > 0) { 200 block.classList.add(this.settings.activeClass); 201 } else { 202 block.classList.remove(this.settings.activeClass); 203 } 204 }); 205 206 if (!noFireOpener) { 207 try { 208 //ÐбновлÑем колиÑеÑÑво ÑоваÑов в избÑанном в главном окне 209 window.opener.RsJsCore.components.Favorite.checkActive(count, null, null, true); 210 if (productId) { 211 window.opener.RsJsCore.components.Favorite.toggleIcons(productId, productState); 212 } 213 } catch(e) {} 214 } 215 } 216 217 onDocumentReady() { 218 this.init(); 219 } 220};
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.