1// Flash 2// class Flash { 3// constructor(flash) { 4// this.flash = flash 5// 6// if (this.flash.classList.contains('active')) { 7// this.flash.classList.remove('active') 8// } 9// 10// document.querySelectorAll('a').forEach(link => link.addEventListener('click', (e) => { 11// 12// 13// this.flash.classList.add('active') 14// 15// if (e.target.getAttribute('href')) { 16// e.preventDefault() 17// let link = e.target.getAttribute('href') 18// } else if (e.target.closest('a').getAttribute('href')) { 19// e.preventDefault() 20// let link = e.target.closest('a').getAttribute('href') 21// } else { 22// 23// } 24// 25// setTimeout(() => { 26// location.href = link 27// }, 400) 28// })) 29// } 30// 31// static init() { 32// const flash = document.querySelector('.flash') 33// new Flash(flash) 34// } 35// } 36// document.body.onload = () => Flash.init() 37 38class Video { 39 constructor(video) { 40 this.video = video 41 42 this.poster = this.video.querySelector('.video-poster') 43 this.poster.addEventListener('click', this.play.bind(this)) 44 45 this.content = this.video.querySelector('.video-content') 46 } 47 48 play() { 49 this.poster.style.display = 'none' 50 51 const src = this.content.dataset.src 52 const source = Functions.htmlToElement(src) 53 54 this.content.innerHTML = '' 55 this.content.append(source) 56 57 this.content.style.display = 'flex' 58 } 59 60 static init() { 61 const videos = document.querySelectorAll('.video') 62 63 if (videos) { 64 videos.forEach(video => new Video(video)) 65 } 66 } 67} 68 69Video.init() 70 71// ÐаÑÑа в конÑакÑÐ°Ñ 72class Map { 73 74 constructor(map) { 75 this.map = map 76 77 window.addEventListener('resize', this.setSize.bind(this)) 78 79 this.setSize() 80 } 81 82 setSize() { 83 84 // const width = innerWidth - this.map.getBoundingClientRect().left 85 // this.map.style.width = width + 'px' 86 87 } 88 89 static init() { 90 const map = document.querySelector('.map-fixed') 91 92 if (map) { 93 new Map(map) 94 } 95 } 96} 97 98Map.init() 99 100// ÐонÑÑоллео модалÑнÑÑ Ð¾ÐºÐ¾Ð½ 101class Modal { 102 103 constructor(modal_type, opener = null, options = null) { 104 105 this.modal = document.querySelector('.modal-' + modal_type) 106 this.modal_type = modal_type 107 108 if (this.modal) { 109 this.opener = opener 110 this.subject = this.opener?.dataset?.subject || null 111 this.link = this.opener?.dataset?.link || null 112 this.is_open = false 113 114 this.open() 115 116 if (this.subject) { 117 if (this.modal.querySelector('[name=subject]')) this.modal.querySelector('[name=subject]').value = this.subject 118 } else { 119 if (this.modal.querySelector('[name=subject]')) this.modal.querySelector('[name=subject]').value = '' 120 } 121 122 if (this.link) { 123 if (this.modal.querySelector('[name=link]')) this.modal.querySelector('[name=link]').value = this.link 124 } else { 125 if (this.modal.querySelector('[name=link]')) this.modal.querySelector('[name=link]').value = '' 126 } 127 128 if (options) { 129 if (this.modal.querySelector('[name=options]')) this.modal.querySelector('[name=options]').value = options.join(' / ') 130 } 131 132 // ÐакÑÑÑие 133 this.closer = this.modal.querySelectorAll('.modal__close') 134 this.closer.forEach(button => { 135 button.addEventListener('click', e => { 136 e.preventDefault() 137 this.close() 138 }) 139 }) 140 141 // ÐÑпÑавка 142 if (this.modal.querySelector('.modal__form')) { 143 this.form = this.modal.querySelector('form') 144 145 if (this.form) { 146 this.form.addEventListener('submit', this.submit.bind(this)) 147 } 148 } 149 } 150 } 151 152 open() { 153 this.modal.removeAttribute('hidden') 154 this.modal.classList.add('open') 155 this.is_open = true 156 157 if (this.modal_type == 'constructor') { 158 const iframe_src = this.opener.dataset.iframe 159 const modal_content = this.modal.querySelector('.modal__content iframe') 160 161 modal_content.src = iframe_src 162 } 163 } 164 165 close() { 166 return new Promise((resolve, reject) => { 167 this.modal.classList.remove('open') 168 169 setTimeout(() => { 170 this.modal.setAttribute('hidden', true) 171 this.is_open = false 172 this.form.reset() 173 174 resolve() 175 }, 200) 176 }) 177 } 178 179 async submit(e) { 180 e.preventDefault() 181 182 // await recaptha() 183 184 const url = this.form.action 185 const formData = new FormData(this.form) 186 187 // formData.append('recaptcha_response', window.grecaptcha.getResponse()) 188 189 const submit_button = this.form.querySelector('button') 190 const temp_button_text = submit_button.innerText 191 192 submit_button.innerText = 'ÐодождиÑе...' 193 submit_button.disabled = true 194 195 formData.append('type', this.modal_type) 196 197 let response = await fetch(url, { 198 method: 'POST', 199 body: formData 200 }) 201 202 response = await response.json() 203 204 if (response.success) { 205 this.form.reset() 206 ym(86709843, 'reachGoal', 'formsend') 207 console.log('send') 208 209 if (response.redirect) { 210 let baseUrl = window.location.origin; 211 window.location.href = baseUrl + response.redirect; 212 } else {
213 this.getSuccess() 214 } 215 } else if (response.error) { 216 Alert.add(response.error, 'error') 217 } 218 219 submit_button.innerText = temp_button_text 220 submit_button.disabled = false 221 222 } 223 224 getSuccess() { 225 this.close() 226 227 new Modal('success') 228 } 229 230 static init() { 231 let openers = document.querySelectorAll('[data-modal]') 232 233 if (openers) { 234 openers.forEach(function (opener) { 235 opener.addEventListener('click', function (e) { 236 e.preventDefault() 237 238 const modal_type = opener.dataset.modal 239 240 if (modal_type) { 241 new Modal(modal_type, opener) 242 } 243 }) 244 }) 245 } 246 } 247} 248 249Modal.init() 250 251class Coop { 252 constructor(coop) { 253 this.coop = coop 254 255 this.form = this.coop.querySelector('form') 256 this.form.addEventListener('submit', this.submit.bind(this)) 257 } 258 259 async submit(e) { 260 e.preventDefault() 261 262 const url = this.form.action 263 const formData = new FormData(this.form) 264 265 let response = await fetch(url, { 266 method: 'POST', 267 body: formData 268 }) 269 270 response = await response.json() 271 272 if (response.success) { 273 this.form.reset() 274 let baseUrl = window.location.origin; 275 let path = "/index.php?route=information/thanks"; 276 window.location.href = baseUrl + path; 277 //new Modal('success', null) 278 } else if (response.error) { 279 Alert.add(response.error, 'error') 280 } 281 } 282 283 static init() { 284 const coop = document.querySelector('.for-designer__form') 285 286 if (coop) { 287 new Coop(coop) 288 } 289 } 290} 291 292Coop.init() 293 294// Ð¢Ð¾Ð²Ð°Ñ 295class Product { 296 constructor(product) { 297 this.product = product 298 299 this.name = this.product.querySelector('.product-page__title').innerText 300 301 this.submit = this.product.querySelector('.product-page__get') 302 this.submit.addEventListener('click', this.checked.bind(this)) 303 304 // this.rass = this.product.querySelector('.product-page__rass') 305 // this.rass.addEventListener('click', this.rassModal.bind(this)) 306 // 307 // this.cred = this.product.querySelector('.product-page__cred') 308 // this.cred.addEventListener('click', this.credModal.bind(this)) 309 310 this.options = this.product.querySelectorAll('.product-page__option') 311 } 312 313 checked() { 314 let valid = true 315 316 // this.options.forEach(option => { 317 // if (option.querySelector('.select') && option.querySelector('.select input').value == '') { 318 // valid = false 319 // } 320 // 321 // if ((option.querySelector('.product-page__colors-1') || option.querySelector('.product-page__colors-2')) && !option.querySelector('input:checked')) { 322 // valid = false 323 // } 324 // }) 325 326 if (valid) { 327 this.openModal() 328 } else { 329 Alert.add('ÐÑбеÑиÑе вÑе знаÑениÑ', 'error') 330 } 331 } 332 333 openModal() { 334 let options = [] 335 336 this.options.forEach(option => { 337 let title = option.querySelector('.product-page__label').innerText 338 let value = '' 339 340 if (option.querySelector('.select')) { 341 value = option.querySelector('.select input').value 342 } 343 344 if ((option.querySelector('.product-page__colors-1') || option.querySelector('.product-page__colors-2'))) { 345 value = option.querySelector('input:checked').value 346 } 347 348 options.push(`${title}: ${value}`) 349 }) 350 351 new Modal('get-price', this.submit, options) 352 } 353 354 rassModal() { 355 let options = [] 356 357 this.options.forEach(option => { 358 let title = option.querySelector('.product-page__label').innerText 359 let value = '' 360 361 if (option.querySelector('.select')) { 362 value = option.querySelector('.select input').value 363 } 364 365 if ((option.querySelector('.product-page__colors-1') || option.querySelector('.product-page__colors-2'))) { 366 value = option.querySelector('input:checked').value 367 } 368 369 options.push(`${title}: ${value}`) 370 }) 371 372 new Modal('rass', this.submit, options) 373 } 374 375 credModal() { 376 let options = [] 377 378 this.options.forEach(option => { 379 let title = option.querySelector('.product-page__label').innerText 380 let value = '' 381 382 if (option.querySelector('.select')) { 383 value = option.querySelector('.select input').value 384 } 385 386 if ((option.querySelector('.product-page__colors-1') || option.querySelector('.product-page__colors-2'))) { 387 value = option.querySelector('input:checked').value 388 } 389 390 options.push(`${title}: ${value}`) 391 }) 392 393 new Modal('cred', this.submit, options) 394 } 395 396 static init() { 397 const product = document.querySelector('.product-page') 398 399 if (product) { 400 new Product(product) 401 } 402 } 403} 404 405Product.init() 406 407// ФилÑÑÑÑ 408class Filter { 409 constructor(filter) {
410 this.filter = filter 411 412 this.filter_inputs = this.filter.querySelectorAll('input') 413 this.btnApply = this.filter.querySelector('[data-filter-apply]'); 414 this.btnApply.addEventListener('click', this.change.bind(this)); 415 // this.filter_inputs.forEach(filter => filter.addEventListener('change', this.change.bind(this))) 416 417 this.is_open = false 418 419 this.filter_toggler = this.filter.querySelector('.category__filter-toggler') 420 this.filter_toggler.addEventListener('click', this.open.bind(this)) 421 422 if (this.filter) { 423 this.filter.addEventListener('click', (e) => { 424 const target = e.target; 425 if (target.closest('[data-toggler-parent]') || target.hasAttribute('data-toggler')) { 426 const toggler = target.closest('[data-toggler-parent]'); 427 const parent = toggler.closest('[data-toggler-parent]'); 428 if (parent) { 429 parent.classList.toggle('open'); 430 } 431 } 432 }); 433 } 434 } 435 436 open() { 437 if (this.is_open) { 438 this.filter.classList.remove('open') 439 } else { 440 this.filter.classList.add('open') 441 } 442 443 this.is_open = !this.is_open 444 } 445 446 change(e) { 447 const url = new URL(location.href) 448 let search = url.search 449 search = url.search.split('&') 450 451 this.filter_inputs.forEach(input => { 452 let name = input.name 453 let values = [] 454 455 this.filter.querySelectorAll(`[name="${name}"]`).forEach(item => { 456 if (item.checked) { 457 values.push(item.value) 458 } 459 }) 460 461 values = values.join('_') 462 463 if (values) { 464 let value = input.value 465 let in_params = false 466 467 for (var i = 0; i < search.length; i++) { 468 let key = search[i].split('=')[0] 469 if (name == key) { 470 search[i] = name + '=' + values 471 in_params = true 472 } 473 } 474 475 if (!in_params) { 476 search.push(name + '=' + values) 477 } 478 479 } else { 480 for (var i = 0; i < search.length; i++) { 481 let key = search[i].split('=')[0] 482 483 if (key[0] == '?') 484 key = key.substring(1, key.length) 485 486 if (name == key) { 487 search.splice(i, 1) 488 } 489 } 490 } 491 492 }) 493 494 console.log(search) 495 console.log(search.join('&')) 496 497 location = url.origin + url.pathname + search.join('&') 498 } 499 500 static init() { 501 const filter = document.querySelector('.category__filters-list') 502 503 if (filter) { 504 new Filter(filter) 505 } 506 } 507} 508 509Filter.init() 510 511// ÐамбÑÑÐ³ÐµÑ 512class Menu { 513 constructor(menu) { 514 this.menu = menu 515 this.menu_open = document.querySelector('.header__menubtn') 516 this.menu_close = this.menu.querySelector('.menu__close') 517 518 this.menu_open.addEventListener('click', this.open.bind(this)) 519 this.menu_close.addEventListener('click', this.close.bind(this)) 520 521 this.togglers = this.menu.querySelectorAll('.menu__indicator') 522 this.togglers.forEach(toggler => toggler.addEventListener('click', this.toggle.bind(this))) 523 } 524 525 toggle(e) { 526 const parrent = e.target.closest('.menu__block') 527 parrent.classList.toggle('open') 528 } 529 530 open() { 531 this.menu.classList.add('open') 532 } 533 534 close() { 535 this.menu.classList.remove('open') 536 } 537 538 static init() { 539 const menu = document.querySelector('.menu') 540 541 if (menu) { 542 new Menu(menu) 543 } 544 } 545} 546 547Menu.init() 548 549// ÐаÑка ÑелеÑона 550class Mask { 551 552 constructor(phone) { 553 this.phone = phone 554 555 if (!this.phone) return console.log('ЧÑо-Ñо не Ñак Ñ ÑелекÑоÑом'); 556 557 this.layout = '+7 (___) ___-__-__'; 558 this.maskreg = this.getRegexp(); 559 560 this.setListeners(); 561 } 562 563 getRegexp() { 564 var str = this.layout.replace(/_/g, '\\d') 565 str = str.replace(/\(/g, '\\(') 566 str = str.replace(/\)/g, '\\)') 567 str = str.replace(/\+/g, '\\+') 568 str = str.replace(/\s/g, '\\s') 569 570 return str; 571 } 572 573 mask(e) { 574 var _this = e.target, 575 matrix = this.layout, 576 i = 0, 577 def = matrix.replace(/\D/g, ""), 578 val = _this.value.replace(/\D/g, ""); 579 580 if (def.length >= val.length) val = def; 581 582 _this.value = matrix.replace(/./g, function (a) { 583 return /[_\d]/.test(a) && i < val.length ? val.charAt(i++) : i >= val.length ? "" : a 584 }); 585 586 if (e.type == "blur") { 587 var regexp = new RegExp(this.maskreg); 588 if (!regexp.test(_this.value)) _this.value = ""; 589 } else { 590 this.setCursorPosition(_this.value.length, _this); 591 } 592 } 593 594 setCursorPosition(pos, elem) { 595 elem.focus(); 596 if (elem.setSelectionRange) elem.setSelectionRange(pos, pos); 597 else if (elem.createTextRange) { 598 var range = elem.createTextRange(); 599 range.collapse(true); 600 range.moveEnd("character", pos); 601 range.moveStart("character", pos); 602 range.select() 603 } 604 } 605 606 setListeners() { 607 this.phone.addEventListener("input", this.mask.bind(this), false); 608 this.phone.addEventListener("focus", this.mask.bind(this), false); 609 this.phone.addEventListener("blur", this.mask.bind(this), false); 610 } 611 612 getElement(selector) { 613 if (selector === undefined) return false;
614 if (this.isElement(selector)) return selector; 615 if (typeof selector == 'string') { 616 var el = document.querySelector(selector); 617 if (this.isElement(el)) return el; 618 } 619 return false 620 } 621 622 isElement(element) { 623 return element instanceof Element || element instanceof HTMLDocument; 624 } 625 626 static init() { 627 const phones = document.querySelectorAll('[type=tel]:not(.no-mask)') 628 629 if (phones.length) { 630 phones.forEach(phone => new Mask(phone)) 631 } 632 } 633} 634 635Mask.init() 636 637// ÐоиÑк 638class Search { 639 constructor(search) { 640 this.search = search 641 this.search.addEventListener('submit', this.to_search.bind(this)) 642 643 this.search_input = this.search.querySelector('[name=search]') 644 645 if (document.querySelector('.search')) { 646 this.search_box = document.querySelector('.search') 647 648 this.search_open_button = document.querySelector('.header__search') 649 this.search_open_button.addEventListener('click', this.open.bind(this)) 650 651 this.search_close_button = this.search_box.querySelector('.search__close') 652 this.search_close_button.addEventListener('click', this.close.bind(this)) 653 } 654 } 655 656 open() { 657 this.search_box.classList.add('open') 658 } 659 660 close() { 661 this.search_box.classList.remove('open') 662 } 663 664 to_search(e) { 665 e.preventDefault() 666 667 if (this.search_input.value.length > 1) { 668 const url = '/index.php?route=product/search&search=' + this.search_input.value 669 location.href = url 670 } else { 671 Alert.add('ÐÐ»Ñ Ð¿Ð¾Ð¸Ñка введиÑе болÑÑе 1 Ñимвола', 'error') 672 } 673 } 674 675 static init() { 676 const searches = document.querySelectorAll('.search-form') 677 678 if (searches.length) { 679 searches.forEach(search => new Search(search)) 680 } 681 } 682} 683 684Search.init() 685 686// ÐлеÑÑÑ 687const alerts = [] 688 689class Alert { 690 constructor(message, type) { 691 this.message = message 692 this.type = type 693 this.alert = '' 694 695 this.create() 696 } 697 698 async create() { 699 await this.closeAll() 700 701 const alert = document.createElement('div') 702 alert.className = 'alert ' + this.type 703 alert.innerText = this.message 704 705 this.alert = alert 706 707 this.append() 708 } 709 710 async append() { 711 document.body.append(this.alert) 712 713 setTimeout(() => { 714 this.close() 715 }, 3000) 716 } 717 718 closeAll() { 719 return new Promise(async (resolve, reject) => { 720 if (alerts.length) { 721 for (let i = 0; i < alerts.length; i++) { 722 await alerts[i].close() 723 alerts.splice(i, 1) 724 } 725 726 resolve() 727 } else { 728 resolve() 729 } 730 }) 731 } 732 733 close() { 734 return new Promise((resolve, reject) => { 735 if (this.alert) { 736 this.alert.classList.add('close') 737 } 738 739 setTimeout(() => { 740 resolve() 741 }, 300) 742 }) 743 } 744 745 static add(message, type = 'success') { 746 alerts.push(new Alert(message, type)) 747 } 748} 749 750// СлайдеÑÑ 751class Slider { 752 constructor(selector, options) { 753 this.main = document.querySelector(selector) 754 755 if (this.main) { 756 this.slider = this.main.querySelector('.splide') 757 758 if (this.slider) { 759 this.slider = new Splide(this.slider, options).mount(); 760 761 this.prev_button = this.main.querySelector('.slider-navigation__arrow-prev') || this.main.querySelector('.slider__arrow-prev') 762 if (this.prev_button) this.prev_button.addEventListener('click', this.prev.bind(this)) 763 764 this.next_button = this.main.querySelector('.slider-navigation__arrow-next') || this.main.querySelector('.slider__arrow-next') 765 if (this.next_button) this.next_button.addEventListener('click', this.next.bind(this)) 766 767 this.createDotted() 768 769 switch (selector) { 770 case '.functions': 771 this.init_functions_slider() 772 break; 773 } 774 775 return this.slider 776 } 777 } 778 } 779 780 prev() { 781 this.slider.go('-') 782 } 783 784 next() { 785 this.slider.go('+') 786 } 787 788 async createDotted() { 789 const dotted = this.main.querySelector('.slider-navigation__dotted') || this.main.querySelector('.dotted') 790 791 if (dotted) { 792 if (this.slider.length > 1) { 793 for (let i = 0; i < this.slider.length; i++) { 794 let button = document.createElement('button') 795 button.dataset.index = i 796 797 if (i == 0) { 798 button.className = 'active' 799 } 800 801 button.addEventListener('click', () => { 802 this.slider.go(button.dataset.index) 803 804 dotted.querySelectorAll('.active').forEach(item => item.classList.remove('active')) 805 dotted.querySelectorAll('button')[this.slider.index].classList.add('active') 806 }) 807 808 await dotted.append(button) 809 } 810 811 812 this.slider.on('moved', (index) => { 813 dotted.querySelectorAll('.active').forEach(item => item.classList.remove('active')) 814 dotted.querySelectorAll('button')[index].classList.add('active') 815 }) 816 } 817 } 818 } 819 820 // ÐндивидÑалÑнÑе меÑÐ¾Ð´Ñ 821 init_functions_slider() { 822 this.slider.on('moved', (index) => { 823 const title = this.main.querySelectorAll('.functions__item:not(.splide__slide--clone)')[index].dataset.title 824 const text = this.main.querySelectorAll('.functions__item:not(.splide__slide--clone)')[index].dataset.desc 825 826 this.main.querySelector('.functions__name').innerText = title 827 this.main.querySelector('.functions__desc').innerText = text 828 }) 829 } 830 831 static init() { 832 // ÐлавнÑй 833 // new Slider('.slider', { 834 // type: 'loop',
835 // arrows: false, 836 // pagination: false, 837 // autoplay: false, 838 // // interval: 5000, 839 // }) 840 841 // ÐÐ´Ð¾Ñ Ð½Ð¾Ð²ÐµÐ½Ð¸Ðµ 842 new Slider('.worths', { 843 type: 'loop', 844 arrows: false, 845 pagination: false, 846 autoplay: true, 847 interval: 5000, 848 perPage: 1, 849 perMove: 1, 850 width: '700px', 851 gap: '50px', 852 breakpoints: { 853 1150: { 854 width: '500px', 855 }, 856 640: { 857 width: '280px', 858 gap: '10px', 859 } 860 } 861 }) 862 863 // ÐалеÑÐµÑ 864 new Slider('.gallery', { 865 type: 'slide', 866 arrows: false, 867 pagination: false, 868 autoplay: true, 869 interval: 5000, 870 perPage: 1, 871 perMove: 1, 872 gap: '20px', 873 trimSpace: true, 874 breakpoints: { 875 768: { 876 perPage: 2, 877 }, 878 480: { 879 perPage: 1, 880 } 881 } 882 }) 883 884 // ФÑнкÑии 885 new Slider('.functions', { 886 type: 'loop', 887 arrows: false, 888 pagination: false, 889 autoplay: true, 890 interval: 5000, 891 perPage: 1, 892 perMove: 1, 893 gap: '10px', 894 }) 895 896 // ФоÑо ÑоваÑа 897 new Slider('.product-page__images', { 898 type: 'slide', 899 arrows: false, 900 pagination: false, 901 autoplay: false, 902 perPage: 7, 903 perMove: 1, 904 gap: '10px', 905 trimSpace: false 906 }) 907 908 // ÐалеÑÐµÑ ÑоваÑа 909 new Slider('.product-gallery', { 910 type: 'slide', 911 arrows: false, 912 pagination: false, 913 autoplay: true, 914 interval: 5000, 915 perPage: 1, 916 perMove: 1, 917 gap: '20px', 918 trimSpace: true, 919 autoWidth: true, 920 breakpoints: { 921 768: { 922 perPage: 2, 923 }, 924 480: { 925 perPage: 1, 926 } 927 } 928 // type: 'slide', 929 // arrows: false, 930 // pagination: false, 931 // autoplay: true, 932 // interval: 5000, 933 // perPage: 1, 934 // perMove: 1, 935 // gap: '20px', 936 // trimSpace: false, 937 // autoWidth: true, 938 // breakpoints: { 939 // 768: { 940 // perPage: 2, 941 // }, 942 // 480: { 943 // perPage: 1, 944 // } 945 // } 946 }) 947 948 // ÐалеÑÐµÑ Ð²Ð´Ð¾Ñ Ð½Ð¾Ð²ÐµÐ½Ð¸Ñ 949 new Slider('.inspiration__slider', { 950 type: 'slide', 951 arrows: false, 952 pagination: false, 953 autoplay: true, 954 interval: 5000, 955 perPage: 3, 956 perMove: 1, 957 gap: '20px', 958 trimSpace: false, 959 breakpoints: { 960 768: { 961 perPage: 2, 962 }, 963 480: { 964 perPage: 1, 965 } 966 } 967 }) 968 969 // ÐодбоÑка ÑоваÑов Ð²Ð´Ð¾Ñ Ð½Ð¾Ð²ÐµÐ½Ð¸Ñ 970 new Slider('.related', { 971 type: 'loop', 972 arrows: false, 973 pagination: false, 974 autoplay: true, 975 interval: 5000, 976 perPage: 3, 977 perMove: 1, 978 trimSpace: true, 979 gap: '0px', 980 breakpoints: { 981 768: { 982 perPage: 2, 983 }, 984 480: { 985 perPage: 1, 986 } 987 } 988 }) 989 990 // Ð¡Ð»Ð°Ð¹Ð´ÐµÑ Ð¼Ð°ÑеÑиалов 1 991 new Slider('.inspiration__slider-2-1', { 992 type: 'loop', 993 arrows: false, 994 pagination: false, 995 autoplay: true, 996 interval: 5000, 997 perPage: 2, 998 perMove: 1, 999 gap: '20px', 1000 breakpoints: { 1001 640: { 1002 perPage: 1, 1003 } 1004 } 1005 }) 1006 1007 // Ð¡Ð»Ð°Ð¹Ð´ÐµÑ Ð¼Ð°ÑеÑиалов 2 1008 new Slider('.inspiration__slider-2-2', { 1009 type: 'loop',
1010 arrows: false, 1011 pagination: false, 1012 autoplay: true, 1013 interval: 5000, 1014 perPage: 2, 1015 perMove: 1, 1016 gap: '20px', 1017 breakpoints: { 1018 640: { 1019 perPage: 1, 1020 } 1021 } 1022 }) 1023 1024 // ÐолÑÑе о коже 1025 new Slider('.inspiration__more', { 1026 type: 'loop', 1027 arrows: false, 1028 pagination: false, 1029 autoplay: true, 1030 interval: 5000, 1031 perPage: 3, 1032 perMove: 1, 1033 gap: '20px', 1034 breakpoints: { 1035 996: { 1036 perPage: 2, 1037 }, 1038 480: { 1039 perPage: 1, 1040 } 1041 } 1042 }) 1043 1044 // ÐодбоÑка ÑоваÑов Ð²Ð´Ð¾Ñ Ð½Ð¾Ð²ÐµÐ½Ð¸Ñ 1045 new Slider('.other-news', { 1046 type: 'loop', 1047 arrows: false, 1048 pagination: false, 1049 autoplay: true, 1050 interval: 5000, 1051 perPage: 3, 1052 perMove: 1, 1053 gap: '20px', 1054 breakpoints: { 1055 768: { 1056 perPage: 2, 1057 }, 1058 480: { 1059 perPage: 1, 1060 } 1061 } 1062 }) 1063 } 1064} 1065 1066Slider.init() 1067 1068// Ð¢Ð°Ð±Ñ ÑоваÑа 1069class ProductDetails { 1070 constructor(details) { 1071 this.details = details 1072 1073 this.togglers = this.details.querySelectorAll('.product-detail__toggle') 1074 this.togglers.forEach(toggler => toggler.addEventListener('click', (e) => { 1075 this.togglers.forEach(toggler => toggler.classList.remove('active')) 1076 e.target.classList.add('active') 1077 1078 const need = e.target.dataset.tab 1079 1080 this.toggle(need) 1081 })) 1082 1083 this.tabs = this.details.querySelectorAll('.product-detail__tab') 1084 1085 if (this.togglers.length) { 1086 this.first_toggle = this.togglers[0] 1087 this.first_toggle.classList.add('active') 1088 this.first_tab = this.first_toggle.dataset.tab 1089 this.toggle(this.first_tab) 1090 } 1091 } 1092 1093 toggle(need) {
1094 this.tabs.forEach(tab => { 1095 tab.classList.remove('open') 1096 setTimeout(() => { 1097 tab.setAttribute('hidden', true) 1098 }, 200) 1099 }) 1100 1101 setTimeout(() => { 1102 need = this.details.querySelector('#tab-' + need) 1103 1104 need.removeAttribute('hidden') 1105 need.classList.add('open') 1106 }, 200) 1107 } 1108 1109 static init() { 1110 const details = document.querySelector('.product-detail') 1111 1112 if (details) { 1113 new ProductDetails(details) 1114 } 1115 } 1116} 1117 1118ProductDetails.init() 1119 1120// СелекÑÑ 1121let selects = [] 1122 1123class Select { 1124 constructor(select) { 1125 this.select = select 1126 this.is_open = false 1127 this.input = this.select.querySelector('input') 1128 1129 this.button = this.select.querySelector('.select__button') 1130 this.button.addEventListener('click', this.toggle.bind(this)) 1131 this.button_text = this.button.querySelector('span') 1132 1133 this.list = this.select.querySelector('.select__body') 1134 if (this.list) { 1135 this.options = this.list.querySelectorAll('[data-value]') 1136 this.options.forEach(option => option.addEventListener('click', this.choise.bind(this))) 1137 } 1138 } 1139 1140 toggle() { 1141 if (this.is_open) { 1142 this.close() 1143 } else { 1144 this.open() 1145 } 1146 1147 this.is_open = !this.is_open 1148 } 1149 1150 choise(e) { 1151 const elem = e.target 1152 const value = elem.dataset.value 1153 const text = elem.innerText 1154 1155 this.input.value = value != '' ? value : '' 1156 this.button.innerText = value != '' ? text : 'ÐÑбÑаÑÑ' 1157 1158 this.input.dispatchEvent(new Event('change')) 1159 1160 this.close() 1161 } 1162 1163 close() { 1164 this.select.classList.remove('open') 1165 } 1166 1167 open() { 1168 selects.forEach(select => select.close()) 1169 1170 this.select.classList.add('open') 1171 } 1172 1173 static init() { 1174 const selected = document.querySelectorAll('.select') 1175 1176 if (selected.length) { 1177 selected.forEach(select => selects.push(new Select(select))) 1178 } 1179 } 1180} 1181 1182Select.init() 1183 1184// ФоÑо ÑоваÑа 1185class ProductImages { 1186 constructor(product_images) { 1187 this.main = product_images 1188 1189 this.main_image = this.main.querySelector('.product-page__image img') 1190 1191 this.minimages = this.main.querySelectorAll('.product-page__minimage') 1192 this.minimages.forEach(image => image.addEventListener('click', this.changeImage.bind(this))) 1193 } 1194 1195 changeImage(e) { 1196 const src = e.target.dataset.big 1197 this.main_image.src = src 1198 } 1199 1200 static init() { 1201 const product_images = document.querySelector('.product-page__images') 1202 1203 if (product_images) { 1204 new ProductImages(product_images) 1205 } 1206 } 1207} 1208 1209ProductImages.init() 1210 1211// РекомендÑемÑе 1212class Recomended { 1213 constructor(recomended) { 1214 this.recomended = recomended 1215 1216 this.content = this.recomended.querySelector('.splide__list') 1217 this.slider = null 1218 1219 this.categories = this.recomended.querySelectorAll('.recomended__category') 1220 this.categories.forEach(category => category.addEventListener('click', this.getProducts.bind(this))) 1221 1222 setTimeout(this.getFirst.bind(this), 2000) 1223 } 1224 1225 getFirst() { 1226 this.categories[0].dispatchEvent(new Event('click')) 1227 } 1228 1229 async getProducts(e) { 1230 const category_id = e.target.dataset.categoryId 1231 1232 this.categories.forEach(category => category.classList.remove('active')) 1233 e.target.classList.add('active') 1234 1235 const recomended_data = new FormData() 1236 recomended_data.append('category_id', category_id) 1237 1238 let response = await fetch('/index.php?route=product/recomended/getProducts', { 1239 method: 'POST', 1240 body: recomended_data 1241 }) 1242 1243 response = await response.json() 1244 1245 if (response.products) { 1246 await this.refresh() 1247 1248 for (let product in response.products) { 1249 const product_card = await Functions.htmlToElement(response.products[product]) 1250 await this.content.append(product_card) 1251 } 1252 1253 // ÐалеÑÐµÑ ÑекомендÑемÑÑ 1254 this.slider = new Slider('.recomended', { 1255 type: 'loop',
1256 arrows: false, 1257 pagination: false, 1258 autoplay: true, 1259 interval: 5000, 1260 perPage: 3, 1261 perMove: 1, 1262 gap: '0px', 1263 breakpoints: { 1264 768: { 1265 perPage: 2, 1266 }, 1267 480: { 1268 perPage: 1, 1269 } 1270 } 1271 }) 1272 1273 } 1274 } 1275 1276 refresh() { 1277 return new Promise((resolve, reject) => { 1278 this.content.innerHTML = '' 1279 1280 if (this.slider) { 1281 this.slider.refresh() 1282 } 1283 1284 resolve() 1285 }) 1286 } 1287 1288 static init() { 1289 const recomended = document.querySelector('.recomended') 1290 1291 if (recomended) { 1292 new Recomended(recomended) 1293 } 1294 } 1295} 1296 1297Recomended.init() 1298 1299// Ð¡Ð»Ð°Ð¹Ð´ÐµÑ Ð² каÑÑоÑке ÑоваÑа 1300let product_card_sliders = [] 1301 1302class ProductCardSlider { 1303 constructor(product) { 1304 this.product = product 1305 this.id = this.product.dataset.id 1306 1307 this.createSlider() 1308 } 1309 1310 createSlider() { 1311 const class_id = '.product-card-' + this.id 1312 1313 new Slider(class_id, { 1314 type: 'loop', 1315 arrows: false, 1316 pagination: false, 1317 perPage: 1, 1318 perMove: 1, 1319 autoplay: false 1320 }) 1321 } 1322 1323 static init() { 1324 const products = document.querySelectorAll('.product-card') 1325 1326 if (products) { 1327 products.forEach(product => product_card_sliders.push(new ProductCardSlider(product))) 1328 } 1329 } 1330} 1331 1332ProductCardSlider.init() 1333 1334// РаÑкÑÑваÑки 1335class Toggler { 1336 constructor(toggler) { 1337 this.toggler = toggler 1338 this.parent = this.toggler.closest('.toggle-parrent') 1339 this.toggle = this.parent.querySelector('.toggle') 1340 this.is_open = false 1341 1342 this.toggler.addEventListener('click', this.toggleChange.bind(this)) 1343 } 1344 1345 toggleChange() { 1346 if (this.is_open) { 1347 this.toggle.classList.remove('open') 1348 this.toggler.innerText = 'РазвеÑнÑÑÑ' 1349 } else { 1350 this.toggle.classList.add('open') 1351 this.toggler.innerText = 'СвеÑнÑÑÑ' 1352 } 1353 1354 this.is_open = !this.is_open 1355 } 1356 1357 static init() { 1358 const togglers = document.querySelectorAll('.toggler') 1359 1360 if (togglers.length) { 1361 togglers.forEach(item => new Toggler(item)) 1362 } 1363 } 1364} 1365 1366Toggler.init() 1367 1368// Lightbox 1369class Lightbox { 1370 constructor() { 1371 this.lightbox = document.querySelector('.lightbox') 1372 1373 if (this.lightbox) { 1374 this.content = this.lightbox.querySelector('.lightbox__content') 1375 this.content.addEventListener('click', this.close.bind(this)) 1376 1377 this.lightbox_elements = [] 1378 this.open_handler = this.open.bind(this) 1379 this.set_listeners() 1380 } 1381 } 1382 1383 set_listeners() { 1384 if (this.lightbox_elements.length) { 1385 this.lightbox_elements.forEach(elem => elem.removeEventListener('click', this.open_handler)) 1386 } 1387 1388 this.lightbox_elements = document.querySelectorAll('[lightbox]') 1389 this.lightbox_elements.forEach(elem => elem.addEventListener('click', this.open_handler)) 1390 } 1391 1392 open(e) { 1393 const elem = e.target 1394 1395 console.log(elem) 1396 1397 this.content.innerHTML = '' 1398 1399 if (elem.dataset.lightboxImg) { 1400 const img = document.createElement('img') 1401 img.src = elem.dataset.lightboxImg 1402 1403 this.content.append(img) 1404 } 1405 1406 this.lightbox.removeAttribute('hidden') 1407 this.lightbox.classList.add('open') 1408 1409 } 1410 1411 close() { 1412 this.lightbox.classList.remove('open') 1413 1414 setTimeout(() => { 1415 this.lightbox.setAttribute('hidden', true) 1416 this.content.innerHTML = '' 1417 }, 200) 1418 } 1419 1420 static init() { 1421 const lightbox = document.querySelector('.lightbox') 1422 1423 if (lightbox) { 1424 new Lightbox(lightbox) 1425 } 1426 } 1427} 1428 1429let lightbox = new Lightbox() 1430 1431// ÐнимаÑии 1432 1433let observer = new IntersectionObserver(start_animation, {threshold: 0.5}) 1434document.querySelectorAll('.animation-element').forEach(element => observer.observe(element)) 1435 1436function start_animation(elements, intersectionRatio) {
1437 elements.forEach(async element => { 1438 let _element = element.target 1439 // console.log(_element) 1440 if (_element.classList.contains('animation-element') && element.intersectionRatio > 0.1) { 1441 if (_element.dataset.delay) { 1442 await setTimeout(() => { 1443 _element.classList.remove('animation-element') 1444 _element.classList.add('start') 1445 }, _element.dataset.delay * 1000) 1446 } else { 1447 _element.classList.remove('animation-element') 1448 _element.classList.add('start') 1449 } 1450 1451 if (_element.classList.contains('animation-element-list')) { 1452 _element.querySelectorAll('.animation-element-item').forEach((item, i) => { 1453 setTimeout(() => { 1454 item.classList.add('start') 1455 }, i * 400) 1456 }) 1457 } 1458 } 1459 }) 1460} 1461 1462// ФÑнкÑии 1463class Functions { 1464 static htmlToElement(html) { 1465 const template = document.createElement('template'); 1466 1467 html = html.trim(); 1468 1469 template.innerHTML = html; 1470 1471 return template.content.firstChild; 1472 } 1473} 1474 1475// ÐÑделение акÑивнÑÑ Ð¿ÑнкÑов Ð¼ÐµÐ½Ñ 1476const current_url = [location.href, location.pathname, location.pathname.replace('/', '')] 1477current_url.forEach(function (item) { 1478 document.querySelectorAll('[href="' + item + '"]').forEach(item => item.classList.add('active')) 1479}) 1480 1481// Recaptha 1482// function recaptha() { 1483// return new Promise(function (resolve, reject) { 1484// grecaptcha.ready(function () { 1485// grecaptcha.execute('6Lc4f7coAAAAAOEOBp2L9Ol5wEzCGsbksx7Btjh8', {action: 'contact'}).then(function (token) { 1486// document.querySelectorAll('[name=recaptcha_response]').forEach(elem => elem.value = token) 1487// resolve() 1488// }); 1489// }); 1490// }) 1491// } 1492 1493// grecaptcha.ready(function () { 1494// document.querySelectorAll('.modal__form-form').forEach(form => { 1495// let recaptcha_elem = document.createElement('div') 1496// recaptcha_elem.className = 'g-recaptcha' 1497// recaptcha_elem.dataset.sitekey = '6LeWi7coAAAAAPLSSN8A_qZrNCS5Q9vEbxT2Fw74' 1498// 1499// form.append(recaptcha_elem) 1500// 1501// grecaptcha.render(recaptcha_elem) 1502// }) 1503// 1504// }) 1505 1506// window.onloadRecaptcha = function () { 1507// document.querySelectorAll('.grecap').forEach(elem => { 1508// grecaptcha.render(elem, { 1509// 'sitekey': '6LcBZekUAAAAABN1SVylHf7xmgHtfY7Z0KZHD0em' 1510// }) 1511// }) 1512// } 1513 1514const header = document.querySelector('.header'); 1515let isAnimating = false; 1516 1517let currentPath = window.location.pathname; 1518let currentSearch = window.location.search; 1519 1520document.addEventListener('scroll', (e) => { 1521 1522 let scrolledDistance = window.scrollY; 1523 if (scrolledDistance > 650) { 1524 if (!header.classList.contains('scrolled')) { 1525 header.classList.add('scrolled'); 1526 if (currentPath !== '/' && (currentPath !== '/index.php' || currentSearch !== '?route=common/home')) { 1527 header.classList.add('notMain'); 1528 } 1529 header.animate( 1530 [{top: '-150px'}, {top: '0'},], 1531 {duration: 500, iterations: 1,} 1532 ); 1533 } 1534 } else if (scrolledDistance < 650 && !isAnimating) { 1535 if (header.classList.contains('scrolled')) { 1536 isAnimating = true; 1537 let answer = header.animate( 1538 [{top: '0'}, {top: '-150px'},], 1539 {duration: 300, iterations: 1,} 1540 ); 1541 answer.addEventListener('finish', function () { 1542 header.classList.remove('scrolled'); 1543 header.classList.remove('notMain'); 1544 isAnimating = false; 1545 }); 1546 } 1547 } 1548}); 1549 1550class Range { 1551 constructor(range) { 1552 this.range = range 1553 1554 // Ð¡Ð¾Ñ ÑанÑем обеÑÑÐºÑ Ð³Ð´Ðµ бÑÐ´ÐµÑ ÑендеÑиÑÑÑ ÑÐ»Ð°Ð¹Ð´ÐµÑ 1555 this.slider_container = this.range.querySelector('.noui-slider') 1556 this.slider = null 1557 1558 // ÐеÑем минималÑное и макÑималÑное из data аÑÑÑибÑÑов 1559 this.min = parseInt(this.range.dataset.min) 1560 this.max = parseInt(this.range.dataset.max) 1561 1562 // ÐеÑем наÑалÑное и конеÑное знаÑение из data аÑÑÑибÑÑов, еÑли Ð½ÐµÑ - беÑем наÑалÑное и конеÑное 1563 this.start = this.range.dataset.start ? parseInt(this.range.dataset.start) : this.min 1564 this.end = this.range.dataset.end ? parseInt(this.range.dataset.end) : this.max 1565 1566 // ÐÐ¾Ð»Ñ Ð²Ð²Ð¾Ð´Ð° коÑоÑÑе бÑдÑÑ ÑвÑÐ·Ð°Ð½Ñ Ñ ÑлаиÌдеÑом 1567 this.input_from = this.range.querySelector('[data-from]') 1568 this.input_to = this.range.querySelector('[data-to]') 1569 1570 // Ð¥ÐµÐ½Ð´Ð»ÐµÑ ÐºÐ¾ÑоÑÑй бÑÐ´ÐµÑ ÑÑÑанавливаÑÑ Ð·Ð½Ð°Ñение в ÑÐ»Ð°Ð¹Ð´ÐµÑ Ð¸Ð· инпÑÑов 1571 this.set_value_to_slider_handler = this.setValueToSlider.bind(this) 1572 1573 this.create() 1574 } 1575 1576 create() { 1577 // ÐниÑиализиÑÑем ÑÐ»Ð°Ð¹Ð´ÐµÑ 1578 this.slider = noUiSlider.create(this.slider_container, { 1579 // ÐаÑалÑнÑе знаÑÐµÐ½Ð¸Ñ 1580 start: [ 1581 this.start, 1582 this.end 1583 ], 1584 // ÐинималÑное и макÑималÑное знаÑÐµÐ½Ð¸Ñ 1585 range: { 1586 min: this.min, 1587 max: this.max 1588 }, 1589 connect: true, 1590 }); 1591 1592 // СобÑÑие когда Ð¼Ñ Ð¸Ð·Ð¼ÐµÐ½Ð¸Ð»Ð¸ знаÑÐµÐ½Ð¸Ñ Ð² ÑлаиÌдеÑе 1593 this.slider.on('update', (values, handle) => { 1594 // УÑÑанавливаем минималÑное и макÑималÑное в инпÑÑÑ 1595 switch (handle) { 1596 case 0: 1597 this.input_from.value = parseInt(values[0]) 1598 this.min = parseInt(values[0]) 1599 break; 1600 case 1: 1601 this.input_to.value = parseInt(values[1]) 1602 this.max = parseInt(values[1]) 1603 break; 1604 } 1605 }); 1606 1607 // ÐеÑаем ÑобÑÑÐ¸Ñ Ð½Ð° инпÑÑÑ, пÑи изменении бÑдем ÑÑÑанавливаÑÑ Ð·Ð½Ð°Ñение в ÑлаиÌÐ´ÐµÑ 1608 this.input_from.addEventListener('change', this.set_value_to_slider_handler) 1609 this.input_to.addEventListener('change', this.set_value_to_slider_handler) 1610 } 1611 1612 setValueToSlider() { 1613 this.slider.set([ 1614 this.input_from.value, 1615 this.input_to.value 1616 ]) 1617 } 1618 1619 static init() { 1620 const ranges = document.querySelectorAll('[data-range]') 1621 1622 if (ranges.length) {
1623 ranges.forEach(range => new Range(range)) 1624 } 1625 } 1626} 1627 1628Range.init() 1629window.addEventListener('load', function () { 1630 let url = new URL(location.href) 1631 let search = url.search 1632 console.log(search) 1633 if (search.includes('option_')) { 1634 let catalog = document.querySelector('.category__block') 1635 if (catalog) { 1636 catalog.scrollIntoView({block: "start", behavior: "smooth"}); 1637 1638 } 1639 } 1640 1641})
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.