1$(document).ready(function () { 2 var ACTIVE_ITEM_CLASS = 'app-desktop-search__popup-link_active'; 3 4 /* ------------------------------------------------------------------ */ 5 /* ÐÑкÑÑÑие / закÑÑÑие блока авÑÐ¾Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ */ 6 /* ------------------------------------------------------------------ */ 7 8 function openSearchPopup() { 9 $('.js-search-ac-body').addClass('is-open'); 10 } 11 12 function closeSearchPopup() { 13 var $acBody = $('.js-search-ac-body'); 14 // СкÑÑваем блок авÑÐ¾Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÑÑазÑ, ÑÑÐ¾Ð±Ñ Ð½Ðµ бÑло "половинÑ" конÑенÑа. 15 $acBody.removeClass('is-open'); 16 // console.log('closeSearchPopup'); 17 $('.app-desktop-search__input-wrap').removeClass('has-value'); 18 clearActiveItem(); 19 renderSuggestions([]); 20 21 // Ðолное закÑÑÑие поиÑка в Ñапке без пÑогÑаммного click() 22 // (инаÑе полÑÑаем ÑекÑÑÑÐ¸Ñ Ð¾Ð±ÑабоÑÑиков и stack overflow). 23 var $desktopSearchBtn = $('.app-desktop-search-btn'); 24 // ÐапÑÑкаем обÑаÑнÑÑ Ð°Ð½Ð¸Ð¼Ð°ÑÐ¸Ñ ÑÐ½Ð¸Ð·Ñ Ð²Ð²ÐµÑÑ . 25 $desktopSearchBtn.addClass('for-close search-popup-animation search-form-active'); 26 $('.app-search-backdrop').remove(); 27 $('body').removeClass('search-popup-is-opening'); 28 29 setTimeout(function () { 30 $desktopSearchBtn.removeClass('for-close search-popup-active search-popup-animation search-form-active'); 31 }, 600); 32 33 if ($(window).scrollTop() < 1) { 34 $('body').addClass('app-scroll-pos-top'); 35 } 36 } 37 38 /* ------------------------------------------------------------------ */ 39 /* ÐкÑивнÑй ÑÐ»ÐµÐ¼ÐµÐ½Ñ (навигаÑÐ¸Ñ ÑÑÑелками) */ 40 /* ------------------------------------------------------------------ */ 41 42 function clearActiveItem() { 43 $('.app-desktop-search__popup-link').removeClass(ACTIVE_ITEM_CLASS); 44 } 45 46 function setActiveItemByIndex(index) { 47 var $items = $('.app-desktop-search__popup-link'); 48 clearActiveItem(); 49 50 if (!$items.length) return; 51 52 if (index < 0) index = $items.length - 1; 53 else if (index >= $items.length) index = 0; 54 55 $items.eq(index).addClass(ACTIVE_ITEM_CLASS); 56 } 57 58 function getActiveItemIndex() { 59 var activeIndex = -1; 60 $('.app-desktop-search__popup-link').each(function (i) { 61 if ($(this).hasClass(ACTIVE_ITEM_CLASS)) { 62 activeIndex = i; 63 return false; 64 } 65 }); 66 return activeIndex; 67 } 68 69 /* ------------------------------------------------------------------ */ 70 /* Ð ÐµÐ½Ð´ÐµÑ Ð¿Ð¾Ð´Ñказок (ÑекÑÑовÑе запÑоÑÑ) */ 71 /* ------------------------------------------------------------------ */ 72 73 var HISTORY_KEY = 'mf_search_history'; 74 var MAX_HISTORY = 3; 75 var MAX_SUGGESTIONS = 3; 76 var lastCorrection = ''; 77 78 function getHistory() { 79 try { 80 return JSON.parse(localStorage.getItem(HISTORY_KEY) || '[]'); 81 } catch (e) { 82 return []; 83 } 84 } 85 86 function saveToHistory(query) { 87 if (!query) return; 88 var history = getHistory().filter(function (q) { return q !== query; }); 89 history.unshift(query); 90 if (history.length > MAX_HISTORY) history = history.slice(0, MAX_HISTORY); 91 localStorage.setItem(HISTORY_KEY, JSON.stringify(history)); 92 } 93 94 function clearHistory() { 95 localStorage.removeItem(HISTORY_KEY); 96 } 97 98 function buildQueryIcon(type) { 99 if (type === 'history') { 100 return '<svg class="app-desktop-search__popup-link-icon" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8 1.5A6.5 6.5 0 1 0 14.5 8 6.508 6.508 0 0 0 8 1.5ZM8 13A5 5 0 1 1 13 8 5.006 5.006 0 0 1 8 13Zm.75-8.25h-1.5v3.44l2.28 2.28 1.06-1.06-1.84-1.84Z" fill="currentColor"/></svg>'; 101 } 102 if (type === 'category') { 103 return '<svg class="app-desktop-search__popup-link-icon" viewB
103ox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="6" height="6" rx="1" stroke="currentColor" stroke-width="1.2"/><rect x="9" y="1" width="6" height="6" rx="1" stroke="currentColor" stroke-width="1.2"/><rect x="1" y="9" width="6" height="6" rx="1" stroke="currentColor" stroke-width="1.2"/><rect x="9" y="9" width="6" height="6" rx="1" stroke="currentColor" stroke-width="1.2"/></svg>'; 104 } 105 return '<svg class="app-desktop-search__popup-link-icon" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M6.8 1.4a5.4 5.4 0 1 0 0 10.8A5.4 5.4 0 0 0 6.8 1.4ZM0 6.8a6.8 6.8 0 1 1 13.6 0A6.8 6.8 0 0 1 0 6.8Z" fill="currentColor"/><path fill-rule="evenodd" clip-rule="evenodd" d="M10.415 10.415a.7.7 0 0 1 .99 0l2.88 2.88a.7.7 0 1 1-.99.99l-2.88-2.88a.7.7 0 0 1 0-.99Z" fill="currentColor"/></svg>'; 106 } 107 108 function buildLinkHtml(text, type, href) { 109 var url = href || ('/search/?q=' + encodeURIComponent(text)); 110 return '<a class="app-desktop-search__popup-link" href="' + url + '">' 111 + buildQueryIcon(type) 112 + '<span>' + escapeHtml(text) + '</span>' 113 + '</a>'; 114 } 115
116 function renderSuggestions(suggestions) { 117 var $historyBlock = $('.js-search-history-block'); 118 var $popularBlock = $('.js-search-popular-block'); 119 var $historyList = $('.js-search-history-list'); 120 var $popularList = $('.js-search-popular-list'); 121 122 var history = getHistory(); 123 124 /* ÐÑÑоÑÐ¸Ñ */ 125 if (history.length) { 126 $historyList.html(history.map(function (q) { return buildLinkHtml(q, 'history'); }).join('')); 127 $historyBlock.show(); 128 } else { 129 $historyList.html(''); 130 $historyBlock.hide(); 131 } 132 133 /* ÐодÑказки Ð¾Ñ ÑеÑвеÑа */ 134 if (suggestions.length) { 135 $popularList.html(suggestions.slice(0, MAX_SUGGESTIONS).map(function (q) { return buildLinkHtml(q, 'search'); }).join('')); 136 $popularBlock.show(); 137 } else { 138 $popularList.html(''); 139 $popularBlock.hide(); 140 } 141 142 /* ÐидимоÑÑÑ Ð¿Ð¾Ð¿Ð°Ð¿Ð° ÑпÑавлÑеÑÑÑ ÑенÑÑализованно в updateAutocompleteVisibility() */ 143 } 144 145 /* ------------------------------------------------------------------ */ 146 /* Ð ÐµÐ½Ð´ÐµÑ ÐºÐ°ÑегоÑий */ 147 /* ------------------------------------------------------------------ */ 148 149 function renderCategories(categories) { 150 var $block = $('.js-search-categories-block'); 151 var $list = $('.js-search-categories-list'); 152 153 if (!categories || !categories.length) { 154 $list.html(''); 155 $block.hide(); 156 return; 157 } 158 159 $list.html( 160 categories.slice(0, MAX_SUGGESTIONS).map(function (cat) { 161 return buildLinkHtml(cat.name || cat, 'category', cat.url || null); 162 }).join('') 163 ); 164 $block.show(); 165 } 166 167 /* ------------------------------------------------------------------ */ 168 /* Ð ÐµÐ½Ð´ÐµÑ Ñабов-ÑÑоÑнений */ 169 /* ------------------------------------------------------------------ */ 170 171 function renderTaps(taps) { 172 var $tapsContainer = $('.app-desktop-search__taps'); 173 if (!taps || !taps.length) { 174 $tapsContainer.html(''); 175 $tapsContainer.hide(); 176 return; 177 } 178 $tapsContainer.html( 179 taps.map(function (tap) { 180 return '<button type="button" class="app-desktop-search__tap">' 181 + escapeHtml(tap) 182 + '</button>'; 183 }).join('') 184 ); 185 $tapsContainer.show(); 186 } 187 188 /* Ðлик по ÑапÑ-ÑÑоÑнениÑ: пÑи correction заменÑем поÑледнее Ñлово, инаÑе допиÑÑваем */ 189 $(document).on('click', '.app-desktop-search__tap', function () { 190 var $input = $('#header-search-input'); 191 if (!$input.length) { 192 return; 193 } 194 195 var current = $input.val() || ''; 196 var tapText = $(this).text() || ''; 197 tapText = tapText.trim(); 198 if (!tapText) { 199 return; 200 } 201 202 var newValue = ''; 203 if (lastCorrection !== '') { 204 var currentTrimmedRight = String(current).replace(/\s+$/, ''); 205 if (currentTrimmedRight === '') { 206 newValue = tapText; 207 } else if (/\S/.test(currentTrimmedRight)) { 208 newValue = currentTrimmedRight.replace(/\S+$/, tapText); 209 } else { 210 newValue = tapText; 211 } 212 } else { 213 var needsSpace = current.length > 0 && !/\s$/.test(current); 214 newValue = current + (needsSpace ? ' ' : '') + tapText; 215 } 216 217 $input.val(newValue).trigger('input'); 218 $input.focus(); 219 }); 220 221 /* ------------------------------------------------------------------ */ 222 /* Ð ÐµÐ½Ð´ÐµÑ ÐºÐ°ÑÑоÑек ÑоваÑов */ 223 /* ------------------------------------------------------------------ */ 224 225 function buildProductCard(item) { 226 function normalizePriceSpacing(value) { 227 return String(value) 228 .replace(/ /g, '\u00A0') 229 .replace(/ /g, '\u00A0'); 230 } 231 232 function offerIsOnlyInStore(offer) { 233 return offer.only_in_store === true || offer.only_in_store === 1 234 || offer.ONLY_IN_STORE === '1' || offer.ONLY_IN_STORE === 1; 235 } 236 237 /* ÐлаÑка Ñкидки */ 238 var badge = item.discount 239 ? '<span class="app-desktop-search__product-badge">' + escapeHtml(item.discount) + '</span>' 240 : ''; 241 242 /* ÐеÑки (Ñ Ð¸Ñ Ð¿Ñодаж, новинка и Ñ.п.) */ 243 var labels = (item.labels && item.labels.length) 244 ? '<div class="app-desktop-search__product-labels">' 245 + item.labels.map(function (l) { return '<span class="app-desktop-search__product-label">' + escapeHtml(l) + '</span>'; }).join('') 246 + '</div>' 247 : ''; 248 249 /* РейÑинг-звÑÐ·Ð´Ñ */ 250 var stars = (item.rating !== null && item.rating !== undefined) 251 ? '<div class="app-desktop-search__product-stars">' + buildStars(item.rating) + '</div>' 252 : ''; 253 254 /* СÑÑока меÑа (меÑки + звÑздÑ). 255 * ÐбÑÑÑка вÑводиÑÑÑ Ð²Ñегда, ÑÑÐ¾Ð±Ñ Ð²ÑÑоÑа каÑÑоÑек бÑла одинаковой 256 * даже пÑи оÑÑÑÑÑÑвии ÑейÑинга и меÑок. 257 */ 258 var meta = '<div class="app-desktop-search__product-meta">' + labels + stars + '</div>'; 259 260 /* ТекÑÑÐ°Ñ Ñена */ 261 var hasFormattedPrice = item.price_formatted !== null && item.price_formatted !== undefined && String(item.price_formatted).trim() !== ''; 262 var currencyOld = item.currency ? ' ' + escapeHtml(item.currency) : ''; 263 var currency = hasFormattedPrice ? '' : currencyOld; 264 var priceDisplay = hasFormattedPrice ? normalizePriceSpacing(item.price_formatted) : item.price; 265 var price = (priceDisplay !== null && priceDisplay !== undefined) 266 ? '<span class="app-desktop-search__product-price">' + escapeHtml(String(priceDisplay)) + currency + '</span>' 267 : ''; 268 269 /* СÑаÑÐ°Ñ Ñена */ 270 var showOldPrice = item.price_old && item.price_old > item.price; 271 var priceOldDisplay = (item.price_old_formatted !== null && item.price_old_formatted !== undefined && String(item.price_old_formatted).trim() !== '') 272 ? normalizePriceSpacing(item.price_old_formatted) 273 : item.price_old; 274 var currencyOldForOld = (item.price_old_formatted !== null && item.price_old_formatted !== undefined && String(item.price_old_formatted).trim() !== '') 275 ? '' 276 : currencyOld; 277 var priceOld = showOldPrice 278 ? '<span class="app-desktop-search__product-price-old">' + escapeHtml(String(priceOldDisplay)) + currencyOldForOld + '</span>' 279 : ''; 280 281 /* Ðлок Ñен */ 282 var prices = (price || priceOld) 283 ? '<div class="app-desktop-search__product-prices">' + price + priceOld + '</div>' 284 : ''; 285 286 /* СÑÑÑÑик ÑвеÑов */ 287 var colorsCount = item.colors ? parseInt(item.colors, 10) : 0; 288 var colorsText = colorsCount > 0 ? colorsCount + ' ' + declOfNum(colorsCount, ['ÑвеÑ', 'ÑвеÑа', 'ÑвеÑов']) : ''; 289 var colorsHtml = colorsText 290 ? '<span class="app-desktop-search__product-colors">' + escapeHtml(colorsText) + '</span>' 291 : ''; 292 293 /* Ðнопка избÑанного â иÑполÑзÑÐµÑ Ð³Ð»Ð¾Ð±Ð°Ð
293»ÑнÑй обÑабоÑÑик add-in-favorite-button */ 294 var favActiveClass = item.in_fav ? ' active' : ''; 295 var favBtn = item.favorite_offer_id 296 ? '<button type="button" class="add-in-favorite-button app-desktop-search__fav-btn' + favActiveClass + '" data-item="' + item.favorite_offer_id + '" data-remove-block="Y" aria-label="РизбÑанное">' 297 + '<svg class="white_heart" width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15.6301 3.4575C15.247 3.07425 14.7922 2.77023 14.2916 2.56281C13.791 2.35539 13.2545 2.24863 12.7126 2.24863C12.1707 2.24863 11.6342 2.35539 11.1336 2.56281C10.633 2.77023 10.1782 3.07425 9.79509 3.4575L9.00009 4.2525L8.20509 3.4575C7.43132 2.68373 6.38186 2.24903 5.28759 2.24903C4.19331 2.24903 3.14386 2.68373 2.37009 3.4575C1.59632 4.23127 1.16162 5.28072 1.16162 6.375C1.16162 7.46927 1.59632 8.51873 2.37009 9.2925L3.16509 10.0875L9.00009 15.9225L14.8351 10.0875L15.6301 9.2925C16.0133 8.90943 16.3174 8.45461 16.5248 7.95401C16.7322 7.45342 16.839 6.91686 16.839 6.375C16.839 5.83313 16.7322 5.29657 16.5248 4.79598C16.3174 4.29539 16.0133 3.84056 15.6301 3.4575Z" stroke="#535353" stroke-linecap="round" stroke-linejoin="round"/></svg>' 298 + '<svg class="dark_heart" width="18" height="17" viewBox="0 0 18 17" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15.6301 3.4575C15.247 3.07425 14.7922 2.77023 14.2916 2.56281C13.791 2.35539 13.2545 2.24863 12.7126 2.24863C12.1707 2.24863 11.6342 2.35539 11.1336 2.56281C10.633 2.77023 10.1782 3.07425 9.79509 3.4575L9.00009 4.2525L8.20509 3.4575C7.43132 2.68373 6.38186 2.24903 5.28759 2.24903C4.19331 2.24903 3.14386 2.68373 2.37009 3.4575C1.59632 4.23127 1.16162 5.28072 1.16162 6.375C1.16162 7.46927 1.59632 8.51873 2.37009 9.2925L3.16509 10.0875L9.00009 15.9225L14.8351 10.0875L15.6301 9.2925C16.0133 8.90943 16.3174 8.45461 16.5248 7.95401C16.7322 7.45342 16.839 6.91686 16.839 6.375C16.839 5.83313 16.7322 5.29657 16.5248 4.79598C16.3174 4.29539 16.0133 3.84056 15.6301 3.4575Z" fill="#535353" stroke="#535353" stroke-linecap="round" stroke-linejoin="round"/></svg>' 299 + '</button>' 300 : ''; 301 302 /* ÐижнÑÑ ÑÑÑока: ÑвеÑа + кнопка избÑанного */ 303 var footer = (colorsHtml || favBtn) 304 ? '<div class="app-desktop-search__product-footer">' 305 + colorsHtml 306 + favBtn 307 + '</div>' 308 : ''; 309 310 /* ÐеÑелиÑÑÑвание ÑоÑо â пÑозÑаÑнÑе Ð·Ð¾Ð½Ñ Ð¿Ð¾Ð²ÐµÑÑ ÐºÐ°ÑÑинки */ 311 var photosRow = ''; 312 var photos = item.photos && item.photos.length ? item.photos : []; 313 if (photos.length > 1) { 314 photosRow = '<div class="app-desktop-search__photos-row">' 315 + photos.map(function (url) { 316 return '<div class="app-desktop-search__photos-zone" data-photo="' + escapeHtml(url) + '"></div>'; 317 }).join('') 318 + '</div>'; 319 } 320 321 /* РазмеÑÐ½Ð°Ñ ÑеÑка â поÑвлÑеÑÑÑ Ð¿Ñи наведении повеÑÑ Ð½Ð¸Ð¶Ð½ÐµÐ¹ ÑаÑÑи ÑоÑо */ 322 var sizesBlock = ''; 323 var offers = item.offers && item.offers.length ? item.offers : []; 324 var allSizesOnlyInStore = offers.length > 0 && offers.every(offerIsOnlyInStore); 325 var storeOnlyBadge = allSizesOnlyInStore 326 ? '<div class="app-desktop-search__product-store-only"><span class="app-desktop-search__product-store-only__text">ТолÑко в Ð¼Ð°Ð³Ð°Ð·Ð¸Ð½Ð°Ñ </span></div>' 327 : ''; 328 329 if (offers.length) { 330 var sizeItems = offers.map(function (offer) { 331 var onlyInStore = offerIsOnlyInStore(offer); 332 var onlyInStoreClass = onlyInStore ? ' only_in_store' : ''; 333 return '<div class="app-desktop-search__size-item' + onlyInStoreClass + '"' 334 + ' data-id="' + (offer.id || '') + '"' 335 + ' onclick="addToBasketAll(' + (offer.id || '') + ', null, \'ÐоиÑк\')">' 336 + '<div class="size-item__size">' + escapeHtml(offer.size || '') + '</div>' 337 + '</div>'; 338 }).join(''); 339 340 var hasMore = offers.length > 4; 341 sizesBlock = '<div class="app-desktop-search__product-sizes main-product-hover-block">' 342 + '<div class="add-to-basket">
342ÐобавиÑÑ Ð² коÑзинÑ</div>' 343 + '<div class="sizes-block">' 344 + '<div class="sizes-line" data-count="4">' + sizeItems + '</div>' 345 + '<div class="left-arrow disabled">' 346 + '<svg class="left-arrow_disabled" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12.5 5.5L7.75 10.25L12.5 15" stroke="#DEDEDE" stroke-linecap="round" stroke-linejoin="round"/></svg>' 347 + '<svg class="left-arrow_active" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12.5 5.5L7.75 10.25L12.5 15" stroke="#212121" stroke-linecap="round" stroke-linejoin="round"/></svg>' 348 + '</div>' 349 + '<div class="right-arrow ' + (hasMore ? 'active' : 'disabled') + '">' 350 + '<svg class="right-arrow_disabled" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.5 14.5L12.25 9.75L7.5 5" stroke="#DEDEDE" stroke-linecap="round" stroke-linejoin="round"/></svg>' 351 + '<svg class="right-arrow_active" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.5 14.5L12.25 9.75L7.5 5" stroke="#535353" stroke-linecap="round" stroke-linejoin="round"/></svg>' 352 + '</div>' 353 + '</div>' 354 + '</div>'; 355 } 356 357 return '<a class="app-desktop-search__product-card" href="' + escapeHtml(item.url || '#') + '">' 358 + '<div class="app-desktop-search__product-img-wrap">' 359 + '<img class="app-desktop-search__product-img" src="' + escapeHtml(item.image || '') + '" alt="' + escapeHtml(item.name || '') + '" loading="lazy">' 360 + badge 361 + storeOnlyBadge 362 + photosRow 363 + sizesBlock 364 + '</div>' 365 + '<div class="app-desktop-search__product-info">' 366 + meta 367 + '<span class="app-desktop-search__product-name">' + escapeHtml(item.name || '') + '</span>' 368 + prices 369 + footer 370 + '</div>' 371 + '</a>'; 372 } 373 374 function buildStars(rating) { 375 var count = Math.round(parseFloat(rating) || 5); 376 var html = ''; 377 for (var i = 0; i < 5; i++) { 378 html += '<svg class="app-desktop-search__product-star" viewBox="0 0 15 15" fill="' + (i < count ? '#525252' : 'none') + '" xmlns="http://www.w3.org/2000/svg">' 379 + '<path d="M7.5 1l1.545 4.756H14l-4.045 2.938 1.545 4.756L7.5 10.512l-3.999 2.938 1.545-4.756L1 5.756h4.955L7.5 1Z" stroke="#525252" stroke-width="1"/>' 380 + '</svg>'; 381 } 382 return html; 383 } 384 385 /* ------------------------------------------------------------------ */ 386 /* Ð¡Ð»Ð°Ð¹Ð´ÐµÑ ÑазмеÑов в каÑÑоÑÐºÐ°Ñ Ð°Ð²ÑÐ¾Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ */ 387 /* ------------------------------------------------------------------ */ 388 389 function getSizesItemsPerLine($sizesLine) { 390 // СколÑко ÑлеменÑов ÑеалÑно помеÑÑиÑÑÑ Ð² ÑиÑÐ¸Ð½Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ ÑÑда. 391 // ÐÑиоÑиÑеÑ: 4 в ÑÑд. ÐÑли не Ð²Ð»ÐµÐ·Ð°ÐµÑ â ÑменÑÑаем ÑиÑÐ¸Ð½Ñ items на JS. 392 // Ðалее по ÑбÑваниÑ: 3 -> 2 -> 1. 393 if (!$sizesLine || !$sizesLine.length) return 4; 394 395 var items = $sizesLine.find('.app-desktop-search__size-item').toArray(); 396 if (!items.length) return 4; 397 398 var lineEl = $sizesLine[0]; 399 var containerWidth = lineEl.clientWidth || 0; 400 401 // Ðажно: `sizes-line` внÑÑÑи hover-блока (`display: none`) на ÑÑапе init 402 // Ð¼Ð¾Ð¶ÐµÑ Ð¸Ð¼ÐµÑÑ clientWidth = 0. Тогда беÑÑм ÑиÑÐ¸Ð½Ñ Ð²Ð¸Ð´Ð¸Ð¼Ð¾Ð³Ð¾ конÑейнеÑа каÑÑоÑки. 403 if (!containerWidth) { 404 var $imgWrap = $sizesLine.closest('.app-desktop-search__product-img-wrap'); 405 if ($imgWrap && $imgWrap.length) { 406 containerWidth = $imgWrap[0].clientWidth || 0; 407 } 408 } 409 410 if (!containerWidth) return 4; 411 412 var itemEl = items[0]; 413 var styles = window.getComputedStyle(itemEl); 414 var marginLeft = parseFloat(styles.marginLeft) || 0; 415 var marginRight = parseFloat(styles.marginRight) || 0; 416 var marginTotal = marginLeft + marginRight; 417 418 // ÐоÑÑÑÐ¿Ð½Ð°Ñ ÑиÑина под ÑлеменÑÑ ÑазмеÑов: 419 // ÑиÑина sizes-line минÑÑ ÑикÑиÑованнÑй ÑезеÑв под ÑÑÑелки. 420 // Ðо ÑÑебованиÑ: sizes-line - 60px. 421 var availableWidth = Math.max(0, containerWidth - 60); 422 if (!availableWidth) return 1; 423 424 function applyWidth(widthPx) { 425 // ÐенÑем ÑолÑко локалÑнÑе инлайн-ÑÑили Ñ ÑлеменÑов в ÑÑом hover-блоке. 426 // CSS-моделÑ: width/min-width + flex-basis. 427 for (var i = 0; i < items.length; i++) { 428 items[i].style.width = widthPx + 'px'; 429 items[i].style.minWidth = widthPx + 'px'; 430 items[i].style.flex = '0 0 ' + widthPx + 'px'; 431 } 432 } 433 434 // ÐÑли длина знаÑÐµÐ½Ð¸Ñ ÑазмеÑа > 6 Ñимволов â оно "ÑоÑно не Ð²Ð»ÐµÐ·ÐµÑ Ð² 2 ÑÑÑоки". 435 // ÐнаÑиÑ, заÑанее ÑменÑÑаем кол-во ÑазмеÑов в ÑÑд (даÑм ÑÑейкам болÑÑе ÑиÑинÑ). 436 var maxSizeLen = 0; 437 for (var i = 0; i < items.length; i++) { 438 var sizeTextEl = items[i].querySelector('.size-item__size'); 439 var text = sizeTextEl ? (sizeTextEl.textContent || '') : (items[i].textContent || ''); 440 text = String(text).trim(); 441 if (text.length > maxSizeLen) maxSizeLen = text.length; 442 } 443 444 var forceSmallerPerLine = maxSizeLen > 6; 445 446 // ÐинималÑÐ½Ð°Ñ ÑиÑина одной ÑÑейки (заÑиÑа Ð¾Ñ ÑлиÑком Ñзкого ÑекÑÑа). 447 // ÐÐ»Ñ Ð´Ð»Ð¸Ð½Ð½ÑÑ Ð·Ð½Ð°Ñений делаем ÐµÑ Ð²ÑÑе. 448 var MIN_ITEM_WIDTH = forceSmallerPerLine ? 40 : 18; 449 450 // ÐодбиÑаем perLine и ÑиÑинÑ: 451 // widthPerItem = availableWidth / perLine - (marginLeft + marginRight)
452 var candidates = forceSmallerPerLine ? [2, 1] : [4, 3, 2, 1]; 453 for (var c = 0; c < candidates.length; c++) { 454 var perLine = candidates[c]; 455 var widthPerItem = Math.floor(availableWidth / perLine - marginTotal); 456 if (widthPerItem >= MIN_ITEM_WIDTH) { 457 applyWidth(widthPerItem); 458 return perLine; 459 } 460 } 461 462 // ÐÑли даже пÑи Ñамом маленÑком пеÑLine не Ñ Ð²Ð°ÑаеÑ, оÑÑавим ÑекÑÑее (fallback 1). 463 return 1; 464 } 465 466 function initSizesSlider(container) { 467 var lines = container ? container.querySelectorAll('.main-product-hover-block .sizes-line') : []; 468 Array.prototype.forEach.call(lines, function (line) { 469 var $line = $(line); 470 var items = Array.prototype.slice.call(line.querySelectorAll('.app-desktop-search__size-item')); 471 var perLine = getSizesItemsPerLine($line); 472 if (items.length <= perLine) return; 473 for (var i = perLine; i < items.length; i++) { 474 items[i].style.display = 'none'; 475 } 476 }); 477 } 478 479 /** 480 * ÐÑи hover на каÑÑоÑке Ð¿Ð¾Ð´Ð½Ð¸Ð¼Ð°ÐµÑ Ð¿Ð»Ð°ÑÐºÑ Â«Ð¢Ð¾Ð»Ñко в Ð¼Ð°Ð³Ð°Ð·Ð¸Ð½Ð°Ñ Â»: 481 * bottom = вÑÑоÑа нижнего овеÑÐ»ÐµÑ (.main-product-hover-block: «ÐобавиÑÑ Ð² коÑзинÑ» + ÑеÑка ÑазмеÑов) + 10px. 482 */ 483 function applyStoreOnlyBadgeBottomForCardHover($card) { 484 var $badge = $card.find('.app-desktop-search__product-store-only'); 485 if (!$badge.length) { 486 return; 487 } 488 var $hover = $card.find('.main-product-hover-block'); 489 if (!$hover.length) { 490 return; 491 } 492 var h = $hover.outerHeight(true) || $hover.outerHeight(); 493 if (!h && $hover[0]) { 494 h = $hover[0].getBoundingClientRect().height; 495 } 496 $badge.css('bottom', Math.round(h) + 10 + 'px'); 497 } 498 499 function resetStoreOnlyBadgeBottomForCard($card) { 500 $card.find('.app-desktop-search__product-store-only').css('bottom', ''); 501 } 502 503 $(document).on('mouseenter', '.js-search-products-grid .app-desktop-search__product-card', function () { 504 var $card = $(this); 505 if (!$card.find('.app-desktop-search__product-store-only').length) { 506 return; 507 } 508 var el = this; 509 window.requestAnimationFrame(function () { 510 window.requestAnimationFrame(function () { 511 applyStoreOnlyBadgeBottomForCardHover($(el)); 512 }); 513 }); 514 }); 515 516 $(document).on('mouseleave', '.js-search-products-grid .app-desktop-search__product-card', function () { 517 resetStoreOnlyBadgeBottomForCard($(this)); 518 }); 519 520 /* Ðлик по Ð±Ð»Ð¾ÐºÑ ÑазмеÑов и кнопке избÑанного не должен пеÑÐµÑ Ð¾Ð´Ð¸ÑÑ Ð¿Ð¾ ÑÑÑлке каÑÑоÑки */ 521 $(document).on('click', '.js-search-products-grid .main-product-hover-block', function (e) { 522 e.preventDefault(); 523 e.stopPropagation(); 524 }); 525 526 $(document).on('click', '.js-search-products-grid .app-desktop-search__fav-btn', function (e) { 527 e.preventDefault(); 528 e.stopPropagation(); 529 }); 530 531 /* СÑÑелка впÑаво â Ñдвигаем окно видимÑÑ ÑазмеÑов */ 532 $(document).on('click', '.js-search-products-grid .right-arrow.active', function (e) { 533 e.preventDefault(); 534 e.stopPropagation(); 535 var $sizesLine = $(this).siblings('.sizes-line'); 536 var items = $sizesLine.find('.app-desktop-search__size-item').toArray(); 537 var perLine = getSizesItemsPerLine($sizesLine); 538 var firstVisible = -1; 539 for (var i = 0; i < items.length; i++) { 540 if ($(items[i]).css('display') !== 'none') { firstVisible = i; break; } 541 } 542 if (firstVisible < 0 || firstVisible + perLine >= items.length) return; 543 $(items[firstVisible]).hide(); 544 $(items[firstVisible + perLine]).show(); 545 546 var newFirst = firstVisible + 1; 547 $(this).siblings('.left-arrow').toggleClass('disabled', newFirst === 0).toggleClass('active', newFirst > 0); 548 var lastVisible = newFirst + perLine - 1; 549 $(this).toggleClass('active', lastVisible < items.length - 1).toggleClass('disabled', lastVisible >= items.length - 1); 550 }); 551 552 /* СÑÑелка влево â Ñдвигаем окно видимÑÑ ÑазмеÑов */ 553 $(document).on('click', '.js-search-products-grid .left-arrow.active', function (e) { 554 e.preventDefault(); 555 e.stopPropagation(); 556 var $sizesLine = $(this).siblings('.sizes-line'); 557 var items = $sizesLine.find('.app-desktop-search__size-item').toArray(); 558 var perLine = getSizesItemsPerLine($sizesLine); 559 var firstVisible = -1; 560 for (var i = 0; i < items.length; i++) { 561 if ($(items[i]).css('display') !== 'none') { firstVisible = i; break; } 562 } 563 if (firstVisible <= 0) return; 564 $(items[firstVisible - 1]).show(); 565 $(items[firstVisible + perLine - 1]).hide(); 566 567 var newFirst = firstVisible - 1; 568 $(this).toggleClass('disabled', newFirst === 0).toggleClass('active', newFirst > 0); 569 var lastVisible = newFirst + perLine - 1; 570 $(this).siblings('.right-arrow').toggleClass('active', lastVisible < items.length - 1).toggleClass('disabled', lastVisible >= items.length - 1); 571 }); 572 573 /* Смена ÑоÑо пÑи наведении на Ð·Ð¾Ð½Ñ photos-row */ 574 $(document).on('mouseenter', '.app-desktop-search__photos-zone', function () { 575 var url = $(this).data('photo'); 576 if (url) { 577 $(this).closest('.app-desktop-search__product-img-wrap') 578 .find('.app-desktop-search__product-img') 579 .attr('src', url); 580 } 581 }); 582 583 var PRODUCTS_VISIBLE = 4; 584
585 function renderProducts(products, query) { 586 var $productsBlock = $('.js-search-products'); 587 var $grid = $('.js-search-products-grid'); 588 var $footer = $('.js-search-products-footer'); 589 var $viewAll = $('.js-search-view-all'); 590 591 if (!products || !products.length) { 592 $grid.html(''); 593 $footer.hide(); 594 $productsBlock.hide(); 595 return; 596 } 597 598 /* ÐоказÑваем не более 4 каÑÑоÑек */ 599 $grid.html(products.slice(0, PRODUCTS_VISIBLE).map(buildProductCard).join('')); 600 $productsBlock.show(); 601 602 /* ÐниÑиализиÑÑем ÑÐ»Ð°Ð¹Ð´ÐµÑ ÑазмеÑов в ÑолÑко ÑÑо оÑÑендеÑеннÑÑ ÐºÐ°ÑÑоÑÐºÐ°Ñ */ 603 initSizesSlider($grid[0]); 604 605 /* Ðнопка «СмоÑÑеÑÑ Ð²Ñе ÑезÑлÑÑаÑÑ» â ÑолÑко еÑли ÑоваÑов болÑÑе 4 */ 606 if (products.length > PRODUCTS_VISIBLE) { 607 var searchUrl = '/search/?q=' + encodeURIComponent(query || ''); 608 $viewAll.attr('href', searchUrl); 609 $footer.show(); 610 } else { 611 $footer.hide(); 612 } 613 } 614 615 function updateAutocompleteVisibility() { 616 var $acBody = $('.js-search-ac-body'); 617 var hasTaps = $('.app-desktop-search__taps .app-desktop-search__tap').length > 0; 618 var hasHistory = $('.js-search-history-list .app-desktop-search__popup-link').length > 0; 619 var hasPopular = $('.js-search-popular-list .app-desktop-search__popup-link').length > 0; 620 var hasCategories = $('.js-search-categories-list .app-desktop-search__popup-link').length > 0; 621 var hasProducts = $('.js-search-products-grid .app-desktop-search__product-card').length > 0; 622 623 var hasAnyContent = hasTaps || hasHistory || hasPopular || hasCategories || hasProducts; 624 if (hasAnyContent) { 625 $acBody.addClass('is-open'); 626 } else { 627 $acBody.removeClass('is-open'); 628 } 629 } 630 631 /* ------------------------------------------------------------------ */ 632 /* AJAX: запÑÐ¾Ñ Ð¿Ð¾Ð´Ñказок */ 633 /* ------------------------------------------------------------------ */ 634 635 function getSuggestions() { 636 var query = $('#header-search-input').val().trim(); 637 $('.app-desktop-search-btn').removeClass('for-close'); 638 639 function requestAutocompleteRich(requestQuery) { 640 return BX.ajax.runComponentAction( 641 'markformelle:mf.search.autocomplete', 642 'getAutocompleteRich', 643 { 644 mode: 'class', 645 data: { q: requestQuery }, 646 } 647 ); 648 } 649 650 function renderAutocompleteData(data) { 651 lastCorrection = (data.correction || '').trim(); 652 renderTaps(data.taps || []); 653 renderSuggestions(data.phrases || []); 654 renderCategories(data.categories || []); 655 renderProducts(data.products || [], query); 656 updateAutocompleteVisibility(); 657 clearActiveItem(); 658 } 659 660 /* ÐÑегда идÑм на ÑеÑÐ²ÐµÑ â пÑи пÑÑÑом запÑоÑе Anyquery веÑнÑÑ Ð´ÐµÑолÑнÑе даннÑе */ 661 requestAutocompleteRich(query).then(function (response) { 662 var data = response.data || {}; 663 664 // ÐÐ»Ñ Ð½ÐµÐ¿ÑÑÑого запÑоÑа пÑи пÑÑÑÑÑ ÑоваÑÐ°Ñ Ð¿Ð¾Ð²ÑоÑÑем запÑÐ¾Ñ Ð±ÐµÐ· ÑекÑÑа. 665 if (query !== '' && (!data.products || !data.products.length)) { 666 requestAutocompleteRich('').then(function (fallbackResponse) { 667 renderAutocompleteData(fallbackResponse.data || {}); 668 }, function () { 669 renderAutocompleteData(data); 670 }); 671 return; 672 } 673 674 renderAutocompleteData(data); 675 }, function () { 676 lastCorrection = ''; 677 renderTaps([]); 678 renderSuggestions([]); 679 renderCategories([]); 680 renderProducts([], query); 681 updateAutocompleteVisibility(); 682 }); 683 } 684 685 /* ------------------------------------------------------------------ */ 686 /* ÐÑпомогаÑелÑнÑе */ 687 /* ------------------------------------------------------------------ */ 688 689 function declOfNum(n, titles) { 690 var cases = [2, 0, 1, 1, 1, 2]; 691 return titles[(n % 100 > 4 && n % 100 < 20) ? 2 : cases[Math.min(n % 10, 5)]]; 692 } 693 694 function escapeHtml(str) { 695 return String(str) 696 .replace(/&/g, '&') 697 .replace(/</g, '<') 698 .replace(/>/g, '>') 699 .replace(/"/g, '"'); 700 } 701 702 function debounce(func, wait) { 703 var timeout; 704 return function () { 705 var ctx = this; 706 var args = arguments; 707 clearTimeout(timeout); 708 timeout = setTimeout(function () { func.apply(ctx, args); }, wait); 709 }; 710 } 711 712 var waitForDigi = (function () { 713 var promise = null; 714 715 return function () { 716 if (typeof window === 'undefined') { 717 return Promise.resolve(false); 718 } 719 720 if (promise) return promise; 721 722 promise = new Promise(function (resolve) { 723 function checkDigi() { 724 if (window.Digi && window.Digi.api) { 725 resolve(true); 726 return; 727 } 728 setTimeout(checkDigi, 100); 729 } 730 731 checkDigi(); 732 }); 733 734 return promise; 735 }; 736 })(); 737 738 function trackAutocompleteQueryClick(itemText) { 739 if (!itemText || typeof window === 'undefined') return; 740 741 var searchTerm = ($('#header-search-input').val() || '').trim(); 742 var correction = (lastCorrection || '').trim(); 743 744 waitForDigi().then(function (isReady) { 745 if (!isReady) return; 746 if (!window.Digi || !window.Digi.api || typeof window.Digi.api.sendAutocompleteQueryClickEvent !== 'function') return; 747 748 // ФоÑÐ¼Ð°Ñ Ð¿Ð°ÑамеÑÑов ÑÑÑого по Digi.API: 749 // { searchTerm, correction, item } 750 window.Digi.api.sendAutocompleteQueryClickEvent({ 751 searchTerm: searchTerm, 752 correction: correction, 753 item: itemText 754 }); 755 }); 756 } 757 758 function updateClearBtn() { 759 var $input = $('#header-search-input'); 760 $input.closest('.app-desktop-search__input-wrap') 761 .toggleClass('has-value', $input.val().length > 0); 762 } 763 764 /* ------------------------------------------------------------------ */ 765 /* ÐбÑабоÑÑики ÑобÑÑий */ 766 /* ------------------------------------------------------------------ */ 767 768 $(document).on('input', '#header-search-input', debounce(getSuggestions, 350)); 769 $(document).on('input', '#header-search-input', updateClearBtn); 770 771 /* ФокÑÑ Ð½Ð° инпÑÑе â запÑаÑиваем деÑолÑнÑе даннÑе Ñ ÑеÑвеÑа */ 772 $(document).on('focus', '#header-search-input', function () { 773 if (!$('.js-search-ac-body').hasClass('is-open')) { 774 getSuggestions(); 775 } 776 }); 777 778 /* ÐÑиÑÑиÑÑ Ð¸Ð½Ð¿ÑÑ â показÑваем деÑолÑнÑй ÑÑÐµÐ¹Ñ */ 779 $(document).on('click', '.js-search-clear', function (e) { 780 e.preventDefault(); 781 $('#header-search-input').val(''); 782 updateClearBtn(); 783 getSuggestions(); 784 $('#header-search-input').trigger('focus'); 785 }); 786 787 /* ÐакÑÑÑÑ Ð¿Ð¾Ð¿Ð°Ð¿ */ 788 $(document).on('click', '.js-search-close, .app-desktop-search__close-btn', function (e) { 789 e.preventDefault(); 790 e.stopPropagation(); 791 closeSearchPopup(); 792 }); 793 794 /* ÐеÑкÑоп: клик по search-lupa-btn должен закÑÑваÑÑ Ð°Ð²Ñодополнение 795 * (внеÑний конÑÑÐ¾Ð»Ð»ÐµÑ Ð·Ð°ÐºÑÑÐ²Ð°ÐµÑ Ð¿Ð¾Ð¿Ð°Ð¿/овеÑлей, но closeSearchPopup Ð¼Ð¾Ð¶ÐµÑ Ð½Ðµ вÑзÑваÑÑÑÑ). 796 */ 797 $(document).on('click', '.search-lupa-btn', function () { 798 var $acBody = $('.js-search-ac-body'); 799 if ($acBody.hasClass('is-open')) { 800 closeSearchPopup(); 801 } 802 }); 803 804 /* ÐÑиÑÑиÑÑ Ð¸ÑÑоÑÐ¸Ñ */ 805 $(document).on('click', '.js-search-history-clear', function (e) { 806 e.preventDefault(); 807 e.stopPropagation(); 808 809 clearHistory(); 810 811 // Ðе закÑÑваем попап: обновлÑем деÑолÑнÑе подÑказки заново, 812 // ÑÑÐ¾Ð±Ñ Ð±Ð»Ð¾Ðº "ЧаÑÑо иÑÑÑ" / каÑегоÑии оÑÑалиÑÑ Ð²Ð¸Ð´Ð¸Ð¼Ñми. 813 getSuggestions(); 814 }); 815 816 /* Ð¡Ð¾Ñ Ñанение в иÑÑоÑÐ¸Ñ Ð¿Ñи клике на подÑÐºÐ°Ð·ÐºÑ */ 817 $(document).on('click', '.js-search-history-list .app-desktop-search__popup-link, .js-search-popular-list .app-desktop-search__popup-link', function () { 818 var queryText = $(this).find('span').text().trim(); 819 saveToHistory(queryText); 820 }); 821 822 /* Digi.API: клик по подÑказке в блоке "ЧаÑÑо иÑÑÑ" */ 823 $(document).on('click', '.js-search-popular-list .app-desktop-search__popup-link', function () { 824 var queryText = $(this).find('span').text().trim(); 825 trackAutocompleteQueryClick(queryText); 826 }); 827 828 /* Ð¡Ð¾Ñ Ñанение в иÑÑоÑÐ¸Ñ Ð¿Ñи ÑабмиÑе ÑоÑÐ¼Ñ */ 829 $(document).on('submit', '.app-desktop-search__form form', function () { 830 saveToHistory($('#header-search-input').val().trim()); 831 }); 832 833 /* ÐлавиаÑÑÑÐ½Ð°Ñ Ð½Ð°Ð²Ð¸Ð³Ð°ÑÐ¸Ñ */ 834 $(document).on('keydown', '#header-search-input', function (e) { 835 var $items = $('.app-desktop-search__popup-link'); 836 837 if (e.key === 'Escape') { 838 closeSearchPopup(); 839 return; 840 } 841 842 if (!$items.length) return; 843 844 if (e.key === 'ArrowDown') { 845 e.preventDefault();
846 setActiveItemByIndex(getActiveItemIndex() + 1); 847 } else if (e.key === 'ArrowUp') { 848 e.preventDefault(); 849 setActiveItemByIndex(getActiveItemIndex() - 1); 850 } else if (e.key === 'Enter') { 851 var activeIndex = getActiveItemIndex(); 852 if (activeIndex >= 0) { 853 e.preventDefault(); 854 $items.eq(activeIndex).get(0).click(); 855 } 856 } 857 }); 858 859 $(document).on('mouseenter', '.app-desktop-search__popup-link', function () { 860 clearActiveItem(); 861 $(this).addClass(ACTIVE_ITEM_CLASS); 862 }); 863 864 /* Ðлик вне блока авÑÐ¾Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ 865 * Ðажно: на ÑÑÑаниÑе поиÑка одновÑеменно Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ ÑÐµÐ½Ð´ÐµÑ Ð´Ð²ÑÑ Ñаблонов autocomplete 866 * (`.default` и `header_any`). ÐоÑÑÐ¾Ð¼Ñ Ð·Ð°ÐºÑÑваем ÑолÑко popup header_any и ÑолÑко 867 * когда он ÑеалÑно оÑкÑÑÑ, а Ñакже игноÑиÑÑем клики внÑÑÑи поиÑкового блока `.default`. 868 */ 869 $('body').on('click.mfSearchAutocompleteHeaderAny', function (e) { 870 // ÐÑли попап header_any не оÑкÑÑÑ â ниÑего не делаем, ÑÑÐ¾Ð±Ñ Ð½Ðµ влиÑÑÑ Ð½Ð° `.default`. 871 if (!$('.js-search-ac-body').hasClass('is-open')) { 872 return; 873 } 874 875 var $t = $(e.target); 876 if ( 877 !$t.closest('.js-search-ac-body').length && 878 !$t.closest('.js-search-popup').length && 879 !$t.closest('.search-lupa-btn').length 880 ) { 881 closeSearchPopup(); 882 } 883 }); 884});
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.