1// const btnFixed = document.querySelector('[data-element="btn-fixed"]') 2 3// if (btnFixed) btnFixedInit() 4 5// function btnFixedInit () { 6// const start = btnFixed.getAttribute('data-btn-fixed-start') 7// const end = btnFixed.getAttribute('data-btn-fixed-end') 8// const body = document.getElementsByTagName('body')[0] 9// window.addEventListener('scroll', checkBtnFixed, { passive: true }) 10 11// function checkBtnFixed () { 12// if (window.pageYOffset > start && body.scrollHeight - window.pageYOffset > end && !checkBtnFixedHide()) { 13// btnFixed.classList.add('btn-fixed_active') 14// } else { 15// btnFixed.classList.remove('btn-fixed_active') 16// } 17// } 18 19// const sectionsWhenBtnHide = document.querySelectorAll('[data-btn-fixed-hide="true"]') 20 21// function checkBtnFixedHide () { 22// let isHide = false 23// for (let i = 0; i < sectionsWhenBtnHide.length; i++) { 24// if (elementInViewport(sectionsWhenBtnHide[i])) isHide = true 25// } 26// return isHide 27// } 28 29// function elementInViewport(el) { 30// let top = el.offsetTop 31// let left = el.offsetLeft 32// let width = el.offsetWidth 33// let height = el.offsetHeight 34 35// while(el.offsetParent) { 36// el = el.offsetParent 37// top += el.offsetTop 38// left += el.offsetLeft 39// } 40 41// return ( 42// top < (window.pageYOffset + window.innerHeight) && 43// left < (window.pageXOffset + window.innerWidth) && 44// (top + height) > window.pageYOffset && 45// (left + width) > window.pageXOffset 46// ) 47// } 48 49// } 50 51const aboutSchoolChatsSlider = document.querySelector('.about-school-chats__slider') 52 53if (aboutSchoolChatsSlider) aboutSchoolChatsSliderInit() 54 55function aboutSchoolChatsSliderInit () { 56 let sliderSwiper 57 58 function initSlider () { 59 sliderSwiper = new Swiper(aboutSchoolChatsSlider, { 60 mousewheel: { forceToAxis: true }, 61 slidesPerView: 'auto', 62 spaceBetween: 10, 63 a11y: false, 64 }) 65 } 66 67 window.addEventListener('resize', checkSlider) 68 69 checkSlider() 70 71 function checkSlider () { 72 if (window.innerWidth < 744) { 73 if (!sliderSwiper || sliderSwiper.destroyed) { 74 initSlider() 75 } 76 } else { 77 if (sliderSwiper && !sliderSwiper.destroyed) { 78 sliderSwiper.destroy(true, true) 79 sliderSwiper = null 80 } 81 } 82 } 83} 84 85const aboutSchoolGallerySlider = document.querySelector('.about-school-gallery__slider') 86 87if (aboutSchoolGallerySlider) aboutSchoolGallerySliderInit() 88 89function aboutSchoolGallerySliderInit () { 90 let sliderSwiper 91 92 function initSlider () { 93 sliderSwiper = new Swiper(aboutSchoolGallerySlider, { 94 mousewheel: { forceToAxis: true }, 95 slidesPerView: 'auto', 96 spaceBetween: 10, 97 a11y: false, 98 grid: { 99 rows: 2, 100 fill: 'row', 101 }, 102 }) 103 } 104 105 window.addEventListener('resize', checkSlider) 106 107 checkSlider() 108 109 function checkSlider () { 110 if (window.innerWidth < 744) { 111 if (!sliderSwiper || sliderSwiper.destroyed) { 112 initSlider() 113 } 114 } else { 115 if (sliderSwiper && !sliderSwiper.destroyed) { 116 sliderSwiper.destroy(true, true) 117 sliderSwiper = null 118 } 119 } 120 } 121} 122 123 124dataHrefLinksInit() 125 126function dataHrefLinksInit(node) { 127 if (node) { 128 if (node.getAttribute("data-href-link") || node.href) { 129 node.addEventListener('click', addHandler) 130 } else { 131 const dataHrefLinkInsideNode = node.querySelectorAll('[data-href-link]') 132 for (let i = 0; i < dataHrefLinkInsideNode.length; i++) { 133 dataHrefLinkInsideNode[i].addEventListener('click', addHandler) 134 } 135 } 136 } else { 137 const dataHrefLinks = document.querySelectorAll('[data-href-link]') 138 for (let i = 0; i < dataHrefLinks.length; i++) { 139 dataHrefLinks[i].addEventListener('click', addHandler) 140 } 141 } 142 143 function addHandler (e) { 144 e.preventDefault() 145 let href = '' 146 if (this.getAttribute('data-href-link')) { 147 href = this.getAttribute('data-href-link') 148 } else if (this.href) { 149 href = this.href 150 } 151 if (href) window.open(href, '_blank') 152 } 153} 154 155 156const allCourses = document.querySelector('.all-courses') 157 158 if (allCourses) allCoursesInit() 159 160 function allCoursesInit () { 161 const config = { attributes: false, childList: true, characterData: true, subtree: true } 162 163 const stickyHeader = document.querySelector('.sticky-header') 164 const body = document.querySelector('body') 165 const wrap = document.querySelector('.all-courses__wrap') 166 const urlFilter = allCourses.getAttribute('data-item-h') 167 const h1Filter = allCourses.getAttribute('data-hname')
168 const metaNameFilter = allCourses.getAttribute('data-meta_name') 169 const metaDescriptionFilter = allCourses.getAttribute('data-meta_descr') 170 const openers = allCourses.querySelectorAll("[data-element='all-courses-filter-opener']") 171 const filterh1block = allCourses.querySelector(".all-courses_h1") 172 const filterSubjectWrap = allCourses.querySelector(".all-courses__filter-wrap_subject") 173 const findBtn = allCourses.querySelector('.all-courses__find') 174 const reset = allCourses.querySelector('.all-courses__reset') 175 const grades = allCourses.querySelector("[data-ftype='class_select']") 176 const subjects = allCourses.querySelector("[data-ftype='class_subjects']") 177 const tags = allCourses.querySelector("[data-ftype='class_tags']") 178 const tile = document.querySelector('.all-courses__tile') 179 const filterSumr = allCourses.querySelector('[data-role="filter-sumr"]') 180 const filterNewy = allCourses.querySelector('[data-role="filter-newy"]') 181 const filterHeadline = filterSubjectWrap.querySelector('.all-courses__filter-headline.desk') 182 let timerReload = setTimeout(() => window.location.reload(), 300000) 183 184 185 filterSumr?.addEventListener('change', () => { 186 const checkedCollegeInputs = allCourses.querySelectorAll('[data-filter-college]:checked') 187 checkedCollegeInputs.forEach(college => { 188 college.checked = false 189 const opener = college.closest(".all-courses__filter")?.querySelector('.all-courses__filter-top') 190 if (!opener) return 191 opener.innerHTML = '' 192 const span = document.createElement('span') 193 span.innerHTML = opener.getAttribute('data-default-text') 194 opener.append(span) 195 const tabs = filterSubjectWrap.querySelectorAll('.all-courses__filter-tab') 196 if (tabs.length) tabs[0].click() 197 }) 198 makeFiltration(1) 199 toggleReset() 200 }) 201 202 203 filterNewy?.addEventListener('change', () => { 204 makeFiltration(1) 205 toggleReset() 206 }) 207 208 209 210 211 if (reset) reset.addEventListener('click', resetFilters) 212 213 function resetFilters () { 214 for (let i = 0; i < openers.length; i++) { 215 const wrap = openers[i].nextElementSibling 216 const items = wrap.querySelectorAll("input") 217 items.forEach((item) => { 218 item.checked = false 219 }) 220 updateFilter(openers[i], wrap, false, true) 221 } 222 223 makeFiltration(1, true) 224 if (reset) reset.classList.remove('active') 225 } 226 227 function resetFilter (opener) { 228 const wrap = opener.nextElementSibling 229 const items = wrap.querySelectorAll("input") 230 items.forEach((item) => { 231 item.checked = false 232 }) 233 updateFilter(opener, wrap) 234 } 235 236 moreBtnInit() 237 238 239 function moreBtnInit () { 240 const moreBtn = allCourses.querySelector('.all-courses__more-button') 241 if (moreBtn) moreBtn.addEventListener('click', () => makeFiltration(moreBtn.getAttribute('data-v'))) 242 } 243 244 const observer = new MutationObserver(function observerCallback(mutations) { 245 mutations.forEach( 246 (mutation) => { 247 if (mutation.addedNodes.length) { 248 mutation.addedNodes.forEach((node) => { 249 if (node?.classList?.contains('all-courses__item')) { 250 dataHrefLinksInit(node) 251 togglePrice(node) 252 fancyboxAjaxCardsReInit(node) 253 initCommonAnalytics(node) 254 } 255 }) 256 } 257 }) 258 moreBtnInit() 259 }) 260 261 function updateBodyDataParams (grades_result, subjects_result, tags_result) { 262 grades_result = grades_result === '' || grades_result === null || grades_result === undefined ? 'all' : grades_result; 263 subjects_result = subjects_result === '' || subjects_result === null || subjects_result === undefined ? 'all' : subjects_result; 264 tags_result = tags_result === '' || tags_result === null || tags_result === undefined ? 'all' : tags_result; 265 body.setAttribute('data-filter-stage', grades_result) 266 body.setAttribute('data-filter-subject', subjects_result) 267 body.setAttribute('data-filter-goal', tags_result) 268 const grades = grades_result !== 'all' ? '_grade' : '' 269 const subjects = subjects_result !== 'all' ? '_subject' : '' 270 const tags = tags_result !== 'all' ? '_tag' : '' 271 const dataPageType = `catalog${grades}${subjects}${tags}` 272 body.setAttribute('data-page-type', dataPageType) 273 } 274 275 276 if (tile) observer.observe(tile, config) 277 278 if (tile) togglePrice() 279 280 function togglePrice (node) { 281 if (node) { 282 togglePriceHandler(node) 283 } else { 284 const items = tile?.querySelectorAll(".all-courses__item")
285 items.forEach((item) => { 286 togglePriceHandler(item) 287 }) 288 } 289 function togglePriceHandler (item) { 290 const toggle = item.querySelectorAll('.all-courses__radio-input') 291 if (!toggle.length) return 292 const boxes = item.querySelectorAll('.all-courses__box') 293 const textReplace = item.querySelector('.all-courses__info.text-replace') 294 let texts 295 if (textReplace) { 296 texts = textReplace.querySelectorAll('.all-courses__info-span') 297 } 298 for (let i = 0; i < toggle.length; i++) { 299 toggle[i].addEventListener('change', toggleBoxes) 300 if (texts) toggle[i].addEventListener('change', toggleTexts) 301 } 302 303 function toggleBoxes () { 304 for (let i = 0; i < boxes.length; i++) { 305 if (boxes[i].classList.contains('hide')) { 306 boxes[i].classList.remove('hide') 307 } else { 308 boxes[i].classList.add('hide') 309 } 310 } 311 } 312 function toggleTexts () { 313 for (let i = 0; i < texts.length; i++) { 314 if (texts[i].classList.contains('hide')) { 315 texts[i].classList.remove('hide') 316 } else { 317 texts[i].classList.add('hide') 318 } 319 } 320 } 321 } 322 } 323 324 325 initTabs() 326 327 function initTabs () { 328 const tabsParent = filterSubjectWrap.querySelector('.all-courses__filter-tabs') 329 const list = filterSubjectWrap.querySelector('.all-courses__filter-list') 330 const tabs = filterSubjectWrap.querySelectorAll('.all-courses__filter-tab') 331 const subjectsBoxes = filterSubjectWrap.querySelectorAll('.all-courses__filter-box') 332 333 if (!tabs.length || !subjectsBoxes.length) return 334 335 filterSubjectWrap.addEventListener('scroll', wrapScrollHandler, { passive: true }) 336 337 function wrapScrollHandler () { 338 subjectsBoxes.forEach((subjectBox) => { 339 if (filterSubjectWrap.scrollTop >= subjectBox.offsetTop - 90 - 65) { 340 const oldTab = filterSubjectWrap.querySelector('.all-courses__filter-tab.active') 341 if (oldTab) oldTab.classList.remove('active') 342 const index = subjectBox.getAttribute('data-index') 343 const tab = filterSubjectWrap.querySelector('[data-index="' + index + '"]') 344 if (tab) { 345 tabsParent.scrollLeft = tab.offsetLeft - tabsParent.clientWidth/2 + tab.clientWidth/2 346 tab.classList.add('active') 347 } 348 } 349 }) 350 } 351 352 let timeout 353 let firstToggle = true 354
355 tabs.forEach((tab) => { 356 tab.addEventListener('click', changeTab) 357 tab.addEventListener('mouseenter', changeTab) 358 }) 359 360 function changeTab (e) { 361 e.stopPropagation() 362 clearTimeout(timeout) 363 timeout = setTimeout(() => toggle(this),100) 364 365 function toggle (that) { 366 if (!that.closest('.all-courses__filter-wrap')?.querySelector('.all-courses__filter-tab:hover') && !firstToggle && e.type !== 'click') return 367 firstToggle = false 368 filterSubjectWrap.removeEventListener('scroll', wrapScrollHandler, { passive: true }) 369 const oldTab = filterSubjectWrap.querySelector('.all-courses__filter-tab.active') 370 if (oldTab) oldTab.classList.remove('active') 371 372 that.classList.add('active') 373 filterHeadline.innerHTML = that.getAttribute('data-text') 374 375 subjectsBoxes.forEach((subjectsBox) => { 376 subjectsBox.classList.add('hide') 377 }) 378 379 const index = that.getAttribute('data-index') 380 const activeSubjectsBox = list.querySelector('[data-index="' + index + '"]') 381 activeSubjectsBox.classList.remove('hide') 382 383 filterSubjectWrap.scrollTop = activeSubjectsBox.offsetTop - 90 - 60 384 385 tabsParent.scrollLeft = that.offsetLeft - tabsParent.clientWidth/2 + that.clientWidth/2 386 setTimeout(() => filterSubjectWrap.addEventListener('scroll', wrapScrollHandler, { passive: true }), 200) 387 } 388 } 389 390 tabs[0]?.click() 391 } 392 393 394 findBtn.addEventListener('click', findHandler) 395 396 function findHandler () { 397 let valid = true 398 for (let i = 0; i < openers.length; i++) { 399 const wrap = openers[i].nextElementSibling 400 const itemChecked = wrap.querySelector(["input:checked"]) 401 if (!itemChecked) valid = false 402 } 403 404 if (valid) { 405 makeFiltration() 406 } 407 } 408 409 410 for (let i = 0; i < openers.length; i++) { 411 openers[i].addEventListener("click", (e)=> openFilter(openers[i], e)) 412 413 const wrap = openers[i].nextElementSibling 414 415 const closeBtn = wrap.querySelector('.all-courses__filter-close') 416 if (closeBtn) closeBtn.addEventListener('click', () => closeFilter(openers[i])) 417 418 const filterTopReset = openers[i].parentElement.querySelector('.all-courses__filter-top-reset') 419 if (filterTopReset) filterTopReset.addEventListener('click', () => resetFilter(openers[i])) 420 421 const items = wrap.querySelectorAll("[data-element='all-courses-filter-input']") 422 items.forEach((item) => { 423 item.addEventListener('change', () => updateFilter(openers[i], wrap)) 424 }) 425 426 const informerButtons = wrap.querySelectorAll('.all-courses__filter-informer-button') 427 informerButtons.forEach(informerButton => { 428 informerButton.addEventListener('click', function () { 429 const input = this.closest('.all-courses__filter-box')?.querySelector("[data-element='all-courses-filter-input']") 430 if (input) { 431 input.checked = true 432 updateFilter(openers[i], wrap) 433 } 434 }) 435 }) 436 437 438 const resetFilterBtn = wrap.querySelector('.all-courses__reset-filter') 439 if (resetFilterBtn) resetFilterBtn.addEventListener('click', () => resetFilter(openers[i])) 440 } 441 442 function openFilter (opener, e) { 443 e.stopPropagation() 444 if (opener.classList.contains('active')) { 445 closeFilter(opener) 446 } else { 447 const oldOpen = allCourses.querySelector(".all-courses__filter-top.active") 448 if (oldOpen) oldOpen.classList.remove('active') 449 closeSelectFilter() 450 opener.classList.add('active') 451 452 const filter = opener.parentElement 453 const oldFilter = allCourses.querySelector(".all-courses__filter.open") 454 if (oldFilter) oldFilter.classList.remove('open') 455 if (filter) filter.classList.add('open') 456 } 457 hideHeader() 458 } 459 460 function closeSelectFilter () { 461 const oldSelectFilterOpen = document.querySelector(".select-filter.active") 462 if (oldSelectFilterOpen) { 463 oldSelectFilterOpen.classList.remove('active') 464 oldSelectFilterOpen.querySelector('.select-filter__top').classList.remove('active') 465 } 466 } 467 468 469 checkResetFilterTop(grades?.nextElementSibling) 470 checkResetFilterTop(grades?.nextElementSibling) 471 checkResetFilterTop(tags?.nextElementSibling) 472 473 function checkResetFilterTop (wrap) { 474 const resetFilterTop = wrap?.parentElement.querySelector('.all-courses__filter-top-reset') 475 const item = wrap?.querySelector(["input:checked"]) 476 if (item) { 477 if (resetFilterTop) resetFilterTop.classList.add('active') 478 } 479 } 480 481 function sortFilterFields() { 482 const getParsedData = (element, attribute) => { 483 if (!element) return [] 484 try { 485 const data = element.getAttribute(attribute) 486 return data ? JSON.parse(data) : [] 487 } catch (e) { 488 console.error(`ÐÑибка паÑÑинга JSON в аÑÑибÑÑе ${attribute}:`, e) 489 return [] 490 } 491 } 492 493 const filterBlockInputs = (blockElement, allowedValues, hasActiveFilters) => { 494 const inputs = blockElement.nextElementSibling.querySelectorAll('input') 495 const allowedStrings = allowedValues.map(String) 496 497
498 inputs.forEach(input => { 499 const parent = input.closest('.all-courses__filter-item') 500 if (!parent) return 501 502 const dataItemId = input.getAttribute('data-item-id') 503 const inputValues = dataItemId ? [dataItemId] : input.value.split('|') 504 505 const isAllowed = inputValues.some(val => allowedStrings.includes(val)) 506 const isForbidden = hasActiveFilters && !isAllowed 507 508 parent.classList.toggle('disabled', isForbidden) 509 }) 510 } 511 512 function calculateSubjects () { 513 const boxes = subjects.nextElementSibling.querySelectorAll('.all-courses__filter-box') 514 boxes.forEach(box => { 515 const notForbiddenInputs = box.querySelectorAll('.all-courses__filter-item:not(.disabled)') 516 const tab = subjects.nextElementSibling.querySelector(`.all-courses__filter-tab[data-index='${box.getAttribute('data-index') || ''}']`) 517 if (tab.querySelector('span')) tab.querySelector('span').innerHTML = notForbiddenInputs.length.toString() 518 if (notForbiddenInputs.length === 0) { 519 tab.style.display = 'none' 520 box.style.display = 'none' 521 box.previousElementSibling.style.display = 'none' 522 } else { 523 tab.style.display = '' 524 box.style.display = '' 525 box.previousElementSibling.style.display = '' 526 } 527 }) 528 const tabs = filterSubjectWrap.querySelectorAll('.all-courses__filter-tab') 529 const tabsActive = Array.from(tabs).filter(tab => tab.style.display !== 'none') 530 if (tabsActive.length === 1) { 531 tabsActive[0].click() 532 tabsActive[0].style.display === 'none' 533 filterSubjectWrap.classList.add('all-courses__filter-wrap_hide-tabs') 534 } else if (tabsActive.length > 0) { 535 tabsActive[0].click() 536 filterSubjectWrap.classList.remove('all-courses__filter-wrap_hide-tabs') 537 } else { 538 if (filterHeadline) filterHeadline.innerHTML = '' 539 } 540 } 541 542 function getResultArray (array_1, array_2) { 543 if (array_1.length === 0) return array_2 544 if (array_2.length === 0) return array_1 545 return array_1.filter(item => array_2.includes(item)) 546 } 547 548 const checkedGrade = grades.nextElementSibling.querySelector('input:checked') 549 const checkedSubject = subjects.nextElementSibling.querySelector('input:checked') 550 const checkedTag = tags.nextElementSibling.querySelector('input:checked') 551 552 const hasGrade = !!checkedGrade 553 const hasSubject = !!checkedSubject 554 const hasTag = !!checkedTag 555 556 const grades_1 = getParsedData(checkedSubject, 'data-grades') 557 const grades_2 = getParsedData(checkedTag, 'data-grades') 558 const allowedGrades = getResultArray(grades_1, grades_2) 559 560 const subjects_1 = getParsedData(checkedGrade, 'data-subjects') 561 const subjects_2 = getParsedData(checkedTag, 'data-subjects') 562 const allowedSubjects = getResultArray(subjects_1, subjects_2) 563 564 const tags_1 = getParsedData(checkedGrade, 'data-tags') 565 const tags_2 = getParsedData(checkedSubject, 'data-tags') 566 const allowedTags = getResultArray(tags_1, tags_2) 567 568 filterBlockInputs(grades, allowedGrades, hasSubject || hasTag) 569 filterBlockInputs(subjects, allowedSubjects, hasGrade || hasTag) 570 filterBlockInputs(tags, allowedTags, hasGrade || hasSubject) 571 calculateSubjects() 572 } 573 574 575 async function updateFilter (opener, wrap, noScroll, noFiltration) { 576 if(opener.getAttribute('data-ftype') === 'class_select' || opener.getAttribute('data-ftype') === 'class_tags') { 577 //filterSubjectsList.innerHTML = "<div class='tile-loader-box'><div class='tile-loader'></div></div>"; 578 if (!noFiltration) makeFiltration() 579 580 // updateFilter(openers[1], openers[1].nextElementSibling, true) 581 } else { 582 if (!noFiltration) makeFiltration() 583 } 584 opener.innerHTML = `<div class='all-courses__filter-top-text'>${opener.getAttribute('data-default-text')}</div>` 585 const resetFilterBtn = wrap.querySelector('.all-courses__reset-filter') 586 const resetFilterTop = wrap.parentElement.querySelector('.all-courses__filter-top-reset') 587 const item = wrap.querySelector(["input:checked"]) 588 if (item) { 589 opener.innerHTML = '' 590 span = document.createElement('span') 591 span.innerHTML = item.nextElementSibling.innerHTML 592 opener.append(span) 593 if (resetFilterBtn) resetFilterBtn.classList.add('active') 594 if (resetFilterTop) resetFilterTop.classList.add('active') 595 } else { 596 if (resetFilterBtn) resetFilterBtn.classList.remove('active') 597 if (resetFilterTop) resetFilterTop.classList.remove('active') 598 } 599 toggleReset() 600 closeFilter(opener) 601 sortFilterFields() 602 } 603 604 function toggleReset () { 605 606 const itemsAll = allCourses.querySelectorAll('input:not(.select-filter__input):checked') 607 itemsAll.filter 608 if (itemsAll.length) { 609 if (reset) reset.classList.add('active') 610 } else { 611 if (reset) reset.classList.remove('active') 612 } 613 } 614 615 window.addEventListener('click', closeAllFilters) 616 617 function closeAllFilters () { 618 if (window.innerWidth >= 744) { 619 const oldOpen = allCourses.querySelector(".all-courses__filter-top.active") 620 if (oldOpen) oldOpen.classList.remove('active') 621 showHeader() 622 } 623 } 624 625 function closeFilter (opener) { 626 opener.classList.remove('active') 627 const filter = opener.parentElement 628 if (filter) filter.classList.remove('open') 629 showHeader() 630 } 631 632 async function makeFiltration (p_paginate = 1, isReset = false) { 633 if(p_paginate === 1 ){ 634 $('.filtered_elements').html("<div class='tile-loader'></div>"); 635 $('.more_b').html(""); 636 } 637 clearTimeout(timerReload) 638 timerReload = setTimeout(() => window.location.reload(), 700000) 639 const grades_wrap = grades.nextElementSibling 640 const grades_items = grades_wrap.querySelectorAll(["input:checked"]) 641 let grades_result = '' 642 let grade_first = 0 643 let grade_item = '' 644 let grade_h1_part= ''
645 grades_items.forEach((item, i) => { 646 if (i > 0) grades_result += '|' 647 if (grade_first == 0) grade_first = item.value 648 if (grade_item === '') grade_item = item.getAttribute('data-item') 649 if (grade_h1_part === '') grade_h1_part = item.getAttribute('data-hname') 650 grades_result += item.value 651 }) 652 let subjects_result = '' 653 let subject_first = 0 654 let subject_item = '' 655 let subject_h1_part= '' 656 try{ 657 const subjects_wrap = subjects.nextElementSibling 658 const subjects_items = subjects_wrap.querySelectorAll(["input:checked"]) 659 subjects_items.forEach((item, i) => { 660 if (i > 0) subjects_result += '|' 661 if (subject_first == 0) subject_first = item.value 662 if (subject_item === '') subject_item = item.getAttribute('data-item') 663 if (subject_h1_part === '') subject_h1_part = item.getAttribute('data-hname') 664 subjects_result += item.value 665 }) 666 }catch(e){} 667 let tags_result = '' 668 let tag_first = 0 669 let tag_item = '' 670 let tag_h1_part= '' 671 try{ 672 const tags_wrap = tags.nextElementSibling 673 const tags_items = tags_wrap.querySelectorAll(["input:checked"]) 674 tags_items.forEach((item, i) => { 675 if (i > 0) tags_result += '|' 676 if (tag_first == 0) tag_first = item.value 677 if (tag_item === '') tag_item = item.getAttribute('data-item') 678 if (tag_h1_part === '') tag_h1_part = item.getAttribute('data-hname') 679 tags_result += item.value 680 }) 681 }catch(e){} 682 let utm_f = allCourses.getAttribute('data-utm'); 683 if(utm_f != null && utm_f != '' && utm_f != undefined){ 684 }else{ 685 utm_f = '' 686 } 687 let promo_f = ''; 688 let promo_f_param = ''; 689 let promo_ = allCourses.getAttribute('data-promo'); 690 if(promo_ != null && promo_ != '' && promo_ != undefined){ 691 promo_f = promo_; 692 promo_f_param = '?promo='+promo_f; 693 } 694 if(grade_item === '' && grade_h1_part === ''){ 695 grades_result = 'all' 696 } 697 if(subject_item === '' && subject_h1_part === ''){ 698 subjects_result = 'all' 699 //tags_result = '' 700 } 701 let summerny = '' 702 if (filterSumr?.checked) { 703 summerny = filterSumr.getAttribute('data-value') 704 } else if (filterNewy?.checked) { 705 summerny = filterNewy.getAttribute('data-value') 706 } 707 708 var obData = { 709 'grade': grades_result, 710 'subject': subjects_result, 711 'tag': tags_result, 712 'utm_t': utm_f, 713 'promo': promo_f, 714 'pagePaginate': p_paginate, 715 'summerny': summerny, 716 }; 717 // console.log(obData); 718 $.request('FilterCourseFunctions::onPaginateAllCourses', { 719 data: obData 720 }) 721 // let url = new URL(window.location.href) 722 let url = urlFilter 723 // let useFilterReplaceState = false 724 // if (grade_first > 0){ 725 // url.searchParams.set('gr', grade_first); 726 // useFilterReplaceState = true 727 // } 728 // if (subject_first > 0){ 729 // url.searchParams.set('subject', subject_first); 730 // useFilterReplaceState = true 731 // } 732 // if (tag_first > 0){ 733 // url.searchParams.set('tag', tag_first); 734 // useFilterReplaceState = true 735 // } 736 // if (useFilterReplaceState === true) history.replaceState(null, "", url.toString()) 737 if (subject_item !== "") { 738 url = url + '/' + subject_item 739 } 740 if (grade_item !== "") { 741 if (subject_item !== "") { 742 }else{ 743 url = url + '/all' 744 } 745 url = url + '/' + grade_item 746 } 747 if (tag_item !== "") { 748 if (grade_item !== "") { 749 }else{ 750 if (subject_item !== "") { 751 }else{ 752 url = url + '/all' 753 } 754 url = url + '/all' 755 } 756 url = url + '/' + tag_item 757 } 758 url = url + utm_f 759 history.replaceState(null, "", url.toString()) 760 let new_h1 = h1Filter 761 let new_title = metaNameFilter 762 let new_description = metaDescriptionFilter 763 764 765 766 new_h1 = 'ÐÑÑÑÑ' 767 768 const tagPurposeChecked = allCourses.querySelector('.all-courses__filter_purpose input:checked') 769 let special 770 if (tagPurposeChecked) special = tagPurposeChecked.getAttribute('data-special') === "special" 771 772 const grCollegeChecked = allCourses.querySelector('.all-courses__filter-item_college input
772:checked') 773 let specialcollege 774 if (grCollegeChecked) specialcollege = grCollegeChecked.getAttribute('data-special-college') === "specialcollege" 775 776 if(special){ 777 new_h1 = 'Семейное онлайн-обÑÑение' 778 } 779 if (subject_h1_part !== "" && !special) { 780 if (subject_h1_part === "ÑÐµÐ¼ÐµÐ¹Ð½Ð¾Ð¼Ñ Ð¾Ð±ÑÑениÑ") { 781 new_h1 = 'Семейное обÑÑение' 782 }else{ 783 new_h1 = new_h1 + ' по '+ subject_h1_part 784 } 785 }else{ 786 } 787 if (grade_h1_part !== "") { 788 new_h1 = new_h1 + ' Ð´Ð»Ñ ' + grade_h1_part 789 }else{ 790 } 791 if(specialcollege){ 792 new_h1 = 'ÐапÑавлениÑ' 793 new_h1 = new_h1 + ' ' + grade_h1_part 794 if (subject_h1_part !== "" && !special) { 795 if (subject_h1_part === "ÑÐµÐ¼ÐµÐ¹Ð½Ð¾Ð¼Ñ Ð¾Ð±ÑÑениÑ") { 796 new_h1 = 'Семейное обÑÑение' 797 }else{ 798 new_h1 = new_h1 + ' по '+ subject_h1_part 799 } 800 }else{ 801 } 802 } 803 if (tag_h1_part !== "") { 804 new_h1 = new_h1 + ', ÑÑÐ¾Ð±Ñ ' + tag_h1_part 805 } 806 if (new_h1 === 'ÐÑÑÑÑ' || new_h1 === 'Семейное онлайн-обÑÑение' || new_h1 === 'ÐапÑавлениÑ'){ 807 new_h1 = h1Filter 808 } 809 810 811 if(special){ 812 new_title = new_h1 + ' в «ТоÑке Ðнаний»' 813 new_description = new_h1 + ' в «ТоÑке Ðнаний». âï¸ ÐнÑеÑеÑнÑе и понÑÑнÑе онлайн-занÑÑÐ¸Ñ Ñ Ð¿ÑеподаваÑелÑми. âï¸ ÐеÑÑоналÑнÑй ÑÑÑÑоÑ. âï¸ ÐодгоÑовка к ÐÐÐ, ÐÐРи ÐÐÐ . âï¸ Ð£ÑиÑеÑÑ Ð² Ñдобном Ñемпе, вÑе кÑÑÑÑ Ð´Ð¾ÑÑÑÐ¿Ð½Ñ Ð² запиÑи!' 814 }else{ 815 new_title = new_h1 + ' в онлайн-Ñколе «ТоÑка Ðнаний»' 816 new_description = new_h1 + ' в онлайн-Ñколе «ТоÑка Ðнаний». âï¸ ÐнÑеÑеÑнÑе и понÑÑнÑе онлайн-занÑÑÐ¸Ñ Ñ Ð¿ÑеподаваÑелÑми. âï¸ ÐеÑÑоналÑнÑй ÑÑÑÑоÑ. âï¸ ÐодгоÑовка к ÐÐÐ, ÐÐРи ÐÐÐ . âï¸ Ð£ÑиÑеÑÑ Ð² Ñдобном Ñемпе, вÑе кÑÑÑÑ Ð´Ð¾ÑÑÑÐ¿Ð½Ñ Ð² запиÑи!' 817 } 818 819 820 821 822 if (isReset) { 823 filterh1block.innerHTML = new_h1 + `<svg viewBox="0 0 42 42" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="21" cy="21" r="21" fill="#6683C2" fill-opacity="0.24"></circle><path d="M20.25 29C20.25 29.4142 20.5858 29.75 21 29.75C21.4142 29.75 21.75 29.4142 21.75 29L21 29L20.25 29ZM21.5303 12.4697C21.2374 12.1768 20.7626 12.1768 20.4697 12.4697L15.6967 17.2426C15.4038 17.5355 15.4038 18.0104 15.6967 18.3033C15.9896 18.5962 16.4645 18.5962 16.7574 18.3033L21 14.0607L25.2426 18.3033C25.5355 18.5962 26.0104 18.5962 26.3033 18.3033C26.5962 18.0104 26.5962 17.5355 26.3033 17.2426L21.5303 12.4697ZM21 29L21.75 29L21.75 13L21 13L20.25 13L20.25 29L21 29Z" fill="#003C56"></path></svg>` 824 } else { 825 filterh1block.textContent = new_h1 826 } 827 828 document.title = new_title 829 const meta= document.getElementsByTagName("meta") 830 for (let i= 0; i < meta.length; i++) { 831 if (meta[i].name.toLowerCase() === "description") { 832 meta[i].content = new_description 833 } 834 } 835 836 // updateBodyDataParams(grades_result, subjects_result, tags_result) 837 updateBodyDataParams(grade_item, subject_item, tag_item) 838 if (p_paginate <= 1) { 839 allCourses.setAttribute('data-action', 'filter_apply') 840 sendCommonAnalytics('element_click', allCourses) 841 } 842 } 843 844 function showHeader () { 845 stickyHeader.classList.remove('hide') 846 body.classList.remove('no-scroll') 847 wrap.classList.remove('active') 848 } 849 function hideHeader () { 850 if (window.innerWidth < 744) { 851 stickyHeader.classList.add('hide') 852 body.classList.add('no-scroll') 853 wrap.classList.add('active') 854 } 855 856 } 857 858 setTimeout(() => sortFilterFields(), 200) 859 } 860 861 862const ymAsync = (id, goal, params) => new Promise(resolve => { 863 if (typeof ym !== 'function') return resolve() 864 865 const timeout = setTimeout(resolve, 500) 866 867 try { 868 ym(id, 'reachGoal', goal, params, () => { 869 clearTimeout(timeout) 870 resolve() 871 }) 872 } catch { 873 clearTimeout(timeout) 874 resolve() 875 } 876}) 877 878const gtagAsync = (goal, params) => new Promise(resolve => { 879 if (typeof gtag !== 'function') return resolve() 880 881 const timeout = setTimeout(resolve, 500) 882 883 try { 884 gtag('event', goal, { 885 ...params, 886 event_callback: () => { 887 clearTimeout(timeout) 888 resolve() 889 }, 890 }) 891 } catch { 892 clearTimeout(timeout) 893 resolve() 894 } 895}) 896 897const mailruAsync = (goal, isSessionStorageSave = false) => new Promise(resolve => { 898 const key = `mailru_goal_${goal}` 899 900 if (isSessionStorageSave) { 901 try { 902 if (sessionStorage.getItem(key)) { 903 resolve() 904 return 905 } 906 } catch { 907 } 908 } 909 910 if (!window._tmr || typeof window._tmr.push !== 'function') { 911 resolve() 912 return 913 } 914 915 let settled = false 916 917 const finish = (sent = false) => { 918 if (settled) return 919 920 settled = true 921 clearTimeout(timeout) 922
923 if (sent && isSessionStorageSave) { 924 try { 925 sessionStorage.setItem(key, '1') 926 } catch { 927 } 928 } 929 930 resolve() 931 } 932 933 const timeout = setTimeout(() => { 934 finish(false) 935 }, 1000) 936 937 try { 938 window._tmr.push({ 939 type: 'onready', 940 callback: () => { 941 if (settled) return 942 943 try { 944 window._tmr.reachGoal({ 945 id: 3515465, 946 goal, 947 }) 948 949 finish(true) 950 } catch { 951 finish(false) 952 } 953 }, 954 }) 955 } catch { 956 finish(false) 957 } 958}) 959 960const analytics = { 961 ym(goal, params) { 962 return ymAsync(97240877, goal, params) 963 }, 964 965 gtag(goal, params) { 966 return gtagAsync(goal, params) 967 }, 968 969 mailru(goal, isSessionStorageSave = false) { 970 return mailruAsync(goal, isSessionStorageSave) 971 }, 972 973 reachGoal(goal, params) { 974 return Promise.allSettled([ 975 ymAsync(97240877, goal, params), 976 gtagAsync(goal, params), 977 ]) 978 }, 979} 980 981const animateCounters = document.querySelectorAll('.animate-counter') 982 983if (animateCounters.length) animateCountersInit() 984 985function animateCountersInit () { 986 const observer = new IntersectionObserver((entries) => { 987 entries.forEach(entry => { 988 if (entry.isIntersecting) { 989 animateCounter(entry.target, 0, entry.target.getAttribute('data-animate-counter-end'), 1000) 990 observer.unobserve(entry.target) 991 } 992 }) 993 }, { 994 root: null, 995 scrollMargin : "0px 0px -150px 0px", 996 threshold: 1 997 }) 998 999 for (let i = 0; i < animateCounters.length; i++) { 1000 animateCounterInit(animateCounters[i]) 1001 } 1002 1003 function animateCounterInit (counter) { 1004 observer.observe(counter) 1005 } 1006 1007 function animateCounter(element, startValue, endValue, duration) { 1008 let currentValue = startValue 1009 const increment = (endValue - startValue) / (duration / 10) 1010 const toFixed = element.getAttribute('data-to-fixed') 1011 const counterInterval = setInterval(() => { 1012 currentValue += increment; 1013 if ((increment > 0 && currentValue >= endValue) || (increment < 0 && currentValue <= endValue)) { 1014 currentValue = endValue 1015 clearInterval(counterInterval) 1016 } 1017 element.textContent = (+currentValue).toFixed(toFixed).toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ") 1018 }, 10) 1019 } 1020} 1021 1022const animationsOnScroll = document.querySelectorAll('[data-animate-on-scroll]') 1023 1024if (animationsOnScroll.length) animationsOnScrollInit() 1025 1026function animationsOnScrollInit () { 1027 gsap.registerPlugin(ScrollTrigger) 1028 1029 for (let i = 0; i < animationsOnScroll.length; i++) { 1030 initGsapScrollTrigger(animationsOnScroll[i]) 1031 } 1032 1033 function initGsapScrollTrigger (node) { 1034 if (node.classList.contains('langs-cap__decor-box')) { 1035 gsap.to(node, { 1036 scrollTrigger: { 1037 trigger: node, 1038 start: "top 95%", 1039 onEnter: () => node.classList.add("active") 1040 } 1041 }) 1042 } else { 1043 gsap.to(node, { 1044 scrollTrigger: { 1045 trigger: node, 1046 start: "top 80%", 1047 onEnter: () => node.classList.add("active") 1048 } 1049 }) 1050 } 1051 } 1052} 1053 1054 1055const articleBottomShareBtns = document.querySelectorAll('.article-bottom__share-btn') 1056 1057articleBottomShareBtns.forEach(shareBtn => { 1058 shareBtn.addEventListener('click', function(event) { 1059 const isMobile = window.matchMedia("(pointer: coarse)").matches || /Android|iPhone|iPad|iPod/i.test(navigator.userAgent); 1060 1061 const shareUrl = this.getAttribute('data-url') 1062 if (!shareUrl) return 1063 1064 if (navigator.share && isMobile) { 1065 event.preventDefault() 1066 1067 navigator.share({ 1068 url: shareUrl, 1069 }) 1070 .then() 1071 .catch((error) => console.log('ÐÑибка ÑеÑинга:', error)) 1072 } else { 1073 const type = this.getAttribute('data-share-type') 1074 let baseUrl = '' 1075 switch (type) { 1076 case 'vk': 1077 baseUrl = 'https://vk.com/share.php?url=' 1078 break; 1079 case 'tg': 1080 baseUrl = 'https://t.me/share/url?url=' 1081 break; 1082 case 'max': 1083 baseUrl = 'https://max.ru/:share?text=' 1084 break; 1085 } 1086 const finalUrl = `${baseUrl}${encodeURIComponent(shareUrl)}` 1087 const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent) 1088 if (type === 'max' && !isSafari) { 1089 const shareWindow = window.open(`max://share?text=${encodeURIComponent(shareUrl)}`, '_blank') 1090 1091 setTimeout(() => { 1092 try { 1093 if (shareWindow && !shareWindow.closed) { 1094 shareWindow.location.href = finalUrl 1095 } 1096 } catch (e) { 1097 window.open(`https://max.ru{encodedUrl}`, '_blank') 1098 } 1099 }, 500) 1100 } else { 1101 window.open(finalUrl, '_blank') 1102 } 1103 } 1104 }) 1105}) 1106 1107 1108 1109const articleVideoBoxArray = document.querySelectorAll("[data-element='article__video-box']") 1110 1111if (articleVideoBoxArray.length) articleVideoBoxArrayInit() 1112 1113function articleVideoBoxArrayInit () { 1114 for (let i = 0; i < articleVideoBoxArray.length; i++) { 1115 articleVideoBoxArray[i].addEventListener('click', () => articleVideoBoxInit(articleVideoBoxArray[i]), { once: true }) 1116 } 1117 1118 function articleVideoBoxInit (box) { 1119 const video = box.querySelector('video') 1120 video.controls = true 1121 box.classList.add('active') 1122 } 1123} 1124 1125const blogList = document.querySelector('.blog__list') 1126 1127if (blogList) blogListInit() 1128 1129function blogListInit () { 1130 const config = { attributes: false, childList: true, characterData: true, subtree: true } 1131 const observer = new MutationObserver(function observerCallback(mutations) { 1132 mutations.forEach( 1133 (mutation) => { 1134 if (mutation.addedNodes.length) {
1135 mutation.addedNodes.forEach((node) => { 1136 if (node?.classList?.contains('blog__item')) { 1137 initCommonAnalytics(node) 1138 } 1139 }) 1140 } 1141 }) 1142 }) 1143 1144 observer.observe(blogList, config) 1145} 1146 1147const btnFixed = document.querySelector('[data-element="btn-fixed"]') 1148 1149 if (btnFixed) btnFixedInit() 1150 1151 function btnFixedInit () { 1152 const start = btnFixed.getAttribute('data-btn-fixed-start') || 0 1153 const end = btnFixed.getAttribute('data-btn-fixed-end') || 0 1154 const body = document.getElementsByTagName('body')[0] 1155 const promo = document.querySelector('.promo') 1156 window.addEventListener('scroll', checkBtnFixed, { passive: true }) 1157 1158 function checkBtnFixed () { 1159 const cake = document.querySelector('.cake.cake_active') 1160 if (window.scrollY > start && body.scrollHeight - window.pageYOffset > end && !checkBtnFixedHide()) { 1161 btnFixed.classList.add('active') 1162 if (cake) btnFixed.classList.add('active-with-cake-offset') 1163 if (promo) { 1164 promo.classList.add('transition') 1165 promo.classList.remove('transition-with-cake') 1166 } 1167 if (promo && cake) promo.classList.add('transition-with-cake-offset') 1168 } else { 1169 btnFixed.classList.remove('active') 1170 btnFixed.classList.remove('active-with-cake-offset') 1171 if (promo) promo.classList.remove('transition') 1172 if (promo && cake) { 1173 promo.classList.remove('transition-with-cake-offset') 1174 promo.classList.add('transition-with-cake') 1175 } 1176 } 1177 } 1178 1179 const sectionsWhenBtnHide = document.querySelectorAll('[data-btn-fixed-hide="true"]') 1180 1181 function checkBtnFixedHide () { 1182 let isHide = false 1183 for (let i = 0; i < sectionsWhenBtnHide.length; i++) { 1184 if (elementInViewport(sectionsWhenBtnHide[i])) isHide = true 1185 } 1186 return isHide 1187 } 1188 1189 function elementInViewport(el) { 1190 let top = el.offsetTop 1191 let left = el.offsetLeft 1192 let width = el.offsetWidth 1193 let height = el.offsetHeight 1194 1195 while(el.offsetParent) { 1196 el = el.offsetParent 1197 top += el.offsetTop 1198 left += el.offsetLeft 1199 } 1200 1201 return ( 1202 top < (window.pageYOffset + window.innerHeight) && 1203 left < (window.pageXOffset + window.innerWidth) && 1204 (top + height) > window.pageYOffset && 1205 (left + width) > window.pageXOffset 1206 ) 1207 } 1208 } 1209 1210const btnScrollToTop = document.querySelector('.btn-scroll-to-top') 1211 1212if (btnScrollToTop) btnScrollToTopInit() 1213 1214function btnScrollToTopInit () { 1215 const promo = document.querySelector('.promo') 1216 1217 if (btnScrollToTop) { 1218 btnScrollToTop.addEventListener('click', () => window.scrollTo({ top: 0, behavior: 'smooth' })) 1219 if (promo) btnScrollToTop.classList.add('active-promo') 1220 window.addEventListener('scroll', toggleAllCoursesTop, { passive: true }) 1221 1222 function toggleAllCoursesTop () { 1223 if (window.scrollY > 0) { 1224 btnScrollToTop.classList.add('active') 1225 } else { 1226 btnScrollToTop.classList.remove('active') 1227 } 1228 } 1229 } 1230} 1231 1232const cake = document.querySelector('.cake') 1233 1234if (cake) checkCake() 1235 1236function checkCake() { 1237 const cakeButton = cake.querySelector('.cake__button') 1238 const btnScrollToTop = document.querySelector('.btn-scroll-to-top') 1239 if (!getCookie('cakes_policy')) { 1240 cake.classList.add('cake_active') 1241 if (btnScrollToTop) btnScrollToTop.classList.add('active-cake') 1242 1243 cakeButton.addEventListener('click', function () { 1244 setCake('cakes_policy', 'true', 365) 1245 cake.classList.remove('cake_active') 1246 const btnFixed = document.querySelector('[data-element="btn-fixed"]') 1247 const promo = document.querySelector('.promo') 1248 if (promo) { 1249 promo.classList.remove('transition-with-cake') 1250 promo.classList.remove('transition-with-cake-offset') 1251 } 1252 if (btnFixed) btnFixed.classList.remove('active-with-cake-offset') 1253 if (btnScrollToTop) btnScrollToTop.classList.remove('active-cake') 1254 }) 1255 const footer = document.querySelector('footer') 1256 if (footer) window.addEventListener('scroll', () => switchCake(footer), { passive: true }) 1257 } 1258} 1259 1260function switchCake (footer) { 1261 const scrollHeight = document.documentElement.scrollHeight 1262 const currentScroll = window.scrollY 1263 const clientHeight = document.documentElement.clientHeight 1264 1265 const distanceToBottom = scrollHeight - (currentScroll + clientHeight); 1266 if (distanceToBottom < footer.clientHeight) { 1267 cake.classList.add('hide') 1268 } else { 1269 cake.classList.remove('hide') 1270 } 1271} 1272 1273 1274function setCake(name, value, days) { 1275 let expires = "" 1276 if (days) { 1277 let date = new Date() 1278 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)) 1279 expires = "; expires=" + date.toUTCString() 1280 } 1281 document.cookie = name + "=" + (value || "") + expires + "; path=/" 1282} 1283 1284function setViewportProperty() {
1285 let vh = window.innerHeight * 0.01 1286 document.documentElement.style.setProperty('--vh', `${vh}px`) 1287 } 1288 1289 window.addEventListener('resize', setViewportProperty) 1290 1291 setViewportProperty() 1292 1293const cards = document.querySelector("[data-element='cards']") 1294 1295if (cards) cardsInit() 1296 1297function cardsInit () { 1298 const cardsBoxes = cards.querySelectorAll("[data-element='cards-box']") 1299 1300 cardsBoxes.forEach((box) => { 1301 box.addEventListener('click', toggleBox) 1302 }) 1303 1304 function toggleBox () { 1305 const oldActive = cards.querySelector('.active') 1306 if (oldActive) oldActive.classList.remove('active') 1307 this.classList.add('active') 1308 } 1309} 1310 1311const catalogAchievementsSlider = document.querySelector(".catalog-achievements__slider") 1312 1313if (catalogAchievementsSlider) catalogAchievementsSliderInit() 1314 1315function catalogAchievementsSliderInit () { 1316 const pointer = document.querySelector(".catalog-achievements__pointer") 1317 const slider = new Swiper(catalogAchievementsSlider, { 1318 mousewheel: { forceToAxis: true }, 1319 slidesPerView: 'auto', 1320 spaceBetween: 20, 1321 a11y: false, 1322 navigation: { 1323 nextEl: '.catalog-achievements__btn_next', 1324 prevEl: '.catalog-achievements__btn_prev', 1325 }, 1326 scrollbar: { 1327 el: '.catalog-achievements__scrollbar', 1328 draggable: true, 1329 }, 1330 }) 1331 1332 slider.on('slideChange', function () { 1333 if (pointer) pointer.style.display = 'none' 1334 }) 1335} 1336 1337const catalogTile = document.querySelector(".catalog-tile") 1338 1339if (catalogTile) catalogTileInit() 1340 1341function catalogTileInit () { 1342 const catalogTileFilterTops = catalogTile.querySelectorAll(".catalog-tile__filter-top") 1343 const filterSubject = catalogTile.querySelector(".catalog-tile__filter_subject") 1344 const stickyHeader = document.querySelector('.sticky-header') 1345 const body = document.querySelector('body') 1346 const filterSumr = catalogTile.querySelector('[data-role="filter-sumr"]') 1347 const filterNewy = catalogTile.querySelector('[data-role="filter-newy"]') 1348 const filterSubjectWrap = catalogTile.querySelector(".catalog-tile__filter-wrap") 1349 const filterHeadline = filterSubjectWrap.querySelector('.catalog-tile__filter-headline.desk') 1350 1351 1352 filterSumr?.addEventListener('change', () => makeFiltration(1)) 1353 filterNewy?.addEventListener('change', () => makeFiltration(1)) 1354 1355 1356 catalogTileFilterTops[0].addEventListener("click", (e)=> openFilter(catalogTileFilterTops[0], e)) 1357 1358 document.addEventListener('click', function () { 1359 catalogTileFilterTops[0].classList.remove('active') 1360 showHeader() 1361 }) 1362 1363 function openFilter (opener, e) { 1364 e.stopPropagation() 1365 if (opener.classList.contains('active')) { 1366 opener.classList.remove('active') 1367 showHeader() 1368 opener.parentElement.classList.remove('active') 1369 } else { 1370 opener.classList.add('active') 1371 opener.parentElement.classList.add('active') 1372 hideHeader() 1373 } 1374 } 1375 1376 function showHeader () { 1377 stickyHeader.classList.remove('mob-hide') 1378 body.classList.remove('no-scroll-mob') 1379 } 1380 1381 function hideHeader () { 1382 stickyHeader.classList.add('mob-hide') 1383 body.classList.add('no-scroll-mob') 1384 } 1385 1386 const config = { attributes: true, childList: true, characterData: true, subtree: true } 1387 const tile = catalogTile.querySelector('.catalog-tile__list') 1388 const subjectInputs = catalogTile.querySelectorAll('.catalog-tile__filter-input_subject') 1389 const subjectInputText = catalogTile.querySelector('.catalog-tile__filter_subject .catalog-tile__filter-top-text') 1390 1391 const observer = new MutationObserver(function observerCallback(mutations) { 1392 mutations.forEach( 1393 (mutation) => { 1394 if (mutation.addedNodes.length) { 1395 mutation.addedNodes.forEach((node) => { 1396 if (node?.classList?.contains('catalog-tile__item')) { 1397 initCommonAnalytics(node) 1398 } 1399 }) 1400 } 1401 }) 1402 moreBtnInit() 1403 }) 1404 1405 1406 1407 if (tile) observer.observe(tile, config) 1408 1409 const reset = catalogTile.querySelector('.catalog-tile__reset-filter') 1410 if (reset) reset.addEventListener('click', resetFilters) 1411 1412 function resetFilters () { 1413 const items = catalogTile.querySelectorAll("input")
1414 items.forEach((item) => { 1415 if (item.hasAttribute('data-default-garde') || item.hasAttribute('data-default-subject')) { 1416 item.checked = true 1417 }else{ 1418 item.checked = false 1419 } 1420 }) 1421 reset.style.display = 'none' 1422 subjectInputText.innerHTML = "ÐÑе пÑедмеÑÑ" 1423 makeFiltration() 1424 } 1425 1426 for (let i = 0; i < subjectInputs.length; i++) { 1427 subjectInputs[i].addEventListener('change', updateFilter) 1428 subjectInputs[i].addEventListener('change', changeSubjectInputText) 1429 } 1430 1431 function changeSubjectInputText () { 1432 subjectInputText.innerHTML = this.getAttribute('data-text') 1433 const span = document.createElement('span') 1434 span.innerHTML = this.getAttribute('data-text') 1435 subjectInputText.innerHTML = '' 1436 subjectInputText.append(span) 1437 } 1438 1439 moreBtnInit() 1440 1441 function moreBtnInit () { 1442 const moreBtn = catalogTile.querySelector('.all-courses__more-button') 1443 if (moreBtn) { 1444 const newBtn = replaceBtn(moreBtn) 1445 newBtn.addEventListener('click', () => makeFiltration(newBtn.getAttribute('data-v'))) 1446 } 1447 } 1448 1449 function replaceBtn (oldElement) { 1450 const newElement = oldElement.cloneNode(true) 1451 oldElement.parentNode.replaceChild(newElement, oldElement) 1452 return newElement 1453 } 1454 1455 1456 function updateFilter () { 1457 const itemsAll = catalogTile.querySelectorAll(["input:checked"]) 1458 if (itemsAll.length) { 1459 if (reset) reset.style.display = 'flex' 1460 } else { 1461 if (reset) reset.style.display = 'none' 1462 } 1463 makeFiltration() 1464 } 1465 1466 function makeFiltration (p_paginate = 1) { 1467 let subjects_result = '' 1468 try{ 1469 const subjects_items = catalogTile.querySelectorAll('.catalog-tile__filter-input_subject:checked') 1470 subjects_items.forEach((item, i) => { 1471 if (i > 0) subjects_result += '|' 1472 subjects_result += item.value 1473 }) 1474 }catch(e){} 1475 1476 let utm_f = tile.getAttribute('data-utm'); 1477 let promo_f = tile.getAttribute('data-promo'); 1478 1479 if(p_paginate === 1 ){ 1480 $('.filtered_elements').html("<div class='tile-loader'></div>"); 1481 $('.more_b').html(""); 1482 } 1483 1484 var obData = { 1485 'subject': subjects_result, 1486 'utm_t': utm_f, 1487 'promo': promo_f, 1488 'pagePaginate': p_paginate, 1489 'summerny': getSummerny(), 1490 }; 1491 console.log(obData); 1492 $.request('ModelUrl::onPaginateTeacher', { 1493 data: obData 1494 }) 1495 } 1496 function getSummerny () { 1497 let summerny = '' 1498 if (filterSumr?.checked) { 1499 summerny = filterSumr.getAttribute('data-value') 1500 } else if (filterNewy?.checked) { 1501 summerny = filterNewy.getAttribute('data-value') 1502 } 1503 return summerny 1504 } 1505 1506 1507 initTabs() 1508 1509 function initTabs () { 1510 const tabsParent = filterSubject.querySelector('.catalog-tile__filter-tabs') 1511 const list = filterSubjectWrap.querySelector('.catalog-tile__filter-list') 1512 const tabs = filterSubject.querySelectorAll('.catalog-tile__filter-tab') 1513 const subjectsBoxes = filterSubjectWrap.querySelectorAll('.catalog-tile__filter-box') 1514 1515 if (!tabs.length || !subjectsBoxes.length) return 1516 1517 filterSubjectWrap.addEventListener('scroll', wrapScrollHandler, { passive: true }) 1518 1519 function wrapScrollHandler () { 1520 subjectsBoxes.forEach((subjectBox) => { 1521 if (filterSubjectWrap.scrollTop >= subjectBox.offsetTop - 90 - 65) { 1522 const oldTab = filterSubjectWrap.querySelector('.catalog-tile__filter-tab.active') 1523 if (oldTab) oldTab.classList.remove('active') 1524 const index = subjectBox.getAttribute('data-index') 1525 const tab = filterSubjectWrap.querySelector('[data-index="' + index + '"]') 1526 if (tab) { 1527 tabsParent.scrollLeft = tab.offsetLeft - tabsParent.clientWidth/2 + tab.clientWidth/2 1528 tab.classList.add('active') 1529 } 1530 } 1531 }) 1532 } 1533 1534 let timeout 1535 let firstToggle = true 1536 1537
1538 tabs.forEach((tab) => { 1539 tab.addEventListener('click', changeTab) 1540 tab.addEventListener('mouseenter', changeTab) 1541 }) 1542 1543 1544 function changeTab (e) { 1545 e.stopPropagation() 1546 clearTimeout(timeout) 1547 timeout = setTimeout(() => toggle(this),100) 1548 1549 function toggle (that) { 1550 if (!that.closest('.catalog-tile__filter-wrap').querySelector('.catalog-tile__filter-tab:hover') && !firstToggle) return 1551 firstToggle = false 1552 filterSubjectWrap.removeEventListener('scroll', wrapScrollHandler, { passive: true }) 1553 const oldTab = filterSubjectWrap.querySelector('.catalog-tile__filter-tab.active') 1554 if (oldTab) oldTab.classList.remove('active') 1555 1556 1557 that.classList.add('active') 1558 filterHeadline.innerHTML = that.getAttribute('data-text') 1559 1560 subjectsBoxes.forEach((subjectsBox) => { 1561 subjectsBox.classList.add('hide') 1562 }) 1563 1564 1565 const index = that.getAttribute('data-index') 1566 const activeSubjectsBox = list.querySelector('[data-index="' + index + '"]') 1567 activeSubjectsBox.classList.remove('hide') 1568 1569 1570 filterSubjectWrap.scrollTop = activeSubjectsBox.offsetTop - 90 - 60 1571 1572 tabsParent.scrollLeft = that.offsetLeft - tabsParent.clientWidth/2 + that.clientWidth/2 1573 setTimeout(() => filterSubjectWrap.addEventListener('scroll', wrapScrollHandler, { passive: true }), 200) 1574 } 1575 } 1576 1577 setTimeout(() => tabs[0].click(),200) 1578 } 1579 1580} 1581 1582const collegeAiProfessions = document.querySelector(".college-ai-professions") 1583 1584if (collegeAiProfessions) collegeAiProfessionsInit() 1585 1586function collegeAiProfessionsInit () { 1587 const tabs = collegeAiProfessions.querySelector(".college-ai-professions__tabs") 1588 const collegeAiProfessionsTabs = collegeAiProfessions.querySelectorAll(".college-ai-professions__tab") 1589 const collegeAiProfessionsAreas = collegeAiProfessions.querySelectorAll(".college-ai-professions__area") 1590 1591 collegeAiProfessionsTabs.forEach((item, index) => { 1592 item.addEventListener('click', function () { 1593 const oldItem = collegeAiProfessions.querySelector('.college-ai-professions__tab.active') 1594 if (oldItem) oldItem.classList.remove('active') 1595 this.classList.add('active') 1596 const oldBox = collegeAiProfessions.querySelector('.college-ai-professions__area.active') 1597 if (oldBox) oldBox.classList.remove('active') 1598 collegeAiProfessionsAreas[index].classList.add('active') 1599 tabs.scrollLeft = item.offsetLeft - tabs.clientWidth/2 + item.clientWidth/2 1600 }) 1601 }) 1602} 1603 1604 1605const collegeHow = document.querySelector(".college-how") 1606 1607if (collegeHow) collegeHowInit() 1608 1609function collegeHowInit () { 1610 const togglers = collegeHow.querySelectorAll('.college-how__more') 1611 1612 togglers.forEach((toggler) => { 1613 toggler.addEventListener('click', toggleArea) 1614 }) 1615 1616 function toggleArea () { 1617 const area = this.closest('.college-how__area') 1618 if (area.classList.contains('college-how__area_full')) { 1619 area.classList.remove('college-how__area_full') 1620 this.textContent = 'ÐодÑобнее' 1621 } else { 1622 area.classList.add('college-how__area_full') 1623 this.textContent = 'СвеÑнÑÑÑ' 1624 } 1625 } 1626} 1627 1628const collegeMainDirections = document.querySelector(".college-main-directions") 1629 1630if (collegeMainDirections) collegeMainDirectionsInit() 1631 1632function collegeMainDirectionsInit () { 1633 const nav = collegeMainDirections.querySelector(".college-main-directions__nav") 1634 const collegeMainDirectionsNavItems = collegeMainDirections.querySelectorAll(".college-main-directions__nav-item") 1635 const collegeMainDirectionsBoxes = collegeMainDirections.querySelectorAll(".college-main-directions__box") 1636 1637 collegeMainDirectionsNavItems.forEach((item, index) => { 1638 item.addEventListener('click', function () { 1639 const oldItem = collegeMainDirections.querySelector('.college-main-directions__nav-item.active') 1640 if (oldItem) oldItem.classList.remove('active') 1641 this.classList.add('active') 1642 const oldBox = collegeMainDirections.querySelector('.college-main-directions__box.active') 1643 if (oldBox) oldBox.classList.remove('active') 1644 collegeMainDirectionsBoxes[index].classList.add('active') 1645 nav.scrollLeft = item.offsetLeft - nav.clientWidth/2 + item.clientWidth/2 1646 }) 1647 }) 1648} 1649 1650const BLOCK_READ_THRESHOLD = 10 * 1000 1651 1652initCommonAnalytics() 1653 1654function initCommonAnalytics (container = document) { 1655 if (!container || typeof container?.querySelectorAll !== 'function') return 1656 1657 const dataActions = Array.from(container.querySelectorAll('[data-action]')) 1658 const dataBlocks = Array.from(container.querySelectorAll('[data-block]')) 1659 1660 if (container && typeof container.getAttribute === 'function') { 1661 if (container.matches('[data-action]')) dataActions.push(container) 1662 if (container.matches('[data-block]')) dataBlocks.push(container) 1663 } 1664 1665 dataActions.forEach(dataAction => { 1666 dataAction.addEventListener('click', () => { 1667 sendCommonAnalytics('element_click', dataAction) 1668 }) 1669 }) 1670 1671 if (dataBlocks.length > 0) { 1672 const states = new WeakMap() 1673 1674 dataBlocks.forEach(block => { 1675 states.set(block, { 1676 viewTimer: null, 1677 viewed: false, 1678 read: false, 1679 visible: false, 1680 visibleSince: null, 1681 readTime: 0, 1682 }) 1683 }) 1684 1685 const observer = new IntersectionObserver(entries => {
1686 entries.forEach(entry => { 1687 const block = entry.target 1688 const state = states.get(block) 1689 1690 if (!state || state.read || !block.isConnected) return 1691 1692 const vh = window.innerHeight 1693 const need = Math.min( 1694 entry.boundingClientRect.height * 0.5, 1695 vh * 0.5 1696 ) 1697 1698 const isVisible = 1699 entry.isIntersecting && 1700 entry.intersectionRect.height >= need 1701 1702 if (isVisible) { 1703 state.visible = true 1704 1705 if (!document.hidden && state.visibleSince === null) { 1706 state.visibleSince = performance.now() 1707 } 1708 1709 if (!state.viewed && !state.viewTimer) { 1710 state.viewTimer = setTimeout(() => { 1711 if (state.viewed || !block.isConnected) { 1712 state.viewTimer = null 1713 return 1714 } 1715 1716 state.viewed = true 1717 state.viewTimer = null 1718 1719 sendCommonAnalytics('block_view', block) 1720 }, 1000) 1721 } 1722 } else { 1723 state.visible = false 1724 1725 if (state.visibleSince !== null) { 1726 state.readTime += performance.now() - state.visibleSince 1727 state.visibleSince = null 1728 } 1729 1730 if (state.viewTimer) { 1731 clearTimeout(state.viewTimer) 1732 state.viewTimer = null 1733 } 1734 } 1735 }) 1736 }, { 1737 threshold: Array.from({ length: 101 }, (_, index) => index / 100) 1738 }) 1739 1740 const handleVisibilityChange = () => { 1741 const now = performance.now() 1742 1743 dataBlocks.forEach(block => { 1744 const state = states.get(block) 1745 1746 if (!state || state.read || !state.visible) return 1747 1748 if (document.hidden) { 1749 if (state.visibleSince !== null) { 1750 state.readTime += now - state.visibleSince 1751 state.visibleSince = null 1752 } 1753 } else if (block.isConnected) { 1754 state.visibleSince = now 1755 } 1756 }) 1757 } 1758 1759 document.addEventListener('visibilitychange', handleVisibilityChange) 1760 1761 const readInterval = setInterval(() => { 1762 if (document.hidden) return 1763 1764 const now = performance.now() 1765 1766 dataBlocks.forEach(block => { 1767 const state = states.get(block) 1768 1769 if (!state || state.read) return 1770 1771 if (!block.isConnected) { 1772 if (state.viewTimer) { 1773 clearTimeout(state.viewTimer) 1774 state.viewTimer = null 1775 } 1776 1777 state.visible = false 1778 state.visibleSince = null 1779 state.read = true 1780 1781 observer.unobserve(block) 1782 1783 return 1784 } 1785 1786 if (!state.visible || state.visibleSince === null) return 1787 1788 state.readTime += now - state.visibleSince 1789 state.visibleSince = now 1790 1791 if (state.readTime >= BLOCK_READ_THRESHOLD) { 1792 state.read = true 1793 1794 sendCommonAnalytics('block_read', block) 1795 1796 observer.unobserve(block) 1797 } 1798 }) 1799 1800 const allBlocksFinished = dataBlocks.every(block => { 1801 return states.get(block).read 1802 }) 1803 1804 if (allBlocksFinished) { 1805 clearInterval(readInterval) 1806 1807 document.removeEventListener( 1808 'visibilitychange', 1809 handleVisibilityChange 1810 ) 1811 1812 observer.disconnect() 1813 } 1814 }, 100) 1815 1816 dataBlocks.forEach(block => observer.observe(block)) 1817 } 1818} 1819 1820 1821const getAnalyticsParams = (goal, node) => { 1822 const pageType = node?.closest('[data-page-type]')?.getAttribute('data-page-type') || 'unknown' 1823 1824 const pageName = node.querySelector('#page_name')?.value 1825 let pageNameParsed = '' 1826 try { 1827 pageNameParsed = pageName ? new URL(pageName)?.pathname?.substring(1) : false 1828 } catch (e) { 1829 console.log(e) 1830 } 1831 1832 let block = node?.getAttribute('data-block') || node?.closest('[data-block]')?.getAttribute('data-block') || 'none' 1833 const blockIndex = node?.getAttribute('data-block-index') || node?.closest('[data-block]')?.getAttribute('data-block-index') 1834 if (block !== 'none' && blockIndex) block = block + blockIndex 1835 const action = node?.getAttribute('data-action') 1836 const form = node?.getAttribute('data-form') || pageNameParsed || 'unknown' 1837 const dataElid = node?.getAttribute('data-elid') || node?.closest('[data-elid]')?.getAttribute('data-elid') 1838 1839 const common = {
1840 ...(dataElid ? { entity_id: dataElid } : {}), 1841 filter_stage: node?.closest('[data-filter-stage]')?.getAttribute('data-filter-stage') || 'none', 1842 filter_subject: node?.closest('[data-filter-subject]')?.getAttribute('data-filter-subject') || 'none', 1843 filter_goal: node?.closest('[data-filter-goal]')?.getAttribute('data-filter-goal') || 'none', 1844 } 1845 1846 return { 1847 google: goal === 'submit_form' ? { 1848 submit_form: form, 1849 page_type: pageType, 1850 block_name: block, 1851 ...common, 1852 } : { 1853 ...(goal === 'block_view' ? { block_view: block } : {}), 1854 ...(goal === 'block_read' ? { block_read: block } : {}), 1855 ...(goal !== 'block_view' && goal !== 'block_read' ? { [goal]: action, block_name: block } : {} 1856 ), 1857 1858 ...common, 1859 page_type: pageType, 1860 }, 1861 1862 ym: goal === 'submit_form' ? { 1863 [goal]: { 1864 [pageType]: { 1865 [block] : { 1866 [form]: 1 1867 } 1868 }, 1869 }, 1870 } : { 1871 ...common, 1872 [goal]: { 1873 [pageType]: { 1874 ...(goal === 'block_view' ? { [block]: 1 } : {}), 1875 ...(goal === 'block_read' ? { [block]: 1 } : {}), 1876 ...(goal !== 'block_view' && goal !== 'block_read' ? { [block] : { [action]: 1 } } : {}), 1877 }, 1878 }, 1879 }, 1880 } 1881} 1882 1883 1884async function sendCommonAnalytics (goal, node) { 1885 const params = getAnalyticsParams(goal, node) 1886 1887 async function sendMailru () { 1888 const goalMailru = node.getAttribute('data-analytics-mailru') 1889 if (goalMailru) { 1890 await analytics.mailru(goalMailru) 1891 } 1892 } 1893 1894 1895 await Promise.all([ 1896 analytics.gtag(goal, params.google), 1897 analytics.ym(goal, params.ym), 1898 sendMailru() 1899 ]) 1900 1901} 1902 1903 1904 1905const costAreas = document.querySelectorAll('.cost__area') 1906 1907 if (costAreas.length) costAreasInit() 1908 1909 function costAreasInit () { 1910 for (let i = 0; i < costAreas.length; i++) { 1911 costAreaInit(costAreas[i]) 1912 } 1913 1914 function costAreaInit (area) { 1915 const checkbox = area.querySelector('.cost__checkbox') 1916 if (!checkbox) return 1917 1918 checkbox.addEventListener('change', changePrice) 1919 checkbox.addEventListener('change', changeHref) 1920 1921 const button = area.querySelector('.cost__button') 1922 const newHref = checkbox.getAttribute('new-href') 1923 const initialHref = button.getAttribute('href') 1924 1925 function changeHref () { 1926 const href = button.getAttribute('href') 1927 if (href === newHref) { 1928 button.setAttribute('href', initialHref) 1929 } else { 1930 button.setAttribute('href', newHref) 1931 } 1932 } 1933 1934 const price_full_old_checkbox_off = checkbox.getAttribute('data-price-full-old-checkbox-off') 1935 const price_full_old_checkbox_on = checkbox.getAttribute('data-price-full-old-checkbox-on') 1936 const price_full_current_checkbox_off = checkbox.getAttribute('data-price-full-current-checkbox-off') 1937 const price_full_current_checkbox_on = checkbox.getAttribute('data-price-full-current-checkbox-on') 1938 const price_plan_old_checkbox_off = checkbox.getAttribute('data-price-plan-old-checkbox-off') 1939 const price_plan_old_checkbox_on = checkbox.getAttribute('data-price-plan-old-checkbox-on') 1940 const price_plan_current_checkbox_off = checkbox.getAttribute('data-price-plan-current-checkbox-off') 1941 const price_plan_current_checkbox_on = checkbox.getAttribute('data-price-plan-current-checkbox-on') 1942 1943 const priceFullCurrentNode = area.querySelector('[data-element="price-full-current"]') 1944 const priceFullOldNode = area.querySelector('[data-element="price-full-old"]') 1945 const pricePlanCurrentNode = area.querySelector('[data-element="price-plan-current"]') 1946 const pricePlanOldNode = area.querySelector('[data-element="price-plan-old"]') 1947 1948 function changePrice () { 1949 sendCommonAnalytics('element_click', checkbox) 1950 if (this.checked) { 1951 if (priceFullCurrentNode) priceFullCurrentNode.innerHTML = price_full_current_checkbox_on 1952 if (priceFullOldNode) priceFullOldNode.innerHTML = price_full_old_checkbox_on 1953 if (pricePlanCurrentNode) pricePlanCurrentNode.innerHTML = price_plan_current_checkbox_on 1954 if (pricePlanOldNode) pricePlanOldNode.innerHTML = price_plan_old_checkbox_on 1955 } 1956 else { 1957 if (priceFullCurrentNode) priceFullCurrentNode.innerHTML = price_full_current_checkbox_off 1958 if (priceFullOldNode) priceFullOldNode.innerHTML = price_full_old_checkbox_off 1959 if (pricePlanCurrentNode) pricePlanCurrentNode.innerHTML = price_plan_current_checkbox_off 1960 if (pricePlanOldNode) pricePlanOldNode.innerHTML = price_plan_old_checkbox_off 1961 } 1962 } 1963 } 1964 } 1965 1966const courseAboutVideoWraps = document.querySelectorAll("[data-element='course-about-video-wrap']") 1967 1968for (let i = 0; i < courseAboutVideoWraps.length; i++) { 1969 courseAboutVideoWrapInit(courseAboutVideoWraps[i]) 1970} 1971 1972function courseAboutVideoWrapInit (videoWrap) { 1973 const courseAboutVideo = videoWrap.querySelector("[data-element='course-about-video']") 1974 const soundBtn = videoWrap.querySelector(".course-about__sound") 1975 let startPlayTime = courseAboutVideo.getAttribute('data-play-start') 1976 if (!startPlayTime) startPlayTime = 0 1977 1978 if (courseAboutVideo.readyState >= 2) { 1979 videoLoaded() 1980 } 1981 1982 courseAboutVideo.addEventListener('loadeddata', videoLoaded) 1983 courseAboutVideo.addEventListener('play', videoLoaded) 1984 1985 setTimeout(() => { 1986 try { 1987 courseAboutVideo.currentTime = startPlayTime 1988 } catch (e) { 1989 console.log(e) 1990 } 1991 }, 1000) 1992 1993 1994 function videoLoaded () { 1995 videoWrap.classList.add('loaded') 1996 } 1997 1998 videoWrap.addEventListener('click', playVideo) 1999 2000 function playVideo (e) { 2001 e.stopPropagation() 2002 if (courseAboutVideo.muted) { 2003 courseAboutVideo.muted = false 2004 courseAboutVideo.loop = false 2005 courseAboutVideo.currentTime = 0 2006 courseAboutVideo.controls = true 2007 2008 2009 2010 soundBtn.classList.add('hide') 2011 setTimeout(() => courseAboutVideo.play(), 100) 2012 } else { 2013 courseAboutVideo.muted = true 2014 courseAboutVideo.controls = false 2015 soundBtn.classList.remove('hide') 2016 } 2017 } 2018} 2019 2020const selectArray = document.querySelectorAll('[data-role="custom-select"]') 2021 2022for (let i = 0; i < selectArray.length; i++) { 2023 customSelect(selectArray[i]) 2024} 2025 2026const dataRedirectLinks = document.querySelectorAll('[data-redirect]') 2027 2028if (dataRedirectLinks.length) dataRedirectLinksInit() 2029 2030function dataRedirectLinksInit () { 2031 for (let i = 0; i < dataRedirectLinks.length; i++) { 2032 dataRedirectLinks[i].addEventListener('click', dataRedirect) 2033 } 2034} 2035 2036function dataRedirect (e) { 2037 e.preventDefault() 2038 window.open(this.href, '_blank'); 2039} 2040 2041const diagnostika_b = document.querySelector('.diagnostika_b'); 2042 2043if (diagnostika_b) diagnostika_bInit() 2044 2045function diagnostika_bInit () { 2046 /* ================= 1. ÐолеÑо знаний ================= */ 2047 2048 // ÐÑи идÑÑ Ð¿Ð¾ ÑаÑовой ÑÑÑелке Ð¾Ñ Â«12 ÑаÑов», Ñовно как в Figma. 2049 var WHEEL_AXES = [ 2050 { label: 'ÐÑоби', value: 86, gap: false }, 2051 { label: 'УÑавнениÑ', value: 52, gap: true }, 2052 { label: 'ФÑнкÑии', value: 40, gap: true }, 2053 { label: 'ÐеомеÑÑиÑ', value: 66, gap: false }, 2054 { label: 'ÐÑоÑенÑÑ', value: 90, gap: false }, 2055 { label: 'СÑепени', value: 48, gap: true }, 2056 { label: 'СÑаÑ.', value: 78, gap: false }, 2057 { label: 'ÐадаÑи', value: 44, gap: true } 2058 ]; 2059 2060 // ÐеомеÑÑÐ¸Ñ ÑнÑÑа Ñ Ð´Ð²ÑÑ ÐºÐ¾Ð½ÑÑолÑнÑÑ Ð¼Ð°ÐºÐµÑов Figma (76:3 и 76:4). 2061 // box â ÑÐ°Ð·Ð¼ÐµÑ Ð¾Ð±Ð»Ð°ÑÑи колеÑа, cx/cy â ÑенÑÑ, r â ÑадиÑÑ Ð²Ð½ÐµÑнего колÑÑа, 2062 // dot â диамеÑÑ Ð²ÐµÑÑинÑ, 2063 // gaps â оÑÑÑÑп подпиÑи Ð¾Ñ Ð²Ð½ÐµÑнего колÑÑа: n/e/s/w по ÑÑоÑонам ÑвеÑа, 2064 // d â по диагоналÑм. Ðа Desktop Ð´Ð¸Ð·Ð°Ð¹Ð½ÐµÑ ÑазвÑл подпиÑи
2065 // неÑиммеÑÑиÑно, ÑÑÐ¾Ð±Ñ Ð¾Ð½Ð¸ ÑложилиÑÑ Ð² 470Ã450. 2066 var WHEEL_PRESETS = { 2067 desktop: { 2068 box: [470, 450], cx: 235, cy: 222, r: 163, dot: 11, 2069 gaps: { n: 25, e: 14, s: 30, w: 30, d: 21.2 } 2070 }, 2071 tablet: { 2072 box: [654, 470], cx: 327, cy: 231, r: 170, dot: 10, 2073 gaps: { n: 26, e: 26, s: 26, w: 26, d: 18.4 } 2074 } 2075 }; 2076 2077 // ÐолеÑо еÑÑÑ ÑолÑко на Desktop и Tablet: в макеÑе Mobile его неÑ. 2078 var MOBILE_QUERY = '(max-width: 600px)'; 2079 var TABLET_QUERY = '(max-width: 1180px)'; 2080 2081 var SVG_NS = 'http://www.w3.org/2000/svg'; 2082 2083 function svgEl(name, attrs) { 2084 var node = document.createElementNS(SVG_NS, name); 2085 for (var key in attrs) { node.setAttribute(key, attrs[key]); } 2086 return node; 2087 } 2088 2089 function currentPreset() { 2090 if (window.matchMedia(MOBILE_QUERY).matches) { return null; } 2091 if (window.matchMedia(TABLET_QUERY).matches) { return WHEEL_PRESETS.tablet; } 2092 return WHEEL_PRESETS.desktop; 2093 } 2094 2095 function renderWheel(host, p) { 2096 var w = p.box[0]; 2097 var h = p.box[1]; 2098 2099 host.textContent = ''; 2100 2101 var svg = svgEl('svg', { 2102 'class': 'wheel__chart', 2103 viewBox: '0 0 ' + w + ' ' + h, 2104 preserveAspectRatio: 'xMidYMid meet', 2105 focusable: 'false', 2106 'aria-hidden': 'true' 2107 }); 2108 2109 // СеÑка: 4 колÑÑа 2110 [0.25, 0.5, 0.75, 1].forEach(function (k) { 2111 svg.appendChild(svgEl('circle', { 2112 cx: p.cx, cy: p.cy, r: p.r * k, 2113 fill: 'none', stroke: '#003C56', 'stroke-opacity': '0.1' 2114 })); 2115 }); 2116 2117 // СпиÑÑ 2118 var spokes = ''; 2119 WHEEL_AXES.forEach(function (_, i) { 2120 var a = (Math.PI / 4) * i; 2121 spokes += 'M' + p.cx + ' ' + p.cy + 2122 'L' + (p.cx + p.r * Math.sin(a)) + ' ' + (p.cy - p.r * Math.cos(a)); 2123 }); 2124 svg.appendChild(svgEl('path', { d: spokes, stroke: '#003C56', 'stroke-opacity': '0.1', fill: 'none' })); 2125 2126 // ÐÑогÑамма клаÑÑа â пÑнкÑиÑное колÑÑо 0.8R 2127 svg.appendChild(svgEl('circle', { 2128 cx: p.cx, cy: p.cy, r: p.r * 0.8, 2129 fill: 'none', stroke: '#6683C2', 'stroke-opacity': '0.7', 2130 'stroke-width': '1.4', 'stroke-dasharray': '5 5' 2131 })); 2132 2133 // ÐÑоÑÐ¸Ð»Ñ ÑÑеника 2134 var points = WHEEL_AXES.map(function (axis, i) { 2135 var a = (Math.PI / 4) * i; 2136 var rr = p.r * (axis.value / 100); 2137 return [p.cx + rr * Math.sin(a), p.cy - rr * Math.cos(a)]; 2138 }); 2139 svg.appendChild(svgEl('polygon', { 2140 points: points.map(function (pt) { return pt[0].toFixed(2) + ',' + pt[1].toFixed(2); }).join(' '), 2141 fill: '#6683C2', 'fill-opacity': '0.18', 2142 stroke: '#6683C2', 'stroke-width': '2', 'stroke-linejoin': 'round' 2143 })); 2144 2145 // ÐеÑÑÐ¸Ð½Ñ 2146 points.forEach(function (pt, i) { 2147 svg.appendChild(svgEl('circle', WHEEL_AXES[i].gap 2148 ? { cx: pt[0], cy: pt[1], r: p.dot / 2 - 1, fill: '#FFFFFF', stroke: '#F37E60', 'stroke-width': '2' } 2149 : { cx: pt[0], cy: pt[1], r: p.dot / 2, fill: '#003C56' } 2150 )); 2151 }); 2152 2153 host.appendChild(svg); 2154 2155 // ÐодпиÑи â HTML повеÑÑ SVG, позиÑиониÑÑÑÑÑÑ Ð² пÑоÑенÑÐ°Ñ Ð¾Ñ Ð¾Ð±Ð»Ð°ÑÑи колеÑа 2156 WHEEL_AXES.forEach(function (axis, i) { 2157 var a = (Math.PI / 4) * i; 2158 var sin = Math.sin(a); 2159 var cos = Math.cos(a); 2160 var px = p.cx + p.r * sin; 2161 var py = p.cy - p.r * cos; 2162 var diagonal = Math.abs(sin) > 0.01 && Math.abs(cos) > 0.01; 2163 var x, y; 2164 2165 if (diagonal) { 2166 x = px + p.gaps.d * Math.sign(sin); 2167 y = py - p.gaps.d * Math.sign(cos); 2168 } else if (Math.abs(sin) < 0.01) { // веÑÑикалÑÐ½Ð°Ñ Ð¾ÑÑ 2169 x = p.cx; 2170 y = py - (cos > 0 ? p.gaps.n : -p.gaps.s); 2171 } else { // гоÑизонÑалÑÐ½Ð°Ñ Ð¾ÑÑ 2172 x = px + (sin > 0 ? p.gaps.e : -p.gaps.w); 2173 y = p.cy; 2174 } 2175 2176 // ÐÑÑавнивание бокÑа подпиÑи оÑноÑиÑелÑно ÑоÑки на оÑи 2177 var tx = sin > 0.01 ? '0' : (sin < -0.01 ? '-100%' : '-50%'); 2178 var ty = cos > 0.01 ? '-100%' : (cos < -0.01 ? '0' : '-50%'); 2179 2180 var el = document.createElement('span'); 2181 el.className = 'wheel__label' + (axis.gap ? ' wheel__label--gap' : ''); 2182 el.style.left = (x / w * 100) + '%'; 2183 el.style.top = (y / h * 100) + '%'; 2184 el.style.transform = 'translate(' + tx + ', ' + ty + ')'; 2185 el.innerHTML = axis.label + '<b>' + axis.value + '%</b>'; 2186 host.appendChild(el); 2187 }); 2188 } 2189 2190 var wheelHost = document.getElementById('knowledge-wheel'); 2191 if (wheelHost) { 2192 var lastPreset; 2193 2194 var syncWheel = function () { 2195 var preset = currentPreset(); 2196 if (preset === lastPreset) { return; } 2197 lastPreset = preset; 2198 if (preset) { renderWheel(wheelHost, preset); } else { wheelHost.textContent = ''; } 2199 }; 2200 2201 syncWheel(); 2202 2203 var resizeTimer; 2204 window.addEventListener('resize', function () { 2205 clearTimeout(resizeTimer); 2206 resizeTimer = setTimeout(syncWheel, 150); 2207 }); 2208 } 2209 2210} 2211 2212const diagnostika = document.querySelector('.diagnostika'); 2213
2214if (diagnostika) diagnostikaInit() 2215 2216function diagnostikaInit() { 2217 /* ================= 1. ÐолеÑо знаний ================= */ 2218 2219// ÐÑи идÑÑ Ð¿Ð¾ ÑаÑовой ÑÑÑелке Ð¾Ñ Â«12 ÑаÑов», Ñовно как в Figma. 2220 var WHEEL_AXES = [ 2221 { label: 'ÐÑоби', value: 86, gap: false }, 2222 { label: 'УÑавнениÑ', value: 52, gap: true }, 2223 { label: 'ФÑнкÑии', value: 40, gap: true }, 2224 { label: 'ÐеомеÑÑиÑ', value: 66, gap: false }, 2225 { label: 'ÐÑоÑенÑÑ', value: 90, gap: false }, 2226 { label: 'СÑепени', value: 48, gap: true }, 2227 { label: 'СÑаÑ.', value: 78, gap: false }, 2228 { label: 'ÐадаÑи', value: 44, gap: true } 2229 ]; 2230 2231// ÐеомеÑÑÐ¸Ñ Ð¸Ð· ÑÑÑÑ ÐºÐ¾Ð½ÑÑолÑнÑÑ Ð¼Ð°ÐºÐµÑов Figma. 2232// box â ÑÐ°Ð·Ð¼ÐµÑ Ð¾Ð±Ð»Ð°ÑÑи колеÑа, cx/cy â ÑенÑÑ, r â ÑадиÑÑ Ð²Ð½ÐµÑнего колÑÑа, 2233// gapC â оÑÑÑÑп подпиÑи на веÑÑикалÑнÑÑ /гоÑизонÑалÑнÑÑ Ð¾ÑÑÑ , 2234// gapD â оÑÑÑÑп подпиÑи на диагоналÑÑ , dot â диамеÑÑ Ð²ÐµÑÑинÑ. 2235 var WHEEL_PRESETS = { 2236 desktop: { box: [470, 450], cx: 235, cy: 222, r: 163, gapC: 25, gapD: 21, dot: 11 }, 2237 tablet: { box: [654, 470], cx: 327, cy: 231, r: 170, gapC: 26, gapD: 18.4, dot: 10 }, 2238 mobile: { box: [290, 300], cx: 145, cy: 148, r: 78, gapC: 18, gapD: 12.73, dot: 8 } 2239 }; 2240 2241 var SVG_NS = 'http://www.w3.org/2000/svg'; 2242 2243 function svgEl(name, attrs) { 2244 var node = document.createElementNS(SVG_NS, name); 2245 for (var key in attrs) { node.setAttribute(key, attrs[key]); } 2246 return node; 2247 } 2248 2249 function currentPreset() { 2250 if (window.matchMedia('(max-width: 600px)').matches) { return WHEEL_PRESETS.mobile; } 2251 if (window.matchMedia('(max-width: 1180px)').matches) { return WHEEL_PRESETS.tablet; } 2252 return WHEEL_PRESETS.desktop; 2253 } 2254 2255 function renderWheel(host) { 2256 var p = currentPreset(); 2257 var w = p.box[0]; 2258 var h = p.box[1]; 2259 2260 host.textContent = ''; 2261 2262 var svg = svgEl('svg', { 2263 'class': 'wheel__chart', 2264 viewBox: '0 0 ' + w + ' ' + h, 2265 preserveAspectRatio: 'xMidYMid meet', 2266 focusable: 'false', 2267 'aria-hidden': 'true' 2268 }); 2269 2270 // СеÑка: 4 колÑÑа 2271 [0.25, 0.5, 0.75, 1].forEach(function (k) { 2272 svg.appendChild(svgEl('circle', { 2273 cx: p.cx, cy: p.cy, r: p.r * k, 2274 fill: 'none', stroke: '#003C56', 'stroke-opacity': '0.1' 2275 })); 2276 }); 2277 2278 // СпиÑÑ 2279 var spokes = ''; 2280 WHEEL_AXES.forEach(function (_, i) { 2281 var a = (Math.PI / 4) * i; 2282 spokes += 'M' + p.cx + ' ' + p.cy + 2283 'L' + (p.cx + p.r * Math.sin(a)) + ' ' + (p.cy - p.r * Math.cos(a)); 2284 }); 2285 svg.appendChild(svgEl('path', { d: spokes, stroke: '#003C56', 'stroke-opacity': '0.1', fill: 'none' })); 2286 2287 // ÐÑогÑамма клаÑÑа â пÑнкÑиÑное колÑÑо 0.8R 2288 svg.appendChild(svgEl('circle', { 2289 cx: p.cx, cy: p.cy, r: p.r * 0.8, 2290 fill: 'none', stroke: '#6683C2', 'stroke-opacity': '0.7', 2291 'stroke-width': '1.5', 'stroke-dasharray': '6 5' 2292 })); 2293 2294 // ÐÑоÑÐ¸Ð»Ñ ÑÑеника 2295 var points = WHEEL_AXES.map(function (axis, i) { 2296 var a = (Math.PI / 4) * i; 2297 var rr = p.r * (axis.value / 100); 2298 return [p.cx + rr * Math.sin(a), p.cy - rr * Math.cos(a)]; 2299 }); 2300 svg.appendChild(svgEl('polygon', { 2301 points: points.map(function (pt) { return pt[0].toFixed(2) + ',' + pt[1].toFixed(2); }).join(' '), 2302 fill: '#6683C2', 'fill-opacity': '0.18', 2303 stroke: '#6683C2', 'stroke-width': '2', 'stroke-linejoin': 'round' 2304 })); 2305 2306 // ÐеÑÑÐ¸Ð½Ñ 2307 points.forEach(function (pt, i) { 2308 var axis = WHEEL_AXES[i]; 2309 svg.appendChild(svgEl('circle', axis.gap 2310 ? { cx: pt[0], cy: pt[1], r: p.dot / 2 - 1, fill: '#FFFFFF', stroke: '#F37E60', 'stroke-width': '2' } 2311 : { cx: pt[0], cy: pt[1], r: p.dot / 2, fill: '#003C56' } 2312 )); 2313 }); 2314 2315 host.appendChild(svg); 2316 2317 // ÐодпиÑи â HTML повеÑÑ SVG, позиÑиониÑÑÑÑÑÑ Ð² пÑоÑенÑÐ°Ñ Ð¾Ñ Ð¾Ð±Ð»Ð°ÑÑи колеÑа 2318 WHEEL_AXES.forEach(function (axis, i) { 2319 var a = (Math.PI / 4) * i; 2320 var sin = Math.sin(a); 2321 var cos = Math.cos(a); 2322 var diagonal = Math.abs(sin) > 0.01 && Math.abs(cos) > 0.01; 2323 var gap = diagonal ? p.gapD : p.gapC; 2324 2325 var x = p.cx + (p.r * sin) + (diagonal ? gap * Math.sign(sin) : gap * sin); 2326 var y = p.cy - (p.r * cos) - (diagonal ? gap * Math.sign(cos) : gap * cos); 2327 2328 // ÐÑÑавнивание бокÑа подпиÑи оÑноÑиÑелÑно ÑоÑки на оÑи 2329 var tx = sin > 0.01 ? '0' : (sin < -0.01 ? '-100%' : '-50%'); 2330 var ty = cos > 0.01 ? '-100%' : (cos < -0.01 ? '0' : '-50%'); 2331 2332 var el = document.createElement('span'); 2333 el.className = 'wheel__label' + (axis.gap ? ' wheel__label--gap' : ''); 2334 el.style.left = (x / w * 100) + '%'; 2335 el.style.top = (y / h * 100) + '%'; 2336 el.style.transform = 'translate(' + tx + ', ' + ty + ')'; 2337 el.innerHTML = axis.label + '<b>' + axis.value + '%</b>'; 2338 host.appendChild(el); 2339 }); 2340 } 2341 2342 var wheelHost = document.getElementById('knowledge-wheel'); 2343 if (wheelHost) { 2344 renderWheel(wheelHost); 2345 2346 var lastWidthBucket = null; 2347 var resizeTimer; 2348 window.addEventListener('resize', function () { 2349 clearTimeout(resizeTimer); 2350 resizeTimer = setTimeout(function () { 2351 var bucket = currentPreset(); 2352 if (bucket !== lastWidthBucket) { 2353 lastWidthBucket = bucket; 2354 renderWheel(wheelHost); 2355 } 2356 }, 150); 2357 }); 2358 } 2359 2360 /* ================= 3. FAQ-аккоÑдеон ================= */ 2361 2362 Array.prototype.forEach.call(document.querySelectorAll('.faq-item'), function (item) { 2363 var trigger = item.querySelector('.faq-item__q'); 2364 if (!trigger) { return; } 2365 trigger.addEventListener('click', function () { 2366 var willOpen = !item.classList.contains('is-open'); 2367 item.classList.toggle('is-open', willOpen); 2368 trigger.setAttribute('aria-expanded', willOpen ? 'true' : 'false'); 2369 }); 2370 }); 2371} 2372 2373 2374const discountAugust = document.querySelector('[data-element="discount-august"]') 2375 2376if (discountAugust) discountAugustInit() 2377 2378function discountAugustInit () { 2379 const stickyHeader = document.querySelector('.sticky-header') 2380 const close = document.querySelector('[data-element="discount-august__close"]') 2381 close.addEventListener('click', removeDiscount) 2382 2383 function removeDiscount (e) { 2384 e.preventDefault() 2385 discountAugust.remove() 2386 window.removeEventListener('scroll', checkScroll) 2387 stickyHeader.classList.remove('predzaps-top-hide-no-transition') 2388 stickyHeader.classList.remove('predzaps-top-hide') 2389 } 2390 2391 window.addEventListener('scroll', checkScroll, { passive: true }) 2392 2393 function checkScroll () { 2394 if (window.scrollY > 100) { 2395 stickyHeader.classList.add('predzaps-top-hide') 2396 setTimeout(() => stickyHeader.classList.add('predzaps-top-hide-no-transition'), 300) 2397 } else if (window.scrollY <= 20) { 2398 stickyHeader.classList.remove('predzaps-top-hide-no-transition') 2399 setTimeout(() => stickyHeader.classList.remove('predzaps-top-hide'), 100) 2400 } 2401 } 2402} 2403 2404const discount = document.querySelector('[data-element="discount"]') 2405 2406if (discount) discountInit() 2407 2408function discountInit () { 2409 const close = document.querySelector('[data-element="discount__close"]') 2410 close.addEventListener('click', removeDiscount) 2411 2412 function removeDiscount (e) { 2413 e.preventDefault() 2414 discount.remove() 2415 } 2416} 2417 2418const educatorSkillsItems = document.querySelectorAll('.educator-skills__item') 2419
2420if (educatorSkillsItems.length) educatorSkillsItemsInit() 2421 2422function educatorSkillsItemsInit () { 2423 const line = document.querySelector('.educator-skills__line') 2424 2425 function resizeHandler () { 2426 if (window.innerWidth < 1440) { 2427 line.style.bottom = `${educatorSkillsItems[educatorSkillsItems.length - 1].clientHeight - 4}px` 2428 } else { 2429 line.style.bottom = '20px' 2430 } 2431 } 2432 2433 resizeHandler() 2434 2435 window.addEventListener('resize', resizeHandler) 2436} 2437 2438const egeCapTabsArray = document.querySelectorAll('.ege-cap__tabs') 2439 2440for (let i = 0; i < egeCapTabsArray.length; i++) { 2441 egeCapTabsInit(egeCapTabsArray[i]) 2442} 2443 2444function egeCapTabsInit (tabs) { 2445 const tab = tabs.querySelector('a.ege-cap__tab') 2446 if (tab) tab.addEventListener('click', () => tabs.classList.add('active')) 2447} 2448 2449const egeTileToggle = document.querySelectorAll('.ege-tile__toggle') 2450 2451for (let i = 0; i < egeTileToggle.length; i++) { 2452 egeTileToggleInit(egeTileToggle[i]) 2453} 2454 2455function egeTileToggleInit (tabs) { 2456 const tab = tabs.querySelector('a.ege-tile__toggle-item') 2457 if (tab) tab.addEventListener('click', () => tabs.classList.add('active')) 2458} 2459 2460const egeTile = document.querySelector(".ege-tile") 2461 2462if (egeTile) egeTileInit() 2463 2464function egeTileInit () { 2465 const egeTileFilterTop = egeTile.querySelector(".ege-tile__filter-top") 2466 const stickyHeader = document.querySelector('.sticky-header') 2467 const body = document.querySelector('body') 2468 const filterSumr = egeTile.querySelector('[data-role="filter-sumr"]') 2469 const filterNewy = egeTile.querySelector('[data-role="filter-newy"]') 2470 2471 2472 2473 egeTileFilterTop.addEventListener("click", (e)=> openFilter(egeTileFilterTop, e)) 2474 filterSumr?.addEventListener('change', () => makeFiltration(1)) 2475 filterNewy?.addEventListener('change', () => makeFiltration(1)) 2476 2477 document.addEventListener('click', function () { 2478 egeTileFilterTop.classList.remove('active') 2479 }) 2480 2481 function openFilter (opener, e) { 2482 e.stopPropagation() 2483 if (opener.classList.contains('active')) { 2484 opener.classList.remove('active') 2485 showHeader() 2486 } else { 2487 closeSelectFilter() 2488 opener.classList.add('active') 2489 hideHeader() 2490 } 2491 } 2492 2493 function closeSelectFilter () { 2494 const oldSelectFilterOpen = document.querySelector(".select-filter.active") 2495 if (oldSelectFilterOpen) { 2496 oldSelectFilterOpen.classList.remove('active') 2497 oldSelectFilterOpen.querySelector('.select-filter__top').classList.remove('active') 2498 } 2499 } 2500 2501 function showHeader () { 2502 stickyHeader.classList.remove('hide') 2503 body.classList.remove('no-scroll') 2504 } 2505 2506 function hideHeader () { 2507 if (window.innerWidth < 744) { 2508 stickyHeader.classList.add('hide') 2509 body.classList.add('no-scroll') 2510 } 2511 } 2512 2513 const config = { attributes: true, childList: true, characterData: true, subtree: true } 2514 const tile = egeTile.querySelector('.all-courses__tile') 2515 const classInputs = egeTile.querySelectorAll('.ege-tile__tab-input_class') 2516 const subjectInputs = egeTile.querySelectorAll('.ege-tile__filter-input_subject') 2517 const subjectInputText = egeTile.querySelector('.ege-tile__filter-top-text') 2518 2519 const observer = new MutationObserver(function observerCallback(mutations) { 2520 mutations.forEach( 2521 (mutation) => { 2522 if (mutation.addedNodes.length) { 2523 mutation.addedNodes.forEach((node) => { 2524 if (node?.classList?.contains('all-courses__item')) { 2525 dataHrefLinksInit(node) 2526 togglePrice(node) 2527 fancyboxAjaxCardsReInit(node) 2528 initCommonAnalytics(node) 2529 } 2530 }) 2531 } 2532 }) 2533 moreBtnInit() 2534 }) 2535 2536 if (tile) togglePrice() 2537 2538 function togglePrice (node) { 2539 if (node) { 2540 togglePriceHandler(node) 2541 } else { 2542 const items = tile?.querySelectorAll(".all-courses__item") 2543 items.forEach((item) => { 2544 togglePriceHandler(item) 2545 }) 2546 } 2547 function togglePriceHandler (item) { 2548 const toggle = item.querySelectorAll('.all-courses__radio-input') 2549 if (!toggle.length) return 2550 const boxes = item.querySelectorAll('.all-courses__box') 2551 const textReplace = item.querySelector('.all-courses__info.text-replace') 2552 let texts 2553 if (textReplace) { 2554 texts = textReplace.querySelectorAll('.all-courses__info-span') 2555 } 2556 for (let i = 0; i < toggle.length; i++) { 2557 toggle[i].addEventListener('change', toggleBoxes) 2558 if (texts) toggle[i].addEventListener('change', toggleTexts) 2559 } 2560 2561 function toggleBoxes () { 2562 for (let i = 0; i < boxes.length; i++) { 2563 if (boxes[i].classList.contains('hide')) { 2564 boxes[i].classList.remove('hide') 2565 } else { 2566 boxes[i].classList.add('hide') 2567 } 2568 } 2569 } 2570 2571 function toggleTexts () { 2572 for (let i = 0; i < texts.length; i++) { 2573 if (texts[i].classList.contains('hide')) { 2574 texts[i].classList.remove('hide') 2575 } else { 2576 texts[i].classList.add('hide') 2577 } 2578 } 2579 } 2580 } 2581 } 2582 2583 if (tile) observer.observe(tile, config) 2584 2585 const reset = egeTile.querySelector('.ege-tile__reset-filter') 2586 if (reset) reset.addEventListener('click', resetFilters) 2587 2588 function resetFilters () { 2589 const items = egeTile.querySelectorAll("input")
2590 items.forEach((item) => { 2591 if (item.hasAttribute('data-default-garde')) { 2592 item.checked = true 2593 }else{ 2594 item.checked = false 2595 } 2596 }) 2597 reset.style.display = 'none' 2598 subjectInputText.innerHTML = "ÐÑе пÑедмеÑÑ" 2599 makeFiltration(); 2600 } 2601 2602 for (let i = 0; i < classInputs.length; i++) { 2603 classInputs[i].addEventListener('change', updateFilter) 2604 } 2605 2606 for (let i = 0; i < subjectInputs.length; i++) { 2607 subjectInputs[i].addEventListener('change', updateFilter) 2608 subjectInputs[i].addEventListener('change', changeSubjectInputText) 2609 } 2610 2611 function changeSubjectInputText () { 2612 subjectInputText.innerHTML = this.getAttribute('data-text') 2613 } 2614 2615 moreBtnInit() 2616 2617 function moreBtnInit () { 2618 const moreBtn = egeTile.querySelector('.all-courses__more-button') 2619 if (moreBtn) { 2620 const newBtn = replaceBtn(moreBtn) 2621 newBtn.addEventListener('click', () => makeFiltration(newBtn.getAttribute('data-v'))) 2622 } 2623 } 2624 2625 function replaceBtn (oldElement) { 2626 const newElement = oldElement.cloneNode(true) 2627 oldElement.parentNode.replaceChild(newElement, oldElement) 2628 return newElement 2629 } 2630 2631 2632 function updateFilter () { 2633 const itemsAll = egeTile.querySelectorAll(["input:checked"]) 2634 if (itemsAll.length) { 2635 if (reset) reset.style.display = 'flex' 2636 } else { 2637 if (reset) reset.style.display = 'none' 2638 } 2639 makeFiltration() 2640 } 2641 2642 function makeFiltration (p_paginate = 1) { 2643 const grades_items = egeTile.querySelectorAll('.ege-tile__tab-input_class:checked') 2644 let grades_result = '' 2645 let grade_first = 0 2646 grades_items.forEach((item, i) => { 2647 if (i > 0) grades_result += '|' 2648 if (grade_first == 0) grade_first = item.value 2649 grades_result += item.value 2650 }) 2651 let subjects_result = '' 2652 try{ 2653 const subjects_items = egeTile.querySelectorAll('.ege-tile__filter-input_subject:checked') 2654 subjects_items.forEach((item, i) => { 2655 if (i > 0) subjects_result += '|' 2656 subjects_result += item.value 2657 }) 2658 }catch(e){} 2659 2660 let utm_f = tile.getAttribute('data-utm'); 2661 let promo_f = tile.getAttribute('data-promo'); 2662 let oge_ege_type = tile.getAttribute('data-oge-ege'); 2663 2664 if(p_paginate === 1 ){ 2665 $('.filtered_elements').html("<div class='tile-loader'></div>"); 2666 $('.more_b').html(""); 2667 } 2668 2669 var obData = { 2670 'grade': grades_result, 2671 'subject': subjects_result, 2672 'utm_t': utm_f, 2673 'promo': promo_f, 2674 'oge_ege_type': oge_ege_type, 2675 'pagePaginate': p_paginate, 2676 'summerny': getSummerny(), 2677 }; 2678 $.request('DirectionFunctions::onPaginateAllCourses', { 2679 data: obData 2680 }) 2681 // if (grade_first > 0){ 2682 // let url = new URL(window.location.href) 2683 // url.searchParams.set('gr', grade_first); 2684 // history.replaceState(null, "", url.toString()) 2685 // } 2686 // } 2687 } 2688 function getSummerny () { 2689 let summerny = '' 2690 if (filterSumr?.checked) { 2691 summerny = filterSumr.getAttribute('data-value') 2692 } else if (filterNewy?.checked) { 2693 summerny = filterNewy.getAttribute('data-value') 2694 } 2695 return summerny 2696 } 2697 2698} 2699 2700const eye = document.querySelector('.eye') 2701 2702if (eye) eyeInit() 2703 2704function eyeInit() { 2705 const body = document.querySelector('body') 2706 const isActive = localStorage.getItem('tochka-school-eye') 2707 if (isActive === "true") { 2708 activateEye() 2709 } 2710 eye.addEventListener('click', toggleEye) 2711 2712 function toggleEye () { 2713 if (eye.classList.contains('active')) { 2714 resetEye() 2715 } else { 2716 activateEye() 2717 } 2718 } 2719 2720 function activateEye () { 2721 eye.classList.add('active') 2722 body.classList.add('eye-active') 2723 localStorage.setItem('tochka-school-eye', 'true') 2724 } 2725 2726 function resetEye () { 2727 eye.classList.remove('active') 2728 body.classList.remove('eye-active') 2729 localStorage.setItem('tochka-school-eye', '') 2730 } 2731} 2732 2733 2734const famDoc = document.querySelector('.fam-doc') 2735 2736if (famDoc) famDocInit() 2737 2738function famDocInit () { 2739 const toggle = famDoc.querySelector('.fam-doc__button') 2740 toggle?.addEventListener('click', toggleDoc) 2741 2742 function toggleDoc () { 2743 if (famDoc.classList.contains('open')) { 2744 famDoc.classList.remove('open') 2745 toggle.innerHTML = 'ÐÑкÑÑÑÑ ÑаÑпиÑание аÑÑеÑÑаÑии' 2746 } else { 2747 famDoc.classList.add('open') 2748 toggle.innerHTML = 'СкÑÑÑÑ ÑаÑпиÑание аÑÑеÑÑаÑии' 2749 } 2750 } 2751} 2752 2753 2754 2755const familyHowSlider = document.querySelector('[data-element="family-h
2755ow-slider"]') 2756 2757if (familyHowSlider) familyHowSliderInit() 2758 2759function familyHowSliderInit () { 2760 let familyHowSliderSwiper 2761 2762 function initSlider () { 2763 familyHowSliderSwiper = new Swiper(familyHowSlider, { 2764 slidesPerView: 'auto', 2765 spaceBetween: 40, 2766 a11y: false, 2767 navigation: { 2768 nextEl: '.family-how__nav-btn_next', 2769 prevEl: '.family-how__nav-btn_prev', 2770 }, 2771 scrollbar: { 2772 el: '.family-how__scrollbar', 2773 draggable: true, 2774 }, 2775 }) 2776 } 2777 2778 window.addEventListener('resize', checkSlider) 2779 2780 checkSlider() 2781 2782 function checkSlider () { 2783 if (window.innerWidth >= 744) { 2784 if (!familyHowSliderSwiper || familyHowSliderSwiper.destroyed) { 2785 initSlider() 2786 } 2787 } else { 2788 if (familyHowSliderSwiper && !familyHowSliderSwiper.destroyed) { 2789 familyHowSliderSwiper.destroy(true, true) 2790 familyHowSliderSwiper = null 2791 } 2792 } 2793 } 2794} 2795 2796const familyProgram = document.querySelector('.family-program') 2797 2798 if (familyProgram) familyProgramInit() 2799 2800 function familyProgramInit () { 2801 const wrap = document.querySelector('.family-program__wrap') 2802 const overlay = document.querySelector('.family-program__overlay') 2803 2804 overlay.addEventListener('scroll', function () { 2805 wrap.classList.add('hide-hint') 2806 }, {once: true}) 2807 2808 if (overlay.scrollWidth <= overlay.clientWidth) { 2809 wrap.classList.add('hide-hint') 2810 } 2811 } 2812 2813 2814 2815 2816const scheduleFamily = document.querySelector('[data-element="family-schedule"]') 2817 2818if (scheduleFamily) scheduleFamilyInit() 2819 2820function scheduleFamilyInit () { 2821 let offsetHeader 2822 const toggleBottom = scheduleFamily.querySelector('[data-element="family-schedule__toggle-bottom"]') 2823 const programStretch = document.querySelector('.program-stretch') 2824 const toggleTop = document.querySelector('[data-element="family-schedule__toggle-top"]') 2825 const table = scheduleFamily.querySelector('[data-element="family-schedule__box"]') 2826 const row = scheduleFamily.querySelector('[data-element="family-schedule__row"]') 2827 const cells = scheduleFamily.querySelectorAll('[data-element="family-schedule__cell"]') 2828 const cellTime = scheduleFamily.querySelector('[data-element="family-schedule__time"]') 2829 2830 const isSummer = toggleTop?.classList.contains('summer') 2831 2832 tableFixedCalculate() 2833 2834 function tableFixedCalculate() { 2835 if (window.innerWidth <= 360) { 2836 offsetHeader = 70 2837 } else if (window.innerWidth < 1200) { 2838 offsetHeader = 82 2839 } else { 2840 offsetHeader = 108 2841 } 2842 if (window.innerWidth < 1440) { 2843 for (let i = 0; i < cells.length; i++) { 2844 cells[i].style.height = cells[i].parentNode.offsetHeight + 'px' 2845 } 2846 } else { 2847 for (let i = 0; i < cells.length; i++) { 2848 cells[i].style.height = 'auto' 2849 } 2850 } 2851 } 2852 2853 window.addEventListener('scroll', rowFixedCalculate) 2854 window.addEventListener('resize', tableFixedCalculate) 2855 2856 rowFixedCalculate() 2857 2858 function rowFixedCalculate () { 2859 if (window.innerWidth >= 1440) { 2860 row.style.transform = 'none' 2861 cellTime.style.transform = 'none' 2862 } else { 2863 const topCoord = table.getBoundingClientRect().top 2864 const bottomCoord = table.getBoundingClientRect().bottom 2865 if (topCoord < offsetHeader && bottomCoord > 100) { 2866 row.style.transform = row.style.transform.slice(0, row.style.transform.length - 2) - 400 + 'px' 2867 cellTime.style.transform = cellTime.style.transform.slice(0, cellTime.style.transform.length - 2) - 400 + 'px' 2868 window.requestAnimationFrame(updateRowFixedTop) 2869 } else { 2870 row.style.transform = '' 2871 cellTime.style.transform = '' 2872 } 2873 } 2874 } 2875 2876 function updateRowFixedTop () { 2877 row.style.transform = 'translateY(' + (offsetHeader - table.getBoundingClientRect().top) + 'px' + ')' 2878 cellTime.style.transform = 'translateY(' + (offsetHeader - table.getBoundingClientRect().top) + 'px' + ')' 2879 } 2880 2881 toggleBottom.addEventListener('click', toggleTable) 2882 toggleTop?.addEventListener('click', toggleTable) 2883 toggleBottom.addEventListener('click', scrollToTable) 2884 2885 2886 2887 function toggleTable () { 2888 if (table.classList.contains('hide')) { 2889 showTable() 2890 programStretch?.classList.add('program-stretch_active') 2891 } else { 2892 hideTable() 2893 programStretch?.classList.remove('program-stretch_active') 2894 } 2895 } 2896 2897 function scrollToTable () { 2898 const y = scheduleFamily.getBoundingClientRect().top + window.scrollY - 100 2899 window.scrollTo({top: y, behavior: 'smooth'}) 2900 } 2901 2902 function hideTable () { 2903 table.classList.add('hide') 2904 toggleBottom.classList.add('reverse') 2905 toggleTop.classList.add('reverse') 2906 if (!isSummer) { 2907 toggleBottom.innerHTML = "ÐоказаÑÑ ÑаÑпиÑание" 2908 toggleTop.innerHTML = "ÐоказаÑÑ ÑаÑпиÑание" 2909 } else { 2910 toggleBottom.innerHTML = "РаÑпиÑание на май" 2911 toggleTop.innerHTML = "РаÑпиÑание на май" 2912 } 2913 toggleBottom.classList.add('hide') 2914 } 2915 2916 function showTable () { 2917 table.classList.remove('hide') 2918 toggleBottom.classList.remove('reverse') 2919 toggleTop.classList.remove('reverse') 2920 toggleBottom.innerHTML = "СвеÑнÑÑÑ ÑаÑпиÑание" 2921 toggleTop.innerHTML = "СвеÑнÑÑÑ ÑаÑпиÑание" 2922 toggleBottom.classList.remove('hide') 2923 row.style.transform = 'none' 2924 cellTime.style.transform = 'none' 2925 setTimeout(() => tableFixedCalculate(), 100) 2926 } 2927} 2928 2929const familyTeachersSlider = document.querySelector('.family-teachers__slider') 2930 2931if (familyTeachersSlider) familyTeachersSliderInit() 2932
2933function familyTeachersSliderInit () { 2934 let swiper 2935 if (window.innerWidth >= 744) { 2936 swiper = new Swiper(familyTeachersSlider, { 2937 mousewheel: { forceToAxis: true }, 2938 slidesPerView: 'auto', 2939 autoHeight: true, 2940 spaceBetween: 500, 2941 effect: 'fade', 2942 fadeEffect: { 2943 crossFade: true 2944 }, 2945 a11y: false, 2946 pagination: { 2947 el: '.family-teachers__pagination', 2948 clickable: true, 2949 }, 2950 breakpoints: { 2951 744: { 2952 effect: 'fade', 2953 navigation: { 2954 nextEl: '.family-teachers__nav-btn_next', 2955 prevEl: '.family-teachers__nav-btn_prev', 2956 }, 2957 scrollbar: { 2958 el: '.family-teachers__scrollbar', 2959 draggable: true, 2960 }, 2961 } 2962 } 2963 }) 2964 } else { 2965 swiper = new Swiper(familyTeachersSlider, { 2966 slidesPerView: 'auto', 2967 autoHeight: true, 2968 spaceBetween: 200, 2969 fadeEffect: { 2970 crossFade: true 2971 }, 2972 a11y: false, 2973 pagination: { 2974 el: '.family-teachers__pagination', 2975 clickable: true, 2976 }, 2977 breakpoints: { 2978 744: { 2979 effect: 'fade', 2980 navigation: { 2981 nextEl: '.family-teachers__nav-btn_next', 2982 prevEl: '.family-teachers__nav-btn_prev', 2983 }, 2984 scrollbar: { 2985 el: '.family-teachers__scrollbar', 2986 draggable: true, 2987 }, 2988 } 2989 } 2990 }) 2991 } 2992 2993 const isTrialPage = familyTeachersSlider.closest('.family-teachers.trial-lessons') 2994 const boxes = familyTeachersSlider.querySelectorAll('.family-teachers__box') 2995 2996 for (let i = 0; i < boxes.length; i++) { 2997 const list = boxes[i].querySelector('.family-teachers__list') 2998 if (isTrialPage && window.innerWidth >= 1440) { 2999 if (list.clientHeight > 250) moreBtnInit(boxes[i]) 3000 } else { 3001 if (list.clientHeight > 150) moreBtnInit(boxes[i]) 3002 } 3003 3004 } 3005 3006 function moreBtnInit (box) { 3007 box.classList.add('hide') 3008 const btn = box.querySelector('.family-teachers__more') 3009 btn.classList.add('active') 3010 btn.addEventListener('click', toggleBox) 3011 3012 function toggleBox () { 3013 if (box.classList.contains('hide')) { 3014 box.classList.remove('hide') 3015 btn.innerHTML = 'СвеÑнÑÑÑ' 3016 } else { 3017 box.classList.add('hide') 3018 btn.innerHTML = 'ÐоказаÑÑ Ð¿Ð¾Ð»Ð½Ð¾ÑÑÑÑ' 3019 } 3020 swiper.update() 3021 } 3022 } 3023 } 3024 3025function fancyboxAjaxCardsReInit (node) { 3026 if (node && typeof node.querySelectorAll === 'function') { 3027 const fancyboxItems = node.querySelectorAll('[data-fancybox]') 3028 if (fancyboxItems.length) { 3029 fancyboxItems.forEach((item) => { 3030 if (!$.data(item, 'fancybox')) { 3031 $(item).fancybox({ 3032 beforeShow: function (instance) { 3033 try { 3034 const form = document.querySelector(this.src) 3035 const openButton = instance.current.opts.$orig 3036 if (form) { 3037 setDataFtitle(openButton, form) 3038 setBannerName(openButton, form) 3039 } 3040 } catch (e) { 3041 } 3042 }, 3043 afterClose: function () { 3044 try { 3045 const form = document.querySelector(this.src) 3046 if (form) { 3047 setDefaultDataFtitle(form) 3048 setDefaultBannerName(form) 3049 } 3050 } catch (e) { 3051 3052 } 3053 } 3054 }) 3055 } 3056 }) 3057 } 3058 } 3059} 3060 3061 3062const faqAllBg = document.querySelectorAll('.faq-all__bg') 3063 3064if (faqAllBg.length) { 3065 setFaqAllBgWidth() 3066 3067 window.addEventListener('resize', setFaqAllBgWidth, { passive: true }) 3068 3069 function setFaqAllBgWidth() { 3070 for (let i = 0; i < faqAllBg.length; i++) { 3071 faqAllBg[i].style.width = `${document.documentElement.clientWidth - 1}px` 3072 } 3073 } 3074} 3075 3076const faqAllSidebarDesc = document.querySelector('.faq-all__sidebar_desc') 3077 3078if (faqAllSidebarDesc) faqAllSidebarDescInit() 3079 3080function faqAllSidebarDescInit () { 3081 const faqAllLinkArray = faqAllSidebarDesc.querySelectorAll('.faq-all__link') 3082 const faqAllTitleArray = document.querySelectorAll('.faq-all__title') 3083 3084 window.addEventListener('scroll', checkScroll, { passive: true }) 3085 3086 function checkScroll () { 3087 for (let i = faqAllTitleArray.length - 1; i > -1; i--) { 3088 if (faqAllTitleArray[i].getBoundingClientRect().top < 300) { 3089 removeOldLinkActive() 3090 faqAllLinkArray[i].classList.add('active') 3091 break 3092 } else { 3093 faqAllLinkArray[i].classList.remove('active') 3094 } 3095 } 3096 } 3097 3098 function removeOldLinkActive () { 3099 const oldActive = faqAllSidebarDesc.querySelector('.faq-all__link.active') 3100 if (oldActive) oldActive.classList.remove('active') 3101 } 3102} 3103 3104const faqAllSidebarMob = document.querySelector('.faq-all__sidebar_mob') 3105 3106if (faqAllSidebarMob) faqAllSidebarMobInit() 3107 3108function faqAllSidebarMobInit () { 3109 const name = faqAllSidebarMob.querySelector('.faq-all__name') 3110 const layer = faqAllSidebarMob.querySelector('.faq-all__layer') 3111 3112 let scrollDown = true 3113 let lastScrollTop = 0 3114 3115 window.addEventListener('scroll', checkScrollDirection, { passive: true }) 3116 3117 function checkScrollDirection () { 3118 const st = window.scrollY 3119 if (st - lastScrollTop > 7) { 3120 scrollDown = true 3121 } else if (st - lastScrollTop < -7) { 3122 scrollDown = false 3123 } 3124 lastScrollTop = st <= 0 ? 0 : st 3125 if (scrollDown) { 3126 faqAllSidebarMob.classList.remove('fixed') 3127 } else { 3128 faqAllSidebarMob.classList.add('fixed') 3129 } 3130 } 3131 3132 name.addEventListener('click', toggleSidebar) 3133 layer.addEventListener('click', closeSidebar) 3134 3135 function toggleSidebar () { 3136 if (name.classList.contains('active')) { 3137 closeSidebar() 3138 } else { 3139 window.removeEventListener('scroll', checkScrollDirection) 3140 name.classList.add('active') 3141 } 3142 } 3143 3144 function closeSidebar () { 3145 name.classList.remove('active') 3146 window.addEventListener('scroll', checkScrollDirection, {passive: true}) 3147 } 3148 3149 const articleLinkArray = faqAllSidebarMob.querySelectorAll('.faq-all__link') 3150 3151 for (let i = 0; i < articleLinkArray.length; i++) { 3152 articleLinkArray[i].addEventListener('click', toggleLinkActive) 3153 } 3154 3155 function toggleLinkActive () { 3156 const oldActive = faqAllSidebarMob.querySelector('.faq-all__link.active') 3157 if (oldActive) oldActive.classList.remove('active') 3158 this.classList.add('active') 3159 name.classList.remove('active') 3160 window.addEventListener('scroll', checkScrollDirection, {passive: true}) 3161 } 3162} 3163 3164const faqItems = document.querySelectorAll("[data-element='faq-item']") 3165 3166for (let i = 0; i < faqItems.length; i++) { 3167 faqItems[i].addEventListener("click", toggleFaqItem) 3168 3169 function toggleFaqItem () { 3170 this.classList.toggle('active') 3171 } 3172} 3173 3174const filterBlock = document.querySelector('[data-element="filter-block"]') 3175
3176if (filterBlock) filterBlockInit() 3177 3178function filterBlockInit () { 3179 const requestFunctionName = filterBlock.getAttribute('data-request-function') 3180 const filtered_elements = filterBlock.querySelector('.filtered_elements') 3181 const filterSumr = filterBlock.querySelector('[data-role="filter-sumr"]') 3182 const filterNewy = filterBlock.querySelector('[data-role="filter-newy"]') 3183 const subjectInputs = filterBlock.querySelectorAll('.langs-tile__filter-input_subject') 3184 const config = { attributes: false, childList: true, characterData: false, subtree: true } 3185 3186 const body = document.querySelector('body') 3187 let isTileInit = false 3188 3189 const observer = new MutationObserver(function (mutationRecords) { 3190 for (const mutation of mutationRecords) { 3191 if ( 3192 mutation.target.closest('.tile__subject') || 3193 mutation.target.closest('.fam-price__more') || 3194 mutation.target.closest('.tile__tileb') || 3195 mutation.target.closest('.it-tile__pagination') || 3196 mutation.target.closest('.all-courses__more') || 3197 mutation.target.closest('.tile__more') || 3198 mutation.addedNodes[0]?.id === 'ignore-me' 3199 ) { 3200 continue 3201 } 3202 3203 mutation.addedNodes.forEach((node) => { 3204 if ( 3205 node?.classList?.contains('all-courses__item') || 3206 node?.classList?.contains('tile__item') 3207 ) { 3208 dataHrefLinksInit(node) 3209 togglePrice(node) 3210 initCommonAnalytics(node) 3211 } else if (node && typeof node.querySelectorAll === 'function') { 3212 const nodes = node.querySelectorAll('.tile__item, .fam-price__slide') 3213 3214 nodes.forEach((node) => { 3215 dataHrefLinksInit(node) 3216 initCommonAnalytics(node) 3217 }) 3218 } 3219 3220 fancyboxAjaxCardsReInit(node) 3221 }) 3222 3223 moreBtnInit() 3224 tmore_bInit() 3225 3226 if (filterBlock.classList.contains('tile') && !isTileInit) { 3227 isTileInit = true 3228 tileInit(filterBlock) 3229 } 3230 3231 if (filterBlock.classList.contains('fam-price')) { 3232 famPriceInit(filterBlock) 3233 } 3234 } 3235 }) 3236 3237 window.addEventListener('click', (e) => { 3238 closeSubjectFilter() 3239 }) 3240 3241 const tileSubject = document.querySelector('[data-element="tile__subject"]') 3242 const tileSubjectContent = document.querySelector('[data-element="tile__subject-content"]') 3243 const tileSubjectInputs = document.querySelectorAll('[data-element="tile__subject-input"]') 3244 const tileSubjectScroller = document.querySelector('[data-element="tile__subject-scroller"]') 3245 const tileSubjectBox = document.querySelector('[data-element="tile__subject-box"]') 3246 const tileSubjectCurrentReset = document.querySelector('[data-element="tile__subject-current-reset"]') 3247 const tileSubjectReset = document.querySelector('[data-element="tile__subject-reset"]') 3248 const tileSubjectButton = document.querySelector('.tile__subject-button') 3249 const tileSubjectCurrent = document.querySelector('[data-element="tile__subject-current"]') 3250 const tileSubjectCurrentValueSpan = document.querySelector('[data-element="tile__subject-current-value-span"]') 3251 3252 if (tileSubjectButton) tileSubjectButton.addEventListener('click', closeSubjectFilter) 3253 3254 if (tileSubjectReset) tileSubjectCurrentReset.addEventListener('click', resetSubjectFilter) 3255 if (tileSubjectCurrent && tileSubjectReset) tileSubjectReset.addEventListener('click', resetSubjectFilter) 3256 3257 if (tileSubjectScroller && tileSubjectBox) tileSubjectScrollerInit() 3258 if (tileSubject) tileSubjectInit() 3259 3260 3261 3262 if (filtered_elements) observer.observe(filtered_elements, config) 3263 3264 moreBtnInit() 3265 tmore_bInit() 3266 togglePrice() 3267 if (filterBlock.classList.contains('tile')) tileInit(filterBlock) 3268 if (filterBlock.classList.contains('fam-price')) famPriceInit(filterBlock) 3269 3270 filterSumr?.addEventListener('change', () => makeFiltration(1)) 3271 filterNewy?.addEventListener('change', () => makeFiltration(1)) 3272 3273 for (let i = 0; i < subjectInputs.length; i++) { 3274 subjectInputs[i].addEventListener('change', () => makeFiltration(1)) 3275 } 3276 3277 if (tileSubjectContent) swipeTileSubjectContent() 3278 3279 function swipeTileSubjectContent () { 3280 let startY = 0
3281 let currentY = 0 3282 let isSwiping = false 3283 3284 const TRIGGER_THRESHOLD = 150 3285 3286 tileSubjectContent.addEventListener('touchstart', (e) => { 3287 if (e.target.closest('.tile__subject-box')) { 3288 isSwiping = false 3289 return 3290 } 3291 3292 startY = e.touches[0].clientY 3293 currentY = startY 3294 isSwiping = true 3295 3296 tileSubjectContent.style.transition = 'none' 3297 }) 3298 3299 tileSubjectContent.addEventListener('touchmove', (e) => { 3300 if (!isSwiping) return 3301 3302 currentY = e.touches[0].clientY 3303 const diffY = currentY - startY 3304 3305 if (diffY > 0) { 3306 tileSubjectContent.style.transform = `translateY(${diffY}px)` 3307 } 3308 }) 3309 3310 tileSubjectContent.addEventListener('touchend', () => { 3311 if (!isSwiping) return 3312 3313 isSwiping = false 3314 3315 const diffY = currentY - startY 3316 3317 tileSubjectContent.style.transition = 'transform 0.3s ease-out' 3318 3319 if (diffY > TRIGGER_THRESHOLD) { 3320 tileSubjectContent.style.transform = 'translateY(100%)' 3321 3322 setTimeout(() => { 3323 closeSubjectFilter() 3324 tileSubjectContent.style.transform = 'translateY(0)' 3325 }, 300) 3326 } else { 3327 tileSubjectContent.style.transform = 'translateY(0)' 3328 } 3329 3330 startY = 0 3331 currentY = 0 3332 }) 3333 } 3334 3335 function tileSubjectScrollerInit () { 3336 const topMarker = document.createElement('div') 3337 topMarker.style.width = '100%' 3338 const bottomMarker = document.createElement('div') 3339 bottomMarker.style.width = '100%' 3340 3341 tileSubjectBox.prepend(topMarker) 3342 tileSubjectBox.append(bottomMarker) 3343 3344 const tileSubjectBoxObserver = new IntersectionObserver((entries) => { 3345 entries.forEach(entry => { 3346 const isTop = entry.target === topMarker 3347 if (isTop) { 3348 tileSubjectScroller.classList.toggle('tile__subject-scroller_top-shadow', !entry.isIntersecting) 3349 } else { 3350 tileSubjectScroller.classList.toggle('tile__subject-scroller_bottom-shadow', !entry.isIntersecting) 3351 } 3352 }) 3353 }, { 3354 root: tileSubjectBox, 3355 threshold: 1.0 3356 }) 3357 3358 tileSubjectBoxObserver.observe(topMarker) 3359 tileSubjectBoxObserver.observe(bottomMarker) 3360 } 3361 3362 3363 3364 function makeFiltration (p_paginate = 1) { 3365 let subjects_result = getLangSubjectResult() 3366 let utm_f = filtered_elements.getAttribute('data-utm') 3367 let promo_f = filtered_elements.getAttribute('data-promo') 3368 let data_direction = filtered_elements.getAttribute('data-direction') 3369 let grd = filterSumr?.getAttribute('data-grd') 3370 let oge_ege_type = filtered_elements.getAttribute('data-oge-ege'); 3371 3372 if(p_paginate === 1 ){ 3373 $('.filtered_elements').html("<div class='tile-loader'></div>"); 3374 $('.more_b').html(""); 3375 } 3376 3377 var obData = { 3378 'utm_t': utm_f, 3379 'promo': promo_f, 3380 'pagePaginate': p_paginate, 3381 'summerny': getSummerny(), 3382 } 3383 3384 if (data_direction) obData['direction'] = data_direction 3385 if (grd) obData['grade'] = grd 3386 if (oge_ege_type) obData['teacher'] = oge_ege_type 3387 if (subjects_result) obData['subject'] = subjects_result 3388 3389 3390 console.log(obData) 3391 3392 $.request(requestFunctionName, { 3393 data: obData 3394 }) 3395 } 3396 3397 function getSummerny () { 3398 let summerny = '' 3399 if (filterSumr?.checked) { 3400 summerny = filterSumr.getAttribute('data-value') 3401 } else if (filterNewy?.checked) { 3402 summerny = filterNewy.getAttribute('data-value') 3403 } 3404 return summerny 3405 } 3406 3407 function getLangSubjectResult () { 3408 let subjects_result = '' 3409 try{ 3410 const subjects_items = document.querySelectorAll('.langs-tile__filter-input_subject:checked') 3411 subjects_items.forEach((item, i) => { 3412 if (i > 0) subjects_result += '|' 3413 subjects_result += item.value 3414 }) 3415 return subjects_result 3416 }catch(e){} 3417 } 3418 3419 3420 function moreBtnInit () { 3421 const moreBtn = filterBlock.querySelector('[data-role="more-btn"]') 3422 if (moreBtn) { 3423 const newBtn = replaceBtn(moreBtn) 3424 newBtn.addEventListener('click', () => makeFiltration(newBtn.getAttribute('data-v'))) 3425 } 3426 } 3427 3428 function replaceBtn (oldElement) { 3429 const newElement = oldElement.cloneNode(true) 3430 oldElement.parentNode.replaceChild(newElement, oldElement) 3431 return newElement 3432 } 3433 3434 3435 function tmore_bInit () { 3436 try { 3437 const moreBtns = document.querySelectorAll('.tmore_b') 3438 moreBtns.forEach(btn => { 3439 const newBtn = replaceBtn(btn) 3440 newBtn.addEventListener('click', () => request(newBtn)) 3441 }) 3442 } catch (error) { 3443 } 3444 3445 3446 3447 } 3448 function request (moreBtn) { 3449 var attr = moreBtn?.getAttribute('data-v') || 1 3450 var attr_g = filtered_elements.querySelector('[data-element="tile__tab-input"]:checked')?.getAttribute('data-g') || '' 3451 var attr_s = filtered_elements.querySelector('[data-element="tile__subject-input"]:checked')?.getAttribute('data-s') || '' 3452 var attr_utm = filtered_elements.getAttribute('data-utm') 3453 // console.log('attr: ', attr, 'attr_g: ', attr_g, 'attr_s: ', attr_s, 'attr_utm: ', attr_utm); 3454 $('.tile__tileb.active').html("<div class='tile-loader'></div>"); 3455 if ((typeof attr !== 'undefined' && attr !== false) && (typeof attr_g !== 'undefined' && attr_g !== false)) { 3456 let summerny = '' 3457 if (filterSumr?.checked) { 3458 summerny = filterSumr.getAttribute('data-value') 3459 } else if (filterNewy?.checked) { 3460 summerny = filterNewy.getAttribute('data-value') 3461 } 3462 $.request('MainFunctions::onPaginateSingleModel', { 3463 data: { 3464 'pagePaginate': attr, 3465 'grade': attr_g, 3466 'subject': attr_s, 3467 'utm_t': attr_utm, 3468 'summerny': summerny, 3469 } 3470 }); 3471 3472 } 3473 3474 } 3475 3476 function tileSubjectInit () { 3477 if (tileSubjectCurrent) tileSubjectCurrent.addEventListener('click', toggleSubjectFilter) 3478
3479 tileSubjectInputs.forEach((input) => { 3480 input.addEventListener('change', updateFilter) 3481 }) 3482 3483 function updateFilter () { 3484 tileSubjectCurrentValueSpan.innerHTML = this.getAttribute('data-text') 3485 tileSubjectCurrent.classList.add('value-selected') 3486 request() 3487 } 3488 } 3489 3490 function toggleSubjectFilter (e) { 3491 e.stopPropagation() 3492 this.classList.toggle('active') 3493 filtered_elements.classList.toggle('filtered_elements_z-index-max') 3494 body.classList.toggle('no-scroll-lg') 3495 } 3496 3497 function resetSubjectFilter (e) { 3498 e?.stopPropagation?.() 3499 tileSubjectCurrentValueSpan.innerHTML = tileSubjectCurrentValueSpan.getAttribute('data-default-text') 3500 tileSubjectCurrent.classList.remove('value-selected') 3501 const selectedSubject = document.querySelector('[data-element="tile__subject-input"]:checked') 3502 if (selectedSubject) selectedSubject.checked = false 3503 request() 3504 } 3505 3506 function closeSubjectFilter () { 3507 const tileSubjectCurrent = document.querySelector('[data-element="tile__subject-current"]') 3508 if (tileSubjectCurrent) tileSubjectCurrent.classList.remove('active') 3509 filtered_elements.classList.remove('filtered_elements_z-index-max') 3510 body.classList.remove('no-scroll-lg') 3511 } 3512 3513 function tileInit (tile) { 3514 const tileTabs = tile.querySelectorAll('[data-element="tile__tab-input"]') 3515 const tiles = tile.querySelectorAll('.tile__tile') 3516 const tileCounters = tile.querySelectorAll('.tile__nav-counter') 3517 const btnMoreArray = tile.querySelectorAll('.tile__tileb') 3518 3519 const tabs = tile.querySelectorAll('.tile__subject-tab') 3520 const headline = tile.querySelector('.tile__subject-headline') 3521 const subjectInputs = tile.querySelectorAll('.tile__subject-input') 3522 3523 let timeout 3524 let firstToggle = true 3525
3526 tabs.forEach((tab) => { 3527 tab.addEventListener('click', changeTab) 3528 tab.addEventListener('mouseenter', changeTab) 3529 }) 3530 3531 const activeTab = tile.querySelector('.tile__subject-tab.active') 3532 if (!activeTab) { 3533 const firstNotHideTab = tile.querySelector('.tile__subject-tab:not(.hide)') 3534 if (firstNotHideTab) firstNotHideTab.click() 3535 } 3536 3537 function changeTab (e) { 3538 e.stopPropagation() 3539 clearTimeout(timeout) 3540 timeout = setTimeout(() => toggle(this),100) 3541 3542 function toggle (that) { 3543 if (!that.closest('.tile__subject-inner')?.querySelector('.tile__subject-tab:hover') && !firstToggle && e.type !== 'click') return 3544 firstToggle = false 3545 const oldTab = tile.querySelector('.tile__subject-tab.active') 3546 if (oldTab) oldTab.classList.remove('active') 3547 3548 that.classList.add('active') 3549 headline.innerHTML = that.getAttribute('data-text') 3550 3551 const subjectIndexes = getParsedData(that, 'data-index') 3552 3553 subjectInputs.forEach((subjectInput) => { 3554 const inputValues = subjectInput.value.split('|') 3555 const isAllowed = subjectIndexes.some(val => inputValues.includes(val)) 3556 console.log('inputValues - '+inputValues); 3557 console.log('subjectIndexes - '+subjectIndexes); 3558 console.log('isAllowed - '+isAllowed); 3559 if (isAllowed) { 3560 subjectInput.closest('.tile__subject-label').classList.remove('hide') 3561 } else { 3562 subjectInput.closest('.tile__subject-label').classList.add('hide') 3563 } 3564 }) 3565 } 3566 } 3567 3568 tileTabs.forEach((tab) => { 3569 tab.addEventListener('change', toggleTab) 3570 }) 3571 3572 function toggleTab () { 3573 const oldBtnMore = filtered_elements.querySelector('.tile__tileb.active') 3574 if (oldBtnMore) oldBtnMore.classList.remove('active') 3575 3576 const oldActiveTile = filtered_elements.querySelector('.tile__tile.active') 3577 if (oldActiveTile) oldActiveTile.classList.remove('active') 3578 3579 const oldActiveTileCounter = filtered_elements.querySelector('.tile__nav-counter.active') 3580 if (oldActiveTileCounter) oldActiveTileCounter.classList.remove('active') 3581 3582 const id = this.value 3583 tiles[id].classList.add('active') 3584 tileCounters[id].classList.add('active') 3585 btnMoreArray[id].classList.add('active') 3586 syncTileTabs(id) 3587 sortSubjects(this) 3588 sortSubjectsTabs() 3589 resetSubjectFilter() 3590 } 3591 3592 function getParsedData (element, attribute) { 3593 if (!element) return [] 3594 try { 3595 const data = element.getAttribute(attribute) 3596 return data ? JSON.parse(data) : [] 3597 } catch (e) { 3598 console.error(`ÐÑибка паÑÑинга JSON в аÑÑибÑÑе ${attribute}:`, e) 3599 return [] 3600 } 3601 } 3602 3603 function sortSubjectsTabs () {
3604 tabs.forEach((tab) => { 3605 const indexes = getParsedData(tab, 'data-index') 3606 let counter = 0 3607 tileSubjectInputs.forEach(input => { 3608 const inputValues = input.value.split('|') 3609 const isAllowed = inputValues.some(val => indexes.includes(val)) 3610 if (isAllowed && !input.closest('.tile__subject-label')?.classList.contains('disabled')) counter += 1 3611 }) 3612 const counterSpan = tab.querySelector('span') 3613 counterSpan.innerHTML = counter 3614 if (counterSpan) counterSpan.innerHTML = counter 3615 if (counter === 0) { 3616 tab.classList.add('hide') 3617 } else { 3618 tab.classList.remove('hide') 3619 } 3620 }) 3621 const activeTab = tile.querySelector('.tile__subject-tab.active') 3622 if (activeTab) { 3623 if (activeTab.classList.contains('hide')) { 3624 activeTab.classList.remove('active') 3625 const firstNotHideTab = tile.querySelector('.tile__subject-tab:not(.hide)') 3626 if (firstNotHideTab) firstNotHideTab.click() 3627 } 3628 } 3629 } 3630 3631 function sortSubjects (tab) { 3632 const subjects = getParsedData(tab, 'data-subjects') 3633 const allowedStrings = subjects.map(String) 3634 tileSubjectInputs.forEach(input => { 3635 const parent = input.closest('.tile__subject-label') 3636 if (!parent) return 3637 const inputValues = input.value.split('|') 3638 const isAllowed = inputValues.some(val => allowedStrings.includes(val)) 3639 parent.classList.toggle('disabled', !isAllowed) 3640 }) 3641 } 3642 3643 function syncTileTabs(id) { 3644 tileTabs.forEach((tab) => { 3645 if (tab.value === id) { 3646 tab.checked = true 3647 tab.setAttribute('checked', true) 3648 } 3649 }) 3650 } 3651 } 3652 3653 3654 3655 function togglePrice (node) { 3656 if (node) { 3657 togglePriceHandler(node) 3658 } else { 3659 const items = filtered_elements?.querySelectorAll(".all-courses__item") 3660 items.forEach((item) => { 3661 togglePriceHandler(item) 3662 }) 3663 } 3664 function togglePriceHandler (item) { 3665 const toggle = item.querySelectorAll('.all-courses__radio-input') 3666 if (!toggle.length) return 3667 const boxes = item.querySelectorAll('.all-courses__box') 3668 const textReplace = item.querySelector('.all-courses__info.text-replace') 3669 let texts 3670 if (textReplace) { 3671 texts = textReplace.querySelectorAll('.all-courses__info-span') 3672 } 3673 for (let i = 0; i < toggle.length; i++) { 3674 toggle[i].addEventListener('change', toggleBoxes) 3675 if (texts) toggle[i].addEventListener('change', toggleTexts) 3676 } 3677 3678 function toggleBoxes () { 3679 for (let i = 0; i < boxes.length; i++) { 3680 if (boxes[i].classList.contains('hide')) { 3681 boxes[i].classList.remove('hide') 3682 } else { 3683 boxes[i].classList.add('hide') 3684 } 3685 } 3686 } 3687 3688 function toggleTexts () { 3689 for (let i = 0; i < texts.length; i++) { 3690 if (texts[i].classList.contains('hide')) { 3691 texts[i].classList.remove('hide') 3692 } else { 3693 texts[i].classList.add('hide') 3694 } 3695 } 3696 } 3697 } 3698 } 3699 3700 function famPriceInit (famPrice) { 3701 const tabs = famPrice.querySelectorAll('.fam-price__tab') 3702 const slides = famPrice.querySelectorAll('.fam-price__slide') 3703 3704 for (let i = 0; i < tabs.length; i++) { 3705 tabs[i].addEventListener('click', toggleSlide) 3706 } 3707 3708 function toggleSlide () { 3709 const oldTabActive = famPrice.querySelector('.fam-price__tab.active') 3710 if (oldTabActive) oldTabActive.classList.remove('active') 3711 this.classList.add('active') 3712 3713 const oldActiveSlide = famPrice.querySelector('.fam-price__slide.active') 3714 if (oldActiveSlide) oldActiveSlide.classList.remove('active') 3715 3716 const newSlide = slides[this.getAttribute('data-id')] 3717 newSlide.classList.add('active') 3718 } 3719 3720 const famPriceLists = famPrice.querySelectorAll('.fam-price__list') 3721 3722 for (let i = 0; i < famPriceLists.length; i++) { 3723 const list = famPriceLists[i] 3724 const items = list.querySelectorAll('.fam-price__item') 3725 const btn = list.querySelector('.fam-price__more') 3726 3727 if (items.length > 8) { 3728 btn.style.display = 'flex' 3729 btn.addEventListener('click', toggleList) 3730 hideList() 3731 } 3732 3733 function hideList () { 3734 list.classList.remove('active') 3735 for (let j = items.length - 1; j > 7; j--) { 3736 items[j].style.display = 'none' 3737 } 3738 btn.innerHTML = `ÐоказаÑÑ ÐµÑÑ +${items.length - 8}` 3739 } 3740 3741 function showList () { 3742 list.classList.add('active') 3743 for (let j = items.length - 1; j > 7; j--) { 3744 items[j].style.display = 'flex' 3745 } 3746 btn.innerHTML = `СвеÑнÑÑÑ` 3747 } 3748 3749 function toggleList () { 3750 if (list.classList.contains('active')) { 3751 hideList() 3752 } else { 3753 showList() 3754 } 3755 } 3756 } 3757 } 3758 3759} 3760 3761 3762const footerNewDoc = document.querySelector('[data-element="footer-new-doc"]') 3763 3764if (footerNewDoc) footerNewDocInit() 3765 3766function footerNewDocInit () { 3767 footerNewDoc.addEventListener('click', () => footerNewDoc.classList.toggle('active')) 3768} 3769 3770const footerQuizDocsSpan = document.querySelector('.footer-quiz__docs-span'); 3771 3772if (footerQuizDocsSpan) footerQuizDocsSpanInit() 3773 3774function footerQuizDocsSpanInit () { 3775 footerQuizDocsSpan.addEventListener('click', () => { 3776 footerQuizDocsSpan.classList.toggle('footer-quiz__docs-span_active'); 3777 }) 3778} 3779 3780const footerTitleArray = document.querySelectorAll('[data-element="footer__title"]') 3781 3782if (footerTitleArray.length) footerTitleArrayInit() 3783 3784function footerTitleArrayInit () { 3785 for (let i = 0; i < footerTitleArray.length; i++) { 3786 footerTitleArray[i].addEventListener('click', toggleFooterTitle) 3787 } 3788 3789 function toggleFooterTitle () { 3790 this.classList.toggle('active') 3791 } 3792} 3793 3794const FORM_MAP = { 3795 'external-form': ['externalFormData'], 3796 'phone-form': ['phoneFormData'], 3797 'review-form': ['reviewFormData'], 3798 'family-order-form': ['consultFormData'], 3799 'order-form': ['orderFormData'], 3800 'order-form-email': ['orderFormEmailData'], 3801 'order-form-teacher': ['orderFormTeacherData'], 3802 'trial': ['trialFormData'], 3803 'blog-phone': ['blogPhoneFormData'], 3804 'blog-email': ['blogEmailFormData'], 3805 'blog-phone-email': ['blogPhoneEmailFormData'], 3806 'newsletter': ['newsletterFormData'], 3807 'pre-cap__form': ['preFormData'], 3808 'pre-reg__form': ['preFormData'], 3809 'pre-webinar-cap__form': ['preWebinarFormData'], 3810 'library-popup': ['libraryPopupFormData'], 3811 'newsletter-off-form': ['newsletterOffForm'], 3812 'trial-lessons': ['trialLessons'],
3813 'lib-access': ['libAccess'], 3814 'college_new_cap__form': ['collegeNewFormData'], 3815 'college-land-order__form':['collegeLandOrderForm'], 3816 'ege-cap__form_college-ai':['egeCapFormCollegeAi'], 3817 'ege-cap__form_vacancy-cap':['egeCapFormVacancyCap'], 3818 'try-free-popup-order': ['tryFreePopupOrder'], 3819} 3820 3821 3822function getType(elementName) { 3823 return FORM_MAP[elementName] || null 3824} 3825 3826Object.keys(FORM_MAP).forEach((elementName) => { 3827 const pair = getType(elementName) 3828 if (!pair) return 3829 const [dataType] = pair 3830 document.querySelectorAll(`[data-element="${elementName}"]`).forEach((el) => globalFormInit(el, dataType)) 3831}) 3832 3833window.captchaWidget = null 3834let captchaPassed = false 3835 3836// console.log('ð ÐниÑиализаÑÐ¸Ñ ÐºÐ°Ð¿Ñи...'); 3837// try { 3838// window.captchaWidget = window.smartCaptcha.render('captcha-container', { 3839// sitekey: 'ysc1_y2y3Y8WvF9G06BcBNlGlgx4nfWsr2ms4kPjqJ0ite8d30716', // <- пÑовеÑÑÑе клÑÑ! 3840// invisible: true, 3841// callback: (token) => { 3842// console.log('â Callback капÑи вÑзван Ñ Ñокеном:', token) 3843// captchaToken = token 3844// captchaPassed = true 3845// } 3846// }); 3847// } catch (e) { 3848 3849// } 3850// console.log('ð ÐÐ¸Ð´Ð¶ÐµÑ Ñоздан:', window.captchaWidget); 3851 3852 3853async function sendGlobalFormCommonAnalytics (globalForm) { 3854 const goal = globalForm.getAttribute('data-form-goal'); 3855 if (goal) { 3856 const dataFormType = globalForm.getAttribute('data-form'); 3857 await analytics.ym(goal, { [goal] : dataFormType }) 3858 } else { 3859 await sendCommonAnalytics('submit_form', globalForm) 3860 } 3861} 3862 3863 3864 3865function globalFormInit (form, type) { 3866 3867 3868 const globalForm = form 3869 const btnSubmit = globalForm.querySelector('.btn-warning') 3870 const selectPlaceholder = globalForm.querySelector('.modal-order-new__select-placeholder') 3871 const input = globalForm.querySelector("[data-element='input-phone-intl']") 3872 3873 const classSelectTop = globalForm.querySelector('.modal-order-new__select-top') 3874 const inputHidden = globalForm.querySelector("[data-element='input-phone-hidden']") 3875 const linkTo = globalForm.getAttribute("data-docex") 3876 3877 const policy = form.querySelector('[name="policy"]') 3878 const utm_input = globalForm.querySelector('[name="utm"]') 3879 3880 const classSelectInputs = globalForm.querySelectorAll('.modal-order-new__select-input') 3881 3882 for (let i = 0; i < classSelectInputs.length; i++) { 3883 classSelectInputs[i].addEventListener('change', validate) 3884 classSelectInputs[i].addEventListener('change', () => { 3885 if (classSelectTop) classSelectTop.classList.remove('error') 3886 }) 3887 } 3888 3889 let iti 3890 let data_phone_pattern_exists = false; 3891// console.log(input) 3892 if (input) { 3893 if (input.hasAttribute('data-phone-pattern')) { 3894 data_phone_pattern_exists = true; 3895 } 3896 if(data_phone_pattern_exists){ 3897 input.addEventListener('input', function () { 3898 let tempValue = input.value 3899 const cleanNumber = tempValue.replace(/[^+\d]/g, '') 3900 inputHidden.value = cleanNumber 3901 validate() 3902 }) 3903 }else{ 3904 iti = window.intlTelInput(input, { 3905 utilsScript: "../libs/intlTelInputWithUtils.min", 3906 initialCountry: 'ru', 3907 separateDialCode: true, 3908 strictMode: true 3909 }) 3910 3911 input.addEventListener('input', function () { 3912 let tempValue = input.value 3913 inputHidden.value = input.value 3914 const cleanNumber = tempValue.replace(/[^+\d]/g, '') 3915 if (iti.selectedCountryData.dialCode === "7" && cleanNumber.length > 10) { 3916 inputHidden.value = cleanNumber.substring(cleanNumber.length - 10) 3917 input.value = cleanNumber.substring(cleanNumber.length - 10) 3918 } 3919 inputHidden.value = iti.selectedCountryData.dialCode + ' ' + inputHidden.value 3920 validate() 3921 }) 3922 } 3923 } 3924 3925 function resetError () { 3926 if (input) input.classList.remove("error") 3927 } 3928 3929 let inputSms 3930 let isSubmitting = false 3931 3932 const email = globalForm.querySelector('[name="email"]') 3933 if (email) { 3934 email.addEventListener('input', () => validate) 3935 // email.addEventListener('change', () => validateEmail(email)) 3936 } 3937 3938 const textarea = globalForm.querySelector('[name="content"]') 3939 if (textarea && textarea?.hasAttribute('data-required')) { 3940 textarea.addEventListener('input', validate) 3941 textarea.addEventListener('input', () => textarea.classList.remove('error')) 3942 } 3943 3944 3945 const name = globalForm.querySelector('[name="name"]') 3946 if (name) { 3947 name.addEventListener('input', validate) 3948 name.addEventListener('input', () => name.classList.remove('error')) 3949 } 3950 3951 if (policy) { 3952 policy.addEventListener('input', validate) 3953 policy.addEventListener('input', () => policy.closest('label').classList.remove('error-text')) 3954 } 3955 3956 function validate () { 3957 const isNameValid = name ? name?.value : true 3958 const isTextareaValid = (textarea && textarea?.hasAttribute('data-required')) ? textarea?.value : true 3959 const isPhoneValid = input ? iti?.isValidNumber() : true 3960 const isEmailValid = email ? validateEmail(email) : true 3961 const isPolicyValid = policy ? policy?.checked : true 3962 const isSelectValid = classSelectInputs.length ? globalForm.querySelector('.modal-order-new__select-input:checked') : true 3963 if (!isNameValid || !isEmailValid || !isSelectValid || !isPhoneValid || !isPolicyValid || !isTextareaValid) { 3964 btnSubmit.classList.add('btn-fake-disabled') 3965 } else { 3966 btnSubmit.classList.remove('btn-fake-disabled') 3967 } 3968 } 3969 3970 3971 globalForm.addEventListener('submit', async (e) => { 3972 e.preventDefault() 3973 e.stopImmediatePropagation(); 3974 3975 const isToggleThanksBlock = globalForm.hasAttribute('data-toggle-thanks-block') 3976 3977 resetError() 3978 3979 let isValid = true 3980 3981 if (classSelectTop) { 3982 const isSelectChecked = globalForm.querySelector('.modal-order-new__select-input:checked') 3983 if (!isSelectChecked) { 3984 classSelectTop.classList.add('error') 3985 selectPlaceholder.innerHTML = 'ÐÑбеÑиÑе клаÑÑ' 3986 isValid = false 3987 } 3988 } 3989 3990 if (email) { 3991 if (!validateEmail(email)) { 3992 email.classList.add('error') 3993 if (!email.value) email.placeholder = 'ÐведиÑе поÑÑÑ' 3994 isValid = false 3995 } 3996 } 3997 3998 if (name) { 3999 if (!name.value) { 4000 name.classList.add('error') 4001 name.placeholder = `ÐведиÑе имÑ` 4002 isValid = false 4003 } 4004 } 4005 4006 if (textarea && textarea?.hasAttribute('data-required')) { 4007 if (!textarea.value) { 4008 textarea.classList.add('error') 4009 textarea.placeholder = `ÐведиÑе вопÑоÑ` 4010 isValid = false 4011 } 4012 } 4013 4014 4015 if (input) { 4016 if (!iti?.isValidNumber()) { 4017 input.classList.add("error") 4018 if (input && !input?.value) input.placeholder = `ÐведиÑе ÑелеÑон` 4019 } 4020 } 4021 4022 if (!isValid) return 4023 4024 4025 if (input && !input?.value?.trim()) { 4026 input.classList.add("error") 4027 } else if (iti?.isValidNumber() || !input || type == 'libraryPopupFormData' || type == 'blogPhoneFormData' || type == 'blogPhoneEmailFormData' || data_phone_pattern_exists) { 4028 4029 4030 4031 inputSms = `<input class="modal-order-new__input modal-order-new__input_sms" required name="sms_code" type="text" placeholder="ÐведиÑе код из ÑмÑ">` 4032 4033 4034 if (email) { 4035 email_value = email.value 4036 } 4037 4038 btnSubmit.disabled = true; 4039 const dataRequest = globalForm.getAttribute('data-request'); 4040 if (type === 'preFormData') { 4041 e.stopPropagation() 4042 if (globalForm.classList.contains('predzaps-new-cap__form') || globalForm.classList.contains('predzaps-new-order__form') || globalForm.classList.contains('college_new__form')) { 4043 btnSubmit.classList.add('loading') 4044 } 4045 const loader = document.querySelector('.form-loader') 4046 if (loader) loader.classList.add('active') 4047 if (checkHoneypot()) return 4048 const formData = new FormData(globalForm) 4049 const formObject = {} 4050 formData.forEach((value, key) => {
4051 formObject[key] = value; 4052 }) 4053 $.request('MainFunctions::' + dataRequest, { 4054 data: formObject, 4055 success: async function(response) { 4056 4057 let hasErrors = false 4058 4059 for (let key in response) { 4060 if (key.startsWith('.')) { 4061 const className = key.substring(1) 4062 const element = document.querySelector('.' + className) 4063 4064 if (element) { 4065 element.innerHTML = response[key] 4066 hasErrors = true; 4067 btnSubmit.disabled = false; 4068 if (globalForm.classList.contains('predzaps-new-cap__form') || globalForm.classList.contains('predzaps-new-order__form') || globalForm.classList.contains('college_new__form')) { 4069 btnSubmit.classList.remove('loading') 4070 } 4071 } 4072 } 4073 } 4074 if (hasErrors) { 4075 isSubmitting = false 4076 return 4077 } 4078 await sendGlobalFormCommonAnalytics(globalForm) 4079 4080 const utmValue = utm_input ? utm_input.value.trim() : '' 4081 clearForm() 4082 const params = new URLSearchParams() 4083 params.set('cemail', email_value) 4084 const utmParams = new URLSearchParams(utmValue.replace(/^\?+/, ''))
4085 utmParams.forEach((value, key) => { 4086 params.set(key, value) 4087 }) 4088 const finalLink = linkTo + '?' + params.toString() 4089 location.assign(finalLink) 4090 }, 4091 error: function(error) { 4092 // console.error('â ÐÑибка оÑпÑавки:', error); 4093 isSubmitting = false 4094 return false 4095 } 4096 }) 4097 return false 4098 4099 // setTimeout(() => { 4100 // globalForm.submit(); 4101 // setTimeout(() => { 4102 // clearForm(); 4103 // location.assign(linkTo + `?cemail=${email_value}`); 4104 // // location.assign(linkTo + '?email='+email_value) 4105 // }, 100) 4106 // }, 100) 4107 } else { 4108 let linkTo_ = linkTo; 4109 let linkTo_base = linkTo_ 4110 if (utm_input) { 4111 utm_f = utm_input.value; 4112 if(utm_f != null && utm_f != '' && utm_f != undefined){ 4113 }else{ 4114 utm_f = '' 4115 } 4116 if (utm_f.length > 0) { 4117 linkTo_ = linkTo_ + utm_f; 4118 } 4119 } 4120 if (isTargetLink(linkTo_base)) { 4121 if (cookieParams) { 4122 linkTo_ += (linkTo_.includes("?") ? "&" : "?") + cookieParams; 4123 } 4124 } 4125 4126 if (checkHoneypot()) return 4127 4128 4129 4130 try { 4131 e.stopPropagation(); 4132 console.log('isSubmitting:', isSubmitting); 4133 if (isSubmitting) return false; 4134 4135 // if (!captchaPassed) { 4136 // // console.log('ð ÐÑзов execute...'); 4137 captchaToken = null; 4138 // window.smartCaptcha.execute(window.captchaWidget); 4139 4140 // await new Promise((resolve, reject) => { 4141 // const checkToken = setInterval(() => { 4142 // if (captchaToken) { 4143 // clearInterval(checkToken); 4144 // resolve(); 4145 // } 4146 // }, 100); 4147 4148 // setTimeout(() => { 4149 // clearInterval(checkToken); 4150 // reject(new Error('ТаймаÑÑ ÐºÐ°Ð¿Ñи')); 4151 // }, 100000); 4152 // }); 4153 4154 // // console.log('â Токен полÑÑен:', captchaToken); 4155 // } else { 4156 // // console.log('â ÐапÑа Ñже пÑойдена, пÑопÑÑкаем пÑовеÑкÑ'); 4157 // } 4158 4159 4160 // if (captchaToken) { 4161 // console.log(globalForm); 4162 isSubmitting = true; 4163 // console.log('ÐÑпÑавка ÑоÑмÑ:', globalForm); 4164 4165 const dataRequest = globalForm.getAttribute('data-request'); 4166 const formData = new FormData(globalForm); 4167 const formObject = {}; 4168 formData.forEach((value, key) => { 4169 formObject[key] = value; 4170 }); 4171 formObject['smart-token'] = captchaToken; 4172 const isResend = globalForm.querySelector('.form-enter-sms-resend.active') 4173 if (isResend) { 4174 formObject['resend_sms'] = true 4175 const timer = globalForm.querySelector('.form-enter-sms-resend') 4176 timer.classList.remove('active') 4177 timer.innerHTML = 'ÐолÑÑиÑÑ Ð½Ð¾Ð²Ñй код ÑеÑез <span>02:00</span>' 4178 } else { 4179 const sms_code = globalForm.querySelector('input[name="sms_code"]')?.value 4180 if (sms_code) formObject['sms_code'] = sms_code 4181 } 4182 4183 const callPhoneButton = globalForm.querySelector('[data-role="global-form-call-phone"]') 4184 if (callPhoneButton) formObject['already_call'] = true 4185 4186 //formObject.captcha_token = captchaToken; 4187 4188 clearErrorMessages(globalForm) 4189 $.request('MainFunctions::' + dataRequest, { 4190 data: formObject, 4191 success: async function(response) { 4192 // console.log('ÐÑвеÑ:', response); 4193 let hasErrors = false;
4194 4195 for (let key in response) { 4196 if (key.startsWith('.')) { 4197 const className = key.substring(1); 4198 const element = document.querySelector('.' + className); 4199 4200 if (element) { 4201 element.innerHTML = response[key]; 4202 hasErrors = true; 4203 btnSubmit.disabled = false; 4204 const isResendBlockReady = globalForm.querySelector('.form-enter-sms-resend.ready') 4205 if (isResendBlockReady) { 4206 isResendBlockReady.classList.add('active') 4207 } 4208 } 4209 } 4210 } 4211 4212 if (hasErrors) { 4213 isSubmitting = false; 4214 return; 4215 } 4216 4217 if (response['requires_verification']) { 4218 showSmsInput(response) 4219 if (!globalForm.classList.contains('form-enter-sms-code')) showSmsInput(response) 4220 btnSubmit.disabled = false 4221 isSubmitting = false; 4222 } else if (response['requires_phonecall_verification']) { 4223 showFormPhoneCall(response) 4224 btnSubmit.disabled = false 4225 isSubmitting = false; 4226 } else { 4227 await sendGlobalFormCommonAnalytics(globalForm) 4228 clearForm(); 4229 if (isToggleThanksBlock) { 4230 globalForm.classList.add('global-form-thanks-state') 4231 } else if (type === 'preFormData') { 4232 location.assign(linkTo + `?cemail=${email_value}`); 4233 } else if (type === 'collegeNewFormData' || type === 'collegeLandOrderForm') { 4234 await analytics.ym('send-main-form') 4235 await analytics.mailru('lead', true) 4236 location.assign(linkTo_); 4237 } else if (type === 'trialLessons') { 4238 await analytics.gtag('generate_lead') 4239 location.assign(linkTo_); 4240 } else if (globalForm.id === 'fixAsk') { 4241 if (window.tfPopups) window.tfPopups.close('fixAsk') 4242 if (window.tfPopups) window.tfPopups.open('fixDone') 4243 } else { 4244 location.assign(linkTo_); 4245 } 4246 } 4247 }, 4248 error: function(error) { 4249 // console.error('â ÐÑибка оÑпÑавки:', error); 4250 isSubmitting = false; 4251 } 4252 }); 4253 4254 return false; 4255 // }else{ 4256 // return false; 4257 // } 4258 4259 } catch (error) { 4260 // console.error('â ÐÑибка:', error); 4261 // alert('ÐÑибка пÑовеÑки капÑи'); 4262 return false; 4263 } 4264 } 4265 4266 } else { 4267 input.classList.add("error") 4268 } 4269 4270 }) 4271 4272 function clearErrorMessages (form) { 4273 const v_message_block = form.querySelector('.v_message_block') 4274 if (!v_message_block) return 4275 v_message_block.innerHTML = '' 4276 } 4277 4278 function showFormPhoneCall (response) { 4279 globalForm.classList.add('form-enter-sms-code') 4280 const submitButton = globalForm.querySelector('.btn-warning') || 4281 globalForm.querySelector('.btn-orange') 4282 if (submitButton) { 4283 submitButton.innerHTML = 'Уже позвонил' 4284 submitButton.classList.add('form-enter-sms-btn-transparent') 4285 submitButton.insertAdjacentHTML('beforebegin', `<div class="form-enter-sms-call">ÐожалÑйÑÑа, позвониÑе по ÑÑÐ¾Ð¼Ñ Ð±ÐµÑплаÑÐ½Ð¾Ð¼Ñ Ð½Ð¾Ð¼ÐµÑÑ Ð´Ð»Ñ Ð¿ÑÐ¾Ñ Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð²ÐµÑиÑикаÑии!</div>`) 4286 submitButton.insertAdjacentHTML('beforebegin', `<a href="tel:${response['call_phone']}" class="modal-order-new__button btn-warning" data-role="global-form-call-phone" type="button">ÐозвониÑÑ</a>`) 4287 submitButton.insertAdjacentHTML('afterend', `<div class="form-enter-sms-note">Ðжидаем звонок Ñ Ð½Ð¾Ð¼ÐµÑа <br> ${inputHidden.value}</div>`) 4288 4289 } 4290 const title = globalForm.querySelector('.modal-order-new__title') || 4291 globalForm.querySelector('.ege-cap__title') || 4292 globalForm.querySelector('.pre-cap__headline') || 4293 globalForm.querySelector('[data-element="form-enter-sms-title"]') 4294 if (title) { 4295 title.innerHTML = `<a href="tel:${response['call_phone']}" class="form-enter-sms-phone">${response['call_phone_pretty']}</a>` 4296 } 4297 } 4298 4299 function showSmsInput () { 4300 if (globalForm.classList.contains('form-enter-sms-code')) return 4301 const title = globalForm.querySelector('.modal-order-new__title') || 4302 globalForm.querySelector('.ege-cap__title') || 4303 globalForm.querySelector('.pre-cap__headline') || 4304 globalForm.querySelector('.ege-order__title') || 4305 globalForm.querySelector('[data-element="form-enter-sms-title"]') 4306 if (title) { 4307 title.innerHTML = 'ÐведиÑе код подÑвеÑждениÑ' 4308 } 4309 const submitBtn = globalForm.querySelector('.btn-warning') || 4310 globalForm.querySelector('.btn-orange') 4311 const formatPhone = formatPhoneNumber(inputHidden.value) 4312 submitBtn.insertAdjacentHTML('beforebegin', `<div class="form-enter-sms-text">ÐÑпÑавили код на Ð½Ð¾Ð¼ÐµÑ <span>${formatPhone}</span></div>`) 4313 if (inputSms) submitBtn.insertAdjacentHTML('beforebegin', inputSms) 4314 submitBtn.insertAdjacentHTML('afterend', `<button type="button" class="form-enter-sms-resend">ÐолÑÑиÑÑ Ð½Ð¾Ð²Ñй код ÑеÑез <span>02:00</span></button>`) 4315 globalForm.classList.add('form-enter-sms-code') 4316 initResendSmsTimer() 4317 } 4318 4319 function formatPhoneNumber(value) { 4320 const trimmed = value.trim() 4321 const clean = trimmed.replace(/\D/g, '') 4322 4323 const isRussian = ( 4324 clean.length === 11 && 4325 (trimmed.startsWith('+7') || trimmed.startsWith('7') || trimmed.startsWith('8')) 4326 ) 4327 4328 if (isRussian) { 4329 const match = clean.slice(-10).match(/^(\d{3})(\d{3})(\d{2})(\d{2})$/) 4330 if (match) { 4331 return `+7 (${match[1]}) ${match[2]}-${match[3]}-${match[4]}` 4332 } 4333 } 4334 return trimmed.startsWith('+') ? trimmed : '+' + trimmed 4335 } 4336 4337 4338 function initResendSmsTimer () { 4339 const timer = globalForm.querySelector('.form-enter-sms-resend') 4340 const timerSpan = globalForm.querySelector('.form-enter-sms-resend span') 4341 if (!timer || !timerSpan) return 4342 4343 let timeInSecs 4344 let ticker 4345 4346 timeInSecs = 2 * 60 4347 // timeInSecs = 4 4348 ticker = setInterval(tick, 1000) 4349 4350 function tick() { 4351 let secs = timeInSecs 4352 if (secs <= 0) { 4353 clearInterval(ticker) 4354 timer.classList.add('active') 4355 timer.classList.add('ready') 4356 timer.innerHTML = 'ÐолÑÑиÑÑ Ð½Ð¾Ð²Ñй код' 4357 timer.addEventListener('click', () => { 4358 const sms_code = globalForm.querySelector('input[name="sms_code"]') 4359 if (sms_code) sms_code.value = '' 4360 timer.innerHTML = 'ÐолÑÑиÑÑ Ð½Ð¾Ð²Ñй код ÑеÑез <span>02:00</span>' 4361 timer.classList.remove('ready') 4362 initResendSmsTimer() 4363 const submitEvent = new SubmitEvent("submit") 4364 globalForm.dispatchEvent(submitEvent) 4365 }) 4366 return 4367 } 4368 timeInSecs-- 4369 4370 let mins = Math.floor(secs / 60) 4371 secs %= 60 4372 4373 let displayMins = (mins < 10) ? "0" + mins : mins 4374 let displaySecs = (secs < 10) ? "0" + secs : secs 4375
4376 timerSpan.innerHTML = displayMins + ":" + displaySecs 4377 } 4378 } 4379 4380 4381 function clearForm () { 4382 const inputs = globalForm.querySelectorAll('input') 4383 for (let i = 0; i < inputs.length; i++) { 4384 inputs[i].value = '' 4385 } 4386 } 4387 4388 if (input) input.addEventListener('input', resetError) 4389 4390 function validateEmail (email) { 4391 return /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(email.value) 4392 } 4393 function checkHoneypot() { 4394 const honeypots = form.querySelector('.modal-exter__input') 4395 return honeypots && honeypots?.value 4396 } 4397} 4398 4399// ÐÑовеÑка, наÑинаеÑÑÑ Ð»Ð¸ ÑÑÑлка Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ из ÑелевÑÑ URL 4400function isTargetLink(href) { 4401 const targets = [ 4402 "https://salebot.site/", 4403 "https://s.salebot.pro/", 4404 "https://sbsite.pro/", 4405 "https://r.bothelp.io/max", 4406 "https://vk.com/app7062840", 4407 "https://vk.ru/app7062840" 4408 ]; 4409 return targets.some(prefix => href?.startsWith(prefix)); 4410} 4411 4412// СобиÑаем знаÑÐµÐ½Ð¸Ñ Ð¸Ð· нÑжнÑÑ cookie 4413const cookies = ['_fbc', '_fbp', '_ga', '_ym_uid', 'roistat_visit']; 4414let cookieParams = ''; 4415 4416cookies.forEach(name => { 4417 const value = getCookie(name); 4418 if (value) { 4419 if (cookieParams) cookieParams += '&'; 4420 cookieParams += `${name}=${encodeURIComponent(value)}`; 4421 } 4422}); 4423 4424// ФÑнкÑÐ¸Ñ Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ cookie по имени 4425function getCookie(name) { 4426 const matches = document.cookie.match(new RegExp( 4427 "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=\"?([^\";]*)\"?" 4428 )); 4429 return matches ? decodeURIComponent(matches[1]) : undefined; 4430} 4431 4432const urlParams = location.search.slice(1); // ÑбиÑаем '?' 4433 4434const buttonsModalGenerate = document.querySelectorAll('[data-modal-generate]') 4435 4436for (let i = 0; i < buttonsModalGenerate.length; i++) { 4437 buttonsModalGenerate[i].addEventListener('click', generateModal) 4438} 4439 4440function generateModal (e) { 4441 e.preventDefault() 4442 e.stopImmediatePropagation() 4443 const dataBlock = this.closest('[data-block]')?.getAttribute('data-block') 4444 const form = document.createElement('form') 4445 form.classList.add('modal-order-new') 4446 form.setAttribute('data-request-validate', '') 4447 form.id = 'modal-generated' 4448 form.setAttribute('autocomplete', 'off') 4449 if (dataBlock) form.setAttribute('data-block', dataBlock) 4450 4451 const dataFormType = this.getAttribute('data-form-type') 4452 form.setAttribute('data-form', dataFormType || 'order') 4453 4454 const dataFormGoal = this.getAttribute('data-form-goal') 4455 if (dataFormGoal) form.setAttribute('data-form-goal', dataFormGoal) 4456 4457 4458 const dataRequest = this.getAttribute('data-request') 4459 if (dataRequest) form.setAttribute('data-request', dataRequest) 4460 4461 const dataDocex = this.getAttribute('data-docex') 4462 if (dataDocex) form.setAttribute('data-docex', dataDocex) 4463 4464 const captcha = document.createElement('div') 4465 captcha.classList.add('captcha') 4466 form.appendChild(captcha) 4467 4468 const title = document.createElement('div') 4469 title.classList.add('modal-order-new__title') 4470 title.innerHTML = this.getAttribute('data-title-text') 4471 form.appendChild(title) 4472 4473 const dataText = this.getAttribute('data-text') 4474 if (dataText) { 4475 const text = document.createElement('p') 4476 text.classList.add('modal-order-new__text') 4477 text.innerHTML = dataText 4478 form.appendChild(text) 4479 } 4480 4481 4482 const dataHiddenInputs = this.getAttribute('data-hidden-inputs') 4483 const dataHiddenInputsParsed = dataHiddenInputs ? JSON.parse(dataHiddenInputs) : [] 4484 for (let i = 0; i < dataHiddenInputsParsed.length; i++) { 4485 generateHiddenInput(form, dataHiddenInputsParsed[i].name, dataHiddenInputsParsed[i].value) 4486 } 4487 4488 const dataUtm = this.hasAttribute('data-utm') 4489 if (dataUtm) generateHiddenInput(form, 'utm', this.getAttribute('data-utm')) 4490 4491 const inputExter = `<input class="modal-exter__input" 4492 type="text" 4493 name="${this.getAttribute('data-random-name')}" 4494 style="${this.getAttribute('data-random-style')}" 4495 tabindex="-1" 4496 autocomplete="new-password" 4497 autocorrect="off" 4498 autocapitalize="off" 4499 spellcheck="false"> 4500 ` 4501 form.insertAdjacentHTML('beforeend', inputExter) 4502 4503 const isName = this.getAttribute('data-name') 4504 if (isName) { 4505 const nameHtml = ` 4506 <input class="modal-order-new__input" name="name" placeholder="ÐмÑ" type="text"> 4507 ` 4508 form.insertAdjacentHTML('beforeend', nameHtml) 4509 } 4510 4511 const isPhone = this.getAttribute('data-phone') 4512 if (isPhone) { 4513 const phoneHtml = ` 4514 <input class="modal-order-new__input" name="phone" placeholder="ÐÐ¾Ð¼ÐµÑ ÑелеÑона" type="tel" data-element="input-phone-intl"> 4515 <input name="tel" type="hidden" required data-element="input-phone-hidden"> 4516 ` 4517 form.insertAdjacentHTML('beforeend', phoneHtml) 4518 } 4519 4520 const isEmail = this.getAttribute('data-email') 4521 if (isEmail) { 4522 const emailHtml = `<input class="modal-order-new__input" name="email" placeholder="E-mail" type="email">` 4523 form.insertAdjacentHTML('beforeend', emailHtml) 4524 } 4525 4526 const labels = ` 4527 <label class="modal-order-new__checkbox"> 4528 <input class="modal-order-new__checkbox-input" name="news" type="checkbox"> 4529 <div class="modal-order-new__checkbox-view"></div> 4530 <div class="modal-order-new__checkbox-text"> 4531 ÐÐ°Ñ 4532 <a href="${document.querySelector('body').getAttribute('data-news-agreement')}" data-redirect >CоглаÑие</a> 4533 на полÑÑение инÑоÑмаÑионной и Ñекламной ÑаÑÑÑлки 4534 </div> 4535 </label> 4536 <label class="modal-order-new__checkbox"> 4537 <input class="modal-order-new__checkbox-input" name="policy" type="checkbox"> 4538 <div class="modal-order-new__checkbox-view"></div> 4539 <div class="modal-order-new__checkbox-text"> 4540 ÐÐ°Ñ 4541 <a href="${document.querySelector('body').getAttribute('data-policy-agreement')}" data-redirect >CоглаÑие</a> 4542 на обÑабоÑÐºÑ Ð¿ÐµÑÑоналÑнÑÑ Ð´Ð°Ð½Ð½ÑÑ Ð² ÑооÑвеÑÑÑвие Ñ 4543 <a href="${document.querySelector('body').getAttribute('data-policy-policy')}" data-redirect >ÐолиÑикой</a> 4544 </div> 4545 </label> 4546 ` 4547 const button = `<button class="modal-order-new__button btn-warning btn-fake-disabled">${this.getAttribute('data-button-text')}</button>` 4548 4549 form.insertAdjacentHTML('beforeend', labels) 4550 form.insertAdjacentHTML('beforeend', button) 4551
4552 const v_counter = dataHiddenInputsParsed.find((input) => input.name === 'v') 4553 const v_counter_value = v_counter ? v_counter.value : '' 4554 form.insertAdjacentHTML('beforeend', `<div class="v_message_block v_messages${v_counter_value}"></div>`) 4555 4556 4557 const body = document.querySelector('body') 4558 body.appendChild(form) 4559 4560 const dataFormElement = this.getAttribute('data-form-element') 4561 globalFormInit(form, dataFormElement) 4562 4563 const dataRedirectLinks = form.querySelectorAll('[data-redirect]') 4564 4565 for (let i = 0; i < dataRedirectLinks.length; i++) { 4566 dataRedirectLinks[i].addEventListener('click', dataRedirect) 4567 } 4568 4569 function dataRedirect (e) { 4570 e.preventDefault() 4571 window.open(this.href, '_blank'); 4572 } 4573 4574 4575 $.fancybox.open({ 4576 src: '#modal-generated', 4577 opts: { 4578 touch: false, 4579 afterClose: function() { 4580 const node = document.getElementById('modal-generated') 4581 node.remove() 4582 } 4583 }, 4584 }) 4585} 4586 4587function generateHiddenInput (form, name, value) { 4588 const input = document.createElement('input') 4589 input.type = 'hidden' 4590 input.name = name 4591 input.value = value 4592 form.appendChild(input) 4593} 4594 4595 4596 4597const headerNew = document.querySelector('[data-element="header-new"]') 4598 4599if (headerNew) headerNewInit() 4600 4601function headerNewInit () { 4602 window.addEventListener('scroll', toggleHeader, {passive: true}) 4603 4604 function toggleHeader () { 4605 if (window.scrollY > 0) { 4606 headerNew.classList.add('thin') 4607 } else { 4608 headerNew.classList.remove('thin') 4609 } 4610 } 4611} 4612 4613const header = document.querySelector('[data-element="header"]') 4614 4615if (header) headerInit() 4616 4617function headerInit () { 4618 const stickyHeader = document.querySelector('.sticky-header') 4619 const body = document.querySelector('body') 4620 const headerStages = document.querySelector('.header__stages') 4621 let lastScrollTop = 0 4622 let scrollDown = true 4623 const headerArea = header.querySelector('.header__area') 4624 const reviewsTileSidebar = document.querySelector('.reviews-tile__sidebar') 4625 const nav = header.querySelector('.nav') 4626 const navMenus = header.querySelectorAll('.nav__menu') 4627 const navBtns = header.querySelectorAll('.nav__btns') 4628 const familyScroller = header.querySelector('.nav__area_family .nav__scroller') 4629 const ed1Scroller = header.querySelector('.nav__area_ed1 .nav__scroller') 4630 const headerLayer = document.querySelector('.header-layer') 4631 4632 window.addEventListener('scroll', checkHeader, { passive: true }) 4633 window.addEventListener('scroll', checkScrollDirection, { passive: true }) 4634 window.addEventListener('resize', checkHeader, { passive: true }) 4635 4636 checkHeader() 4637 4638 function checkHeader () { 4639 if (window.scrollY > 10) { 4640 header.classList.add('header_white') 4641 stickyHeader.classList.add('white') 4642 } else { 4643 header.classList.remove('header_white') 4644 stickyHeader.classList.remove('white') 4645 } 4646 4647 4648 } 4649 4650 function checkScrollDirection () { 4651 const st = window.scrollY 4652 if (st - lastScrollTop > 7) { 4653 scrollDown = true 4654 } else if (st - lastScrollTop < -7) { 4655 scrollDown = false 4656 } 4657 lastScrollTop = st <= 0 ? 0 : st 4658 if (scrollDown) { 4659 if (headerStages) header.classList.add('stages-hide') 4660 header.classList.add('thin') 4661 if (reviewsTileSidebar) reviewsTileSidebar.classList.add('space') 4662 } else { 4663 if (headerStages) header.classList.remove('stages-hide') 4664 header.classList.remove('thin') 4665 if (reviewsTileSidebar) reviewsTileSidebar.classList.remove('space') 4666 } 4667 } 4668 4669 4670 const menuBtn = document.querySelector('.header__nav-item_menu') 4671 const layer = document.querySelector('.header__layer') 4672 const stretch = document.querySelector('.trial-stretch') 4673 4674 const navCloseBtns = header.querySelectorAll('.nav__close') 4675 for (let i = 0; i < navCloseBtns.length; i++) { 4676 navCloseBtns[i].addEventListener('click', closeMenu) 4677 } 4678 menuBtn.addEventListener('click', toggleMenu) 4679 layer.addEventListener('click', closeMenu) 4680 4681 function toggleMenu () { 4682 header.classList.toggle('open') 4683 headerLayer.classList.toggle('active') 4684 fixHeaderTop() 4685 fixMenuHeight() 4686 stickyHeader.classList.toggle('open') 4687 body.classList.toggle('no-scroll') 4688 } 4689 4690 function fixHeaderTop () { 4691 if (header.classList.contains('open') && stretch && stretch?.getBoundingClientRect().top === 0) { 4692 header.style.top = stretch.clientHeight + 'px' 4693 } 4694 if (!header.classList.contains('open') && stretch) { 4695 header.style.top = '0' 4696 } 4697 } 4698 4699 function fixMenuHeight () { 4700 if (header.classList.contains('open') && stretch && stretch?.getBoundingClientRect().top === 0 && window.innerWidth < 744) { 4701 const vh = document.documentElement.style.getPropertyValue('--vh') 4702 nav.style.height = `${(vh.slice(0, -2) * 100) - 80 - stretch.clientHeight}px` 4703 for (let i = 0; i < navMenus.length; i++) { 4704 navMenus[i].style.height = `${(vh.slice(0, -2) * 100) - 80 - 70 - stretch.clientHeight}px` 4705 } 4706 for (let i = 0; i < navBtns.length; i++) { 4707 navBtns[i].style.height = `${(vh.slice(0, -2) * 100) - 80 - 70 - stretch.clientHeight}px` 4708 } 4709 if (familyScroller) familyScroller.style.height = `${(vh.slice(0, -2) * 100) - 210 - stretch.clientHeight}px` 4710 if (ed1Scroller) ed1Scroller.style.height = `${(vh.slice(0, -2) * 100) - 210 - stretch.clientHeight}px` 4711 } else { 4712 nav.removeAttribute('style') 4713 for (let i = 0; i < navMenus.length; i++) { 4714 navMenus[i].removeAttribute('style') 4715 } 4716 for (let i = 0; i < navBtns.length; i++) { 4717 navBtns[i].removeAttribute('style') 4718 } 4719 if (familyScroller) familyScroller.removeAttribute('style') 4720 if (ed1Scroller) ed1Scroller.removeAttribute('style') 4721 } 4722 } 4723 4724 function closeMenu () { 4725 header.classList.remove('open') 4726 headerLayer.classList.remove('active') 4727 if (stretch) { 4728 header.style.top = '0' 4729 nav.removeAttribute('style') 4730 for (let i = 0; i < navMenus.length; i++) { 4731 navMenus[i].removeAttribute('style') 4732 } 4733 for (let i = 0; i < navBtns.length; i++) { 4734 navBtns[i].removeAttribute('style') 4735 } 4736 if (familyScroller) familyScroller.removeAttribute('style') 4737 if (ed1Scroller) ed1Scroller.removeAttribute('style') 4738 } 4739 stickyHeader.classList.remove('open') 4740 body.classList.remove('no-scroll') 4741 headerArea.classList.remove('hide') 4742 const activeArea = document.querySelector('.nav__area.active-mob') 4743 if (activeArea) activeArea.classList.remove('active-mob') 4744 } 4745} 4746 4747const helpSidebarItems = document.querySelectorAll('.help-sidebar__item') 4748const helpLineMenu = document.querySelector('.help-line__menu') 4749const helpLineSearch = document.querySelector('.help-line__search') 4750const helpSidebar = document.querySelector('.help-sidebar') 4751const helpSearchArticle = document.querySelector('.help-search_article') 4752const helpSearchInputs = document.querySelectorAll('.help-search__input') 4753const helpSidebarClose = document.querySelector('.help-sidebar__close') 4754const helpArticleNav = document.querySelector('.help-article-nav') 4755let timerHideHelpSearchMob 4756
4757helpSidebarItems.forEach(item => { 4758 item.addEventListener('click', (e) => item.classList.toggle('help-sidebar__item_active')) 4759}) 4760 4761if (helpLineMenu) helpLineMenuInit() 4762if (helpLineSearch) helpLineSearchInit() 4763 4764function helpLineMenuInit () { 4765 const body = document.querySelector('body') 4766 helpLineMenu.addEventListener('click', openSidebar) 4767 function openSidebar() { 4768 body.classList.add('no-scroll-mob') 4769 helpSidebar?.classList.add('help-sidebar_active') 4770 } 4771 helpSidebarClose.addEventListener('click', closeSidebar) 4772 function closeSidebar() { 4773 body.classList.remove('no-scroll-mob') 4774 helpSidebar?.classList.remove('help-sidebar_active') 4775 } 4776} 4777 4778function helpLineSearchInit () { 4779 helpLineSearch.addEventListener('click', showHelpSearchMob) 4780 function showHelpSearchMob () { 4781 helpSearchArticle?.classList.add('help-search_show') 4782 setTimeout(() => helpSearchArticle.querySelector('.help-search__input')?.focus(), 500) 4783 } 4784} 4785 4786function hideHelpSearchMob () { 4787 helpSearchArticle?.classList.remove('help-search_show') 4788} 4789 4790if (helpSearchInputs.length) helpSearchInputsInit() 4791 4792async function loadHelpJson() { 4793 let path = helpSearchInputs[0].getAttribute('data-json-path') 4794 try { 4795 const response = await fetch(path) 4796 if (!response.ok) throw new Error('Error loading JSON') 4797 return await response.json() 4798 } catch (error) { 4799 console.error('Error loading JSON:', error) 4800 } 4801} 4802 4803function searchAdvanced(query, preparedData) { 4804 const q = query.toLowerCase().trim() 4805 const words = q.split(' ') 4806 4807 const exact = preparedData.filter(item => 4808 item.name.toLowerCase() === q || 4809 item.keywordsArray.includes(q) 4810 ) 4811 if (exact.length) return exact 4812 4813 const includes = preparedData.filter(item => { 4814 const text = (item.name + ' ' + item.keywords).toLowerCase() 4815 return words.every(w => text.includes(w)) 4816 }) 4817 if (includes.length) return includes 4818 4819 return fuse.search({ 4820 $and: words.map(word => ({ 4821 $or: [ 4822 { name: word }, 4823 { keywordsArray: word } 4824 ] 4825 })) 4826 }) 4827} 4828 4829function smartSearch(query, preparedData) { 4830 const results = searchAdvanced(query, preparedData) 4831 return normalizeResults(results) 4832 .sort((a, b) => a.score - b.score) 4833 .map(res => res.item) 4834} 4835 4836function normalizeResults(results) { 4837 return results.map(res => { 4838 if (res.item) return res 4839 return { item: res, score: 0 } 4840 }) 4841} 4842 4843 4844async function helpSearchInputsInit () { 4845 const helpJson = await loadHelpJson() 4846 let fuse 4847 let preparedData 4848 if (helpJson) { 4849 preparedData = helpJson.map(item => ({ 4850 ...item, 4851 keywordsArray: item.keywords 4852 .toLowerCase() 4853 .split(',') 4854 .map(k => k.trim()) 4855 })) 4856 fuse = new Fuse(preparedData, { 4857 includeScore: true, 4858 threshold: 0.3, 4859 ignoreLocation: true, 4860 minMatchCharLength: 2, 4861 4862 keys: [ 4863 { name: 'name', weight: 0.6 }, 4864 { name: 'keywordsArray', weight: 0.4 } 4865 ] 4866 }) 4867 } 4868 4869 for (let i = 0; i < helpSearchInputs.length; i++) { 4870 helpSearchInputInit(helpSearchInputs[i]) 4871 } 4872 4873 function helpSearchInputInit (input) { 4874 const helpSearch = input.closest('.help-search') 4875 const helpSearchList = helpSearch.querySelector('.help-search__list') 4876 const helpSearchAll = helpSearch.querySelector('.help-search__all') 4877 const srfullResults = input.getAttribute('data-srfull-results') 4878 const srResults = input.getAttribute('data-sr-results') 4879 const dataUtm = input.getAttribute('data-utm') 4880 4881 input.addEventListener('input', search) 4882 input.addEventListener('input', updateHelpSearchAllHref) 4883 input.addEventListener('focus', search) 4884 input.addEventListener('keydown', (e) => { 4885 if (e.key === 'Enter') { 4886 debouncedSearch.cancel?.() 4887 handleSearch(e.target.value) 4888 } 4889 }) 4890 4891 document.addEventListener('click', hideSearchResults) 4892 if (helpSearch.classList.contains('help-search_article')) { 4893 input.addEventListener('blur', () => setTimerHideHelpSearchMob(false)) 4894 input.addEventListener('focus', () => setTimerHideHelpSearchMob(true)) 4895 } 4896 4897 function updateHelpSearchAllHref () { 4898 helpSearchAll.href = `${srfullResults}?q=${input.value}` 4899 } 4900 4901 function search () { 4902 if (this.value.length > 3) { 4903 if (helpJson) { 4904 debouncedSearch(this.value) 4905 } 4906 } else { 4907 hideSearchResults() 4908 } 4909 } 4910
4911 function debounce(fn, delay = 300) { 4912 let timeout 4913 4914 function debounced(...args) { 4915 clearTimeout(timeout) 4916 4917 timeout = setTimeout(() => { 4918 fn.apply(this, args) 4919 }, delay) 4920 } 4921 4922 debounced.cancel = () => clearTimeout(timeout) 4923 4924 return debounced 4925 } 4926 4927 const debouncedSearch = debounce(handleSearch, 300) 4928 4929 function handleSearch (query) { 4930 if (!query.trim()) { 4931 generateResultList([]) 4932 hideSearchResults() 4933 return 4934 } 4935 4936 const result = smartSearch(query, preparedData) 4937 if (helpSearchList) generateResultList(result) 4938 showSearchResults() 4939 } 4940 4941 function generateResultList (result) { 4942 helpSearchList.innerHTML = '' 4943 result.forEach((item) => { 4944 const a = document.createElement('a') 4945 a.href = `${srResults}/${item.slug}?${dataUtm}` 4946 a.innerHTML = item.name 4947 a.classList.add('help-search__item') 4948 helpSearchList.appendChild(a) 4949 }) 4950 } 4951 4952 function showSearchResults () { 4953 helpSearch?.classList.add('help-search_active') 4954 } 4955 4956 function hideSearchResults (e) { 4957 if (!e?.target?.closest('.help-search__result')) { 4958 helpSearch?.classList.remove('help-search_active') 4959 } 4960 } 4961 } 4962} 4963 4964function setTimerHideHelpSearchMob (stop) { 4965 if (stop) { 4966 clearTimeout(timerHideHelpSearchMob) 4967 helpArticleNav?.classList.add('help-article-nav_active') 4968 } else { 4969 timerHideHelpSearchMob = setTimeout(hideHelpSearchMob, 10000) 4970 helpArticleNav?.classList.remove('help-article-nav_active') 4971 } 4972} 4973 4974 4975const howSlider = document.querySelector('[data-element="how-slider"]') 4976 4977if (howSlider) howSliderInit() 4978 4979function howSliderInit () { 4980 let howSliderSwiper 4981 4982 function initSlider () { 4983 howSliderSwiper = new Swiper(howSlider, { 4984 mousewheel: { forceToAxis: true }, 4985 slidesPerView: 'auto', 4986 spaceBetween: 30, 4987 a11y: false, 4988 navigation: { 4989 nextEl: '.how__nav-btn_next', 4990 prevEl: '.how__nav-btn_prev', 4991 }, 4992 scrollbar: { 4993 el: '.how__scrollbar', 4994 draggable: true, 4995 }, 4996 }) 4997 } 4998 4999 window.addEventListener('resize', checkSlider) 5000 5001 checkSlider() 5002 5003 function checkSlider () { 5004 if (window.innerWidth >= 1360) { 5005 if (!howSliderSwiper || howSliderSwiper.destroyed) { 5006 initSlider() 5007 } 5008 } else { 5009 if (howSliderSwiper && !howSliderSwiper.destroyed) { 5010 howSliderSwiper.destroy(true, true) 5011 howSliderSwiper = null 5012 } 5013 } 5014 } 5015} 5016 5017const oldPromoAnimateNodes = document.querySelectorAll(".old-promo-animate") 5018 5019if (oldPromoAnimateNodes.length) oldPromoAnimateInit() 5020 5021function oldPromoAnimateInit () { 5022 const delayStep = 0.05 5023 5024 const observer = new IntersectionObserver((entries) => { 5025 entries.forEach((entry, index) => { 5026 if (entry.isIntersecting) { 5027 observer.unobserve(entry.target) 5028 entry.target.style.setProperty('transition-delay', `${index * delayStep}s`); 5029 entry.target.classList.add('old-promo-animate_active') 5030 } 5031 }); 5032 }, { 5033 root: null, 5034 rootMargin: '0px 0px -50px 0px', 5035 threshold: 1 5036 }) 5037 5038 for (let i = 0; i < oldPromoAnimateNodes.length; i++) { 5039 observer.observe(oldPromoAnimateNodes[i]) 5040 } 5041} 5042 5043 5044const parsingOgeLessonVideoBox = document.querySelectorAll('.parsing-oge-lesson__video-box') 5045for (let i = 0; i < parsingOgeLessonVideoBox.length; i++) { 5046 parsingOgeLessonVideoBox[i].addEventListener('click', function () { 5047 parsingOgeLessonVideoBox[i].classList.add('active') 5048 const iframe = parsingOgeLessonVideoBox[i].querySelector('iframe') 5049 iframe.src = iframe.src.replace('autoplay=0', 'autoplay=1') 5050 }) 5051} 5052 5053 5054const how = document.querySelector("[data-element='how']") 5055 5056if (how) howInit() 5057 5058function howInit () { 5059 const btn = document.querySelector("[data-element='how-button']") 5060 btn.addEventListener('click', function () { 5061 this.style.display = "none" 5062 how.classList.add('active') 5063 }) 5064} 5065 5066const information = document.querySelector('.information') 5067 5068if (information) informationInit() 5069 5070function informationInit () { 5071 const togglers = document.querySelectorAll('[data-information-toggler]') 5072 const accordions = document.querySelectorAll('[data-information-accordion]') 5073 const sidebarOpenBtn = document.querySelector('.information__sidebar-open') 5074 const sidebarCloseBtn = document.querySelector('.information__sidebar-close') 5075 const sidebar = document.querySelector('.information__sidebar') 5076 const body = document.querySelector('body') 5077 5078 for (let i = 0; i < accordions.length; i++) { 5079 accordions[i].addEventListener('click', () => { 5080 const oldToggler = document.querySelector('.information__button.active') 5081 if (oldToggler && !accordions[i].classList.contains('active')) oldToggler.classList.remove('active') 5082 accordions[i].classList.toggle('active') 5083 }) 5084 } 5085 5086 for (let i = 0; i < togglers.length; i++) { 5087 togglers[i].addEventListener('click', toggleBox) 5088 } 5089 5090 function toggleBox () { 5091 const id = this.getAttribute('data-information-button-id') 5092 const box = information.querySelector('[data-information-box-id="' + id + '"]') 5093 if (box) { 5094 const oldActive = document.querySelector('.information__box.active') 5095 if (oldActive) oldActive.classList.remove('active') 5096 const oldToggler = document.querySelector('.information__button.active') 5097 if (oldToggler && !this.classList.contains('information__btn')) oldToggler.classList.remove('active') 5098 box.classList.add('active') 5099 this.classList.add('active') 5100 closeSidebar() 5101 window.scrollTo(0, 0) 5102 } 5103 } 5104 5105 sidebarOpenBtn.addEventListener('click', openSidebar) 5106 sidebarCloseBtn.addEventListener('click', closeSidebar) 5107 5108 function openSidebar () { 5109 sidebar.classList.add('active') 5110 body.classList.add('no-scroll') 5111 } 5112 5113 function closeSidebar () { 5114 sidebar.classList.remove('active') 5115 body.classList.remove('no-scroll') 5116 } 5117} 5118 5119const instructionVideoBox = document.querySelector('.instruction__video-box') 5120 5121if (instructionVideoBox) instructionVideoBoxInit() 5122 5123function instructionVideoBoxInit() { 5124 const iframe = instructionVideoBox.querySelector('iframe') 5125 if (!iframe) { 5126 const video = instructionVideoBox.querySelector('video') 5127 instructionVideoBox.addEventListener('click', function () { 5128 this.classList.add('active') 5129 if (video) video.play() 5130 }, { once: true }) 5131 } 5132} 5133 5134const itCapCards = document.querySelector('.it-cap__cards') 5135 5136if (itCapCards) itCapCardsInit() 5137 5138function itCapCardsInit () { 5139 let itCapCardsSwiper 5140 5141 function initSlider () { 5142 itCapCardsSwiper = new Swiper(itCapCards, { 5143 mousewheel: { forceToAxis: true }, 5144 slidesPerView: 'auto', 5145 allowTouchMove: false, 5146 spaceBetween: 25, 5147 autoplay: { 5148 delay: 3000, 5149 }, 5150 speed: 1000, 5151 loop: true, 5152 }) 5153 } 5154 5155 window.addEventListener('resize', checkSlider) 5156 5157 checkSlider() 5158 5159 function checkSlider () { 5160 if (window.innerWidth >= 1440) { 5161 if (!itCapCardsSwiper || itCapCardsSwiper.destroyed) { 5162 initSlider() 5163 } 5164 } else { 5165 if (itCapCardsSwiper && !itCapCardsSwiper.destroyed) { 5166 itCapCardsSwiper.destroy(true, true) 5167 itCapCardsSwiper = null 5168 } 5169 } 5170 } 5171} 5172 5173 5174const itHowSlider = document.querySelector(".it-how__slider") 5175 5176if (itHowSlider) itHowSliderInit() 5177 5178function itHowSliderInit () { 5179 let itHowSliderSwiper 5180 5181 function initSlider () { 5182 itHowSliderSwiper = new Swiper(itHowSlider, { 5183 mousewheel: { forceToAxis: true }, 5184 slidesPerView: 'auto', 5185 spaceBetween: 20,
5186 a11y: false, 5187 navigation: { 5188 nextEl: '.it-how__nav-btn_next', 5189 prevEl: '.it-how__nav-btn_prev', 5190 }, 5191 scrollbar: { 5192 el: '.it-how__scrollbar', 5193 draggable: true, 5194 }, 5195 breakpoints: { 5196 1440: { 5197 spaceBetween: 30, 5198 } 5199 } 5200 }) 5201 } 5202 5203 window.addEventListener('resize', checkSlider) 5204 5205 checkSlider() 5206 5207 function checkSlider () { 5208 if (window.innerWidth >= 744) { 5209 if (!itHowSliderSwiper || itHowSliderSwiper.destroyed) { 5210 initSlider() 5211 } 5212 } else { 5213 if (itHowSliderSwiper && !itHowSliderSwiper.destroyed) { 5214 itHowSliderSwiper.destroy(true, true) 5215 itHowSliderSwiper = null 5216 } 5217 } 5218 } 5219} 5220 5221const itTileItems = document.querySelectorAll('.it-tile__item') 5222 5223for (let i = 0; i < itTileItems.length; i++) { 5224 itTileMoreInit(itTileItems[i]) 5225} 5226 5227function itTileMoreInit (parent) { 5228 const btn = parent.querySelector('.it-tile__more') 5229 const descr = parent.querySelector('.it-tile__author-descr') 5230 5231 if (btn && descr) { 5232 if ((descr.clientHeight > 68 && window.innerWidth >= 1440) || (descr.clientHeight > 50 && window.innerWidth < 1440)) { 5233 descr.classList.add('hide') 5234 } else { 5235 btn.remove() 5236 } 5237 } 5238} 5239 5240const langsTeachersSlider = document.querySelector('.langs-teachers__slider') 5241 5242if (langsTeachersSlider) langsTeachersSliderInit() 5243 5244function langsTeachersSliderInit () { 5245 let swiper 5246 if (window.innerWidth >= 744) { 5247 swiper = new Swiper(langsTeachersSlider, { 5248 mousewheel: { forceToAxis: true }, 5249 slidesPerView: 'auto', 5250 autoHeight: true, 5251 spaceBetween: 500, 5252 effect: 'fade', 5253 fadeEffect: { 5254 crossFade: true 5255 }, 5256 a11y: false, 5257 pagination: { 5258 el: '.langs-teachers__pagination', 5259 clickable: true, 5260 }, 5261 breakpoints: { 5262 744: { 5263 effect: 'fade', 5264 navigation: { 5265 nextEl: '.langs-teachers__nav-btn_next', 5266 prevEl: '.langs-teachers__nav-btn_prev', 5267 }, 5268 scrollbar: { 5269 el: '.langs-teachers__scrollbar', 5270 draggable: true, 5271 }, 5272 } 5273 } 5274 }) 5275 } else { 5276 swiper = new Swiper(langsTeachersSlider, { 5277 mousewheel: { forceToAxis: true }, 5278 slidesPerView: 'auto', 5279 autoHeight: true, 5280 spaceBetween: 200, 5281 fadeEffect: { 5282 crossFade: true 5283 }, 5284 a11y: false, 5285 pagination: { 5286 el: '.langs-teachers__pagination', 5287 clickable: true, 5288 }, 5289 breakpoints: { 5290 744: { 5291 effect: 'fade', 5292 navigation: { 5293 nextEl: '.langs-teachers__nav-btn_next', 5294 prevEl: '.langs-teachers__nav-btn_prev', 5295 }, 5296 scrollbar: { 5297 el: '.langs-teachers__scrollbar', 5298 draggable: true, 5299 }, 5300 } 5301 } 5302 }) 5303 } 5304 5305 const boxes = langsTeachersSlider.querySelectorAll('.langs-teachers__box') 5306 5307 for (let i = 0; i < boxes.length; i++) { 5308 const list = boxes[i].querySelector('.langs-teachers__list') 5309 if (list.clientHeight > 150) moreBtnInit(boxes[i]) 5310 } 5311 5312 function moreBtnInit (box) { 5313 box.classList.add('hide') 5314 const btn = box.querySelector('.langs-teachers__more') 5315 btn.classList.add('active') 5316 btn.addEventListener('click', toggleBox) 5317 5318 function toggleBox () { 5319 if (box.classList.contains('hide')) { 5320 box.classList.remove('hide') 5321 btn.innerHTML = 'СвеÑнÑÑÑ' 5322 } else { 5323 box.classList.add('hide') 5324 btn.innerHTML = 'ÐоказаÑÑ Ð¿Ð¾Ð»Ð½Ð¾ÑÑÑÑ' 5325 } 5326 swiper.update() 5327 } 5328 } 5329} 5330 5331 5332 5333const animateItems = document.querySelectorAll('.library-cap__animate') 5334
5335 if (animateItems.length) animateItemsInit() 5336 5337 function animateItemsInit () { 5338 const speed = 50 5339 let itemsIndex = 0 5340 const text = document.querySelector('.library-cap__text') 5341 const cursor = text.querySelector('.library-cap__cursor') 5342 5343 createString(animateItems[itemsIndex]) 5344 5345 function createString (item) { 5346 item.classList.add('active') 5347 const string = item.querySelector('.library-cap__animate-string') 5348 const cleanString = string.innerHTML.replace(/ |\u00A0/g, ' '); 5349 const text = [...cleanString] 5350 let stringWithSpans = '' 5351 text.forEach((char, i) => { 5352 stringWithSpans += `<span>${char}</span>` 5353 }) 5354 string.innerHTML = stringWithSpans 5355 animateString(string) 5356 } 5357 5358 function animateString (string) { 5359 const spans = string.querySelectorAll('span') 5360 const length = spans.length 5361 let index = 0 5362 animateSpan() 5363 5364 function animateSpan () { 5365 spans[index].classList.add('active') 5366 calculateCoords(spans[index]) 5367 index += 1 5368 if (index < length) { 5369 setTimeout(animateSpan, speed) 5370 } else { 5371 setTimeout(animateHide, 1000) 5372 } 5373 } 5374 function animateHide () { 5375 const spans = string.querySelectorAll('span') 5376 let index = spans.length - 1 5377 animateSpanHide() 5378 5379 function animateSpanHide () { 5380 spans[index].classList.remove('active') 5381 index -= 1 5382 calculateCoords(spans[index]) 5383 if (index < 0) { 5384 cursor.style.left = `${cursor.style.left.slice(0, -2) - 22}px` 5385 const oldActive = document.querySelector('.library-cap__animate.active') 5386 setTimeout(function () { 5387 oldActive.classList.remove('active') 5388 }, 50) 5389 setTimeout(function () { 5390 const oldString = oldActive.querySelector('.library-cap__animate-string') 5391 oldString.innerHTML = oldString.getAttribute('data-text') 5392 itemsIndex += 1 5393 if (itemsIndex >= animateItems.length) itemsIndex = 0 5394 createString(animateItems[itemsIndex]) 5395 }, 100) 5396 } else { 5397 setTimeout(animateSpanHide, speed*0.7) 5398 } 5399 } 5400 } 5401 } 5402 5403 function calculateCoords (span) { 5404 if (!span) return 5405 const top = span.getBoundingClientRect().top - text.getBoundingClientRect().top 5406 const left = span.getBoundingClientRect().left - text.getBoundingClientRect().left 5407 cursor.style.top = `${top}px` 5408 cursor.style.left = `${left}px` 5409 } 5410 } 5411 5412const libraryCap = document.querySelector('.library-cap') 5413 5414 if (libraryCap) libraryCapInit() 5415 5416 function libraryCapInit () { 5417 const libraryTile = document.querySelector('.library-tile') 5418 const libraryWhy = document.querySelector('.library-why') 5419 const libraryInformer = document.querySelector('.library-informer') 5420 const config = { attributes: false, childList: true, characterData: true, subtree: true }
5421 const openers = libraryCap.querySelectorAll("[data-element='library-cap-filter-opener']") 5422 const grades = libraryCap.querySelector("[data-ftype='class_select']") 5423 const subjects = libraryCap.querySelector("[data-ftype='class_subjects']") 5424 const filterSubjectBox = libraryCap.querySelector(".library-cap__filter.library-cap__filter_subject") 5425 const filterSubjectsList = libraryCap.querySelector(".library-cap__filter-wrap.class_subjects") 5426 const filterClassBox = libraryCap.querySelector(".library-cap__filter.library-cap__filter_class") 5427 const tile = document.querySelector('.library-tile') 5428 5429 const title = document.querySelector('.library-tile__title') 5430 const urlFilter = libraryCap.getAttribute('data-item-h') 5431 const h1Filter = libraryCap.getAttribute('data-hname') 5432 const metaName = libraryCap.getAttribute('data-meta_name') 5433 const metaDescription = libraryCap.getAttribute('data-meta_descr') 5434 const stickyHeader = document.querySelector('.sticky-header') 5435 const body = document.querySelector('body') 5436 const crumbsNewList = document.querySelector('.crumbs-new__list') 5437 const crumbs = document.querySelector('.crumbs-new') 5438 const filterSubject = document.querySelector(".library-cap__filter_subject") 5439 const filterSubjectWrap = filterSubject.querySelector(".library-cap__filter-wrap") 5440 5441 5442 const observer = new MutationObserver(function() { 5443 const wrap = openers[1].nextElementSibling 5444 const items = wrap.querySelectorAll("[data-element='library-cap-filter-input']") 5445 items.forEach((item) => { 5446 item.addEventListener('change', () => updateFilter(openers[1], wrap)) 5447 }) 5448 initInformerButtons() 5449 }) 5450 5451 initTabs() 5452 5453 const observerPoster = new MutationObserver(function() { 5454 initLibraryPosters() 5455 initTabs() 5456 initFilterTabs() 5457 initCommonAnalytics(tile.firstElementChild) 5458 }) 5459 5460 observerPoster.observe(tile, config) 5461 5462 const save = libraryCap.querySelector(".library-cap__button") 5463 if (save) save.addEventListener('click', saveHandler) 5464 5465 function saveHandler () { 5466 let valid = true 5467 for (let i = 0; i < openers.length; i++) { 5468 const wrap = openers[i].nextElementSibling 5469 const itemChecked = wrap.querySelector(["input:checked"]) 5470 if (!itemChecked) { 5471 valid = false 5472 openers[i].classList.add('error') 5473 setError() 5474 } 5475 } 5476 5477 if (valid) { 5478 makeFiltration() 5479 scrollToTile() 5480 } 5481 } 5482 5483 const subjectWrap = libraryCap.querySelector('.library-cap__filter.library-cap__filter_subject .library-cap__filter-wrap') 5484 const icon = libraryCap.querySelector('.library-cap__filter-icon') 5485 const labels = subjectWrap.querySelectorAll('.library-cap__filter-item') 5486 if (labels.length < 7 && icon) icon.remove() 5487 5488 const reset = libraryCap.querySelector("[data-element='library-cap-filter-reset']") 5489 if (reset) reset.addEventListener('click', resetFilters) 5490 5491 function resetFilters () { 5492 filterSubjectBox.classList.add('disable') 5493 for (let i = 0; i < openers.length; i++) { 5494 const wrap = openers[i].nextElementSibling 5495 const items = wrap.querySelectorAll("[data-element='library-cap-filter-input']") 5496 items.forEach((item) => { 5497 item.checked = false 5498 }) 5499 updateFilter(openers[i], wrap, true, true) 5500 } 5501 makeFiltration() 5502 hideBlocks() 5503 } 5504 5505 function updateBodyDataParams (grades_result, subjects_result) { 5506 body.setAttribute('data-filter-stage', grades_result ? grades_result : 'all') 5507 body.setAttribute('data-filter-subject', subjects_result ? subjects_result : 'all') 5508 const grades = grades_result ? '_grade' : '' 5509 const subjects = subjects_result ? '_subject' : '' 5510 const dataPageType = `library${grades}${subjects}` 5511 body.setAttribute('data-page-type', dataPageType) 5512 } 5513 5514 5515 async function makeFiltration () { 5516 const grades_wrap = grades.nextElementSibling 5517 const grades_items = grades_wrap.querySelectorAll(["input:checked"]) 5518 let grades_result = '' 5519 let grade_first = 0 5520 let grade_h1_part= '' 5521 let grade_item = '' 5522 let grade_breadname = ''
5523 grades_items.forEach((item, i) => { 5524 if (i > 0) grades_result += '|' 5525 if (grade_first == 0) grade_first = item.value 5526 if (grade_item === '') { 5527 grade_item = item.getAttribute('data-item') 5528 grade_breadname = item.getAttribute('data-breadname') 5529 } 5530 if (grade_h1_part === '') grade_h1_part = item.getAttribute('data-hname') 5531 grades_result += item.value 5532 }) 5533 let subjects_result = '' 5534 let subject_item = '' 5535 let subject_breadname = '' 5536 let subject_h1_part= '' 5537 try{ 5538 const subjects_wrap = subjects.nextElementSibling 5539 const subjects_items = subjects_wrap.querySelectorAll(["input:checked"]) 5540 subjects_items.forEach((item, i) => { 5541 if (i > 0) subjects_result += '|' 5542 subjects_result += item.value 5543 if (subject_item === '') { 5544 subject_item = item.getAttribute('data-item') 5545 subject_breadname = item.getAttribute('data-breadname') 5546 } 5547 if (subject_h1_part === '') subject_h1_part = item.getAttribute('data-hname') 5548 }) 5549 }catch(e){} 5550 let utm_f = libraryCap.getAttribute('data-utm'); 5551 $('.filtered_elements').html("<div class='tile-loader'></div>"); 5552 $.request('VideoCourseFunctions::onPaginateAllCourses', { 5553 data: { 5554 'grade': grades_result, 5555 'subject': subjects_result, 5556 'utm_t': utm_f 5557 } 5558 }) 5559 if (urlFilter ) { 5560 let url = urlFilter 5561 let new_h1 = 'ÐидеоÑÑоки' 5562 let new_title = new_h1 5563 let new_description = 'ÐеÑплаÑнÑе видеоÑÑоки ' 5564 let base_subject = '' 5565 let base_grade = '' 5566 let urlGrade 5567 let urlSubject 5568 5569 if (grade_first > 0 ){ 5570 // let url = new URL(window.location.href) 5571 // url.searchParams.set('gr', grade_first); 5572 5573 if (grade_item) { 5574 urlGrade = url + '/' + grade_item 5575 } 5576 5577 if (subject_item) { 5578 urlSubject = url + '/' + grade_item + '/' + subject_item 5579 } 5580 5581 generateCrumbs() 5582 5583 5584 5585 if (grade_item !== "") { 5586 url = url + '/' + grade_item 5587 if (subject_item !== "") { 5588 url = url + '/' + subject_item 5589 } 5590 5591 } 5592 5593 5594 if (subject_h1_part !== "") { 5595 base_subject = ' по '+ subject_h1_part 5596 new_h1 = new_h1 + base_subject 5597 new_description = new_description + base_subject 5598 }else{ 5599 } 5600 if (grade_h1_part !== "") { 5601 base_grade = ' Ð´Ð»Ñ ' + grade_h1_part 5602 new_h1 = new_h1 + base_grade 5603 new_description = new_description + base_grade 5604 }else{ 5605 } 5606 try{ 5607 title.innerHTML = new_h1 5608 }catch(lib_er){} 5609 } else { 5610 generateCrumbs() 5611 } 5612 5613 url = url + utm_f 5614 history.replaceState(null, "", url.toString()) 5615 5616 new_title = new_h1 + ' в онлайн-Ñколе «ТоÑка Ðнаний»' 5617 new_description = new_description + ' в одном меÑÑе. ÐоÑаговÑе обÑÑÑнениÑ, ÑÐ°Ð·Ð±Ð¾Ñ ÑложнÑÑ Ñем и пÑимеÑÑ ÑеÑениÑ. СмоÑÑиÑе ÑÑоки онлайн в Ñдобном ÑоÑмаÑе!' 5618 console.log(new_title); 5619 5620 5621 document.title = new_title 5622 const meta= document.getElementsByTagName("meta") 5623 for (let i= 0; i < meta.length; i++) { 5624 if (meta[i].name.toLowerCase() === "description") { 5625 meta[i].content = new_description 5626 } 5627 } 5628 5629 updateBodyDataParams(grades_result, subjects_result) 5630 5631 function generateCrumbs () { 5632 if (crumbsNewList) { 5633 crumbsNewList.innerHTML = '' 5634 createCrumbsItem('/', 'ÐлавнаÑ') 5635 if (urlGrade) { 5636 createCrumbsItem(urlFilter, 'ÐиблиоÑека пÑобнÑÑ ÑÑоков') 5637 } else { 5638 createCrumbsItem(false, 'ÐиблиоÑека пÑобнÑÑ ÑÑоков') 5639 } 5640 if (urlGrade && urlSubject) { 5641 createCrumbsItem(urlGrade, grade_breadname) 5642 createCrumbsItem(false, subject_breadname) 5643 } else if (urlGrade) { 5644 createCrumbsItem(false, grade_breadname) 5645 } 5646 } 5647 } 5648 function createCrumbsItem (url, text) { 5649 let item 5650 if (url) { 5651 item = document.createElement('a') 5652 item.href = url 5653 } else { 5654 item = document.createElement('span') 5655 } 5656 item.classList.add('crumbs-new__item') 5657 item.innerHTML = text 5658 crumbsNewList.appendChild(item) 5659 } 5660 5661 } 5662 initLibraryPosters() 5663 // } 5664 5665 } 5666 5667 function scrollToTile () { 5668 showBlocks() 5669 const banner = document.querySelector('.discount') 5670 const bannerHeight = banner ? banner.clientHeight : 0 5671 const theElement = document.getElementById('library-tile') 5672 let offset 5673 if (window.innerWidth < 744) { 5674 offset = 84 + bannerHeight 5675 } else if (window.innerWidth < 1200) { 5676 offset = 102 + bannerHeight 5677 } else { 5678 offset = 120 + bannerHeight 5679 } 5680 window.scrollTo(0, theElement.getBoundingClientRect().top + scrollY - offset) 5681 } 5682 5683 function showBlocks () { 5684 if (libraryTile) libraryTile.classList.remove('hide') 5685 if (libraryWhy) libraryWhy.classList.remove('hide') 5686 if (libraryInformer) libraryInformer.classList.remove('hide') 5687 } 5688 5689 function hideBlocks () { 5690 if (libraryTile) libraryTile.classList.add('hide') 5691 if (libraryWhy) libraryWhy.classList.add('hide') 5692 if (libraryInformer) libraryInformer.classList.add('hide') 5693 } 5694 5695 for (let i = 0; i < openers.length; i++) { 5696 openers[i].addEventListener("click", (e)=> openFilter(openers[i], e)) 5697 5698 const wrap = openers[i].nextElementSibling 5699 const items = wrap.querySelectorAll("[data-element='library-cap-filter-input']")
5700 items.forEach((item) => { 5701 item.addEventListener('change', () => updateFilter(openers[i], wrap)) 5702 }) 5703 if (i === 1) { 5704 window.onload = function() { 5705 observer.observe(wrap, config) 5706 } 5707 } 5708 } 5709 5710 initInformerButtons() 5711 5712 function initInformerButtons () { 5713 const informerButtons = subjects.nextElementSibling.querySelectorAll('.all-courses__filter-informer-button') 5714 informerButtons.forEach(informerButton => { 5715 informerButton.addEventListener('click', function () { 5716 const input = this.closest('.library-cap__filter-box')?.querySelector("[data-element='library-cap-filter-input']") 5717 if (input) { 5718 input.checked = true 5719 updateFilter(subjects, subjects.nextElementSibling) 5720 } 5721 }) 5722 }) 5723 } 5724 5725 5726 function openFilter (opener, e) { 5727 e.stopPropagation() 5728 if (opener.parentElement.classList.contains('library-cap__filter_subject') && !filterClassBox.querySelector(["input:checked"])) { 5729 setError() 5730 } else { 5731 resetError() 5732 if (opener.classList.contains('active')) { 5733 closeFilter(opener) 5734 } else { 5735 const oldOpen = libraryCap.querySelector(".library-cap__filter-top.active") 5736 if (oldOpen) oldOpen.classList.remove('active') 5737 opener.classList.add('active') 5738 5739 const filter = opener.parentElement 5740 const oldFilter = libraryCap.querySelector(".library-cap__filter.open") 5741 if (oldFilter) oldFilter.classList.remove('open') 5742 if (filter) filter.classList.add('open') 5743 5744 stickyHeader.classList.add('mob-hide') 5745 crumbs.classList.add('crumbs-new_mob-hide') 5746 body.classList.add('no-scroll-mob') 5747 } 5748 } 5749 } 5750 5751 window.addEventListener('click', closeAllFilters) 5752 5753 function closeAllFilters () { 5754 const oldOpen = libraryCap.querySelector(".library-cap__filter-top.active") 5755 if (oldOpen) oldOpen.classList.remove('active') 5756 stickyHeader.classList.remove('mob-hide') 5757 crumbs.classList.remove('crumbs-new_mob-hide') 5758 body.classList.remove('no-scroll-mob') 5759 } 5760 5761 function closeFilter (opener) { 5762 opener.classList.remove('active') 5763 const filter = opener.parentElement 5764 if (filter) filter.classList.remove('open') 5765 stickyHeader.classList.remove('mob-hide') 5766 crumbs.classList.remove('crumbs-new_mob-hide') 5767 body.classList.remove('no-scroll-mob') 5768 } 5769 5770 async function updateFilter (opener, wrap, noScroll, noFiltration) { 5771 resetError() 5772 if(opener.getAttribute('data-ftype') === 'class_select') { 5773 filterSubjectsList.innerHTML = "<div class='tile-loader-box'><div class='tile-loader'></div></div>"; 5774 // makeFiltration() 5775 updateFilter(openers[1], openers[1].nextElementSibling, true) 5776 if (!noFiltration) updateFilter(openers[1], openers[1].nextElementSibling, true) 5777 } else { 5778 if (!noFiltration) makeFiltration() 5779 if (!noScroll) scrollToTile() 5780 } 5781 opener.innerHTML = opener.getAttribute('data-default-text') 5782 const items = wrap.querySelectorAll(["input:checked"]) 5783 if (items.length) { 5784 opener.innerHTML = 'ÐÑбÑано: ' 5785 items.forEach((item) => { 5786 const span = document.createElement("span") 5787 span.innerHTML = item.nextElementSibling.innerHTML 5788 span.classList.add('span') 5789 opener.append(span) 5790 }) 5791 } 5792 const itemsAll = libraryCap.querySelectorAll(["input:checked"]) 5793 if (itemsAll.length) { 5794 if (reset) reset.classList.add('show') 5795 } else { 5796 if (reset) reset.classList.remove('show') 5797 } 5798 closeFilter(opener) 5799 } 5800 5801 initLibraryPosters() 5802 5803 function setError () { 5804 openers[0].parentElement.classList.add('library-cap__filter_error') 5805 openers[1].parentElement.classList.add('library-cap__filter_error') 5806 } 5807 5808 function resetError () { 5809 openers[0].parentElement.classList.remove('library-cap__filter_error') 5810 openers[1].parentElement.classList.remove('library-cap__filter_error') 5811 } 5812 5813 function initTabs () { 5814 const tabs = tile.querySelectorAll('.library-tile__tab') 5815 if (!tabs.length) return 5816 5817 const items = tile.querySelectorAll('.library-tile__item') 5818 5819 for (let i = 0; i < tabs.length; i++) { 5820 tabs[i].addEventListener('click', tabFiltration) 5821 } 5822 5823 function tabFiltration () { 5824 const oldActive = document.querySelector('.library-tile__tab.active') 5825 if (oldActive) oldActive.classList.remove('active') 5826 this.classList.add('active') 5827 for (let i = 0; i < items.length; i++) { 5828 items[i].style.display = 'none' 5829 } 5830 const dataIndex = this.getAttribute('data-index') 5831 const filteredItems = tile.querySelectorAll('[data-index="' + dataIndex + '"]') 5832 for (let i = 0; i < filteredItems.length; i++) { 5833 filteredItems[i].style.display = 'flex' 5834 } 5835 } 5836 } 5837 5838 initFilterTabs() 5839 5840 function initFilterTabs () { 5841 const filterHeadline = filterSubjectWrap.querySelector('.library-cap__filter-headline') 5842 const tabsParent = filterSubject.querySelector('.library-cap__filter-tabs') 5843 const list = filterSubjectWrap.querySelector('.library-cap__filter-list') 5844 const tabs = filterSubject.querySelectorAll('.library-cap__filter-tab') 5845 const subjectsBoxes = filterSubjectWrap.querySelectorAll('.library-cap__filter-box') 5846 5847 if (!tabs.length || !subjectsBoxes.length) return 5848 5849 filterSubjectWrap.addEventListener('scroll', wrapScrollHandler, { passive: true }) 5850 5851 function wrapScrollHandler () {
5852 subjectsBoxes.forEach((subjectBox) => { 5853 if (filterSubjectWrap.scrollTop >= subjectBox.offsetTop - 90 - 65) { 5854 const oldTab = filterSubjectWrap.querySelector('.library-cap__filter-tab.active') 5855 if (oldTab) oldTab.classList.remove('active') 5856 const index = subjectBox.getAttribute('data-index') 5857 const tab = filterSubjectWrap.querySelector('[data-index="' + index + '"]') 5858 if (tab) { 5859 tabsParent.scrollLeft = tab.offsetLeft - tabsParent.clientWidth/2 + tab.clientWidth/2 5860 tab.classList.add('active') 5861 } 5862 } 5863 }) 5864 } 5865 5866 let timeout 5867 let firstToggle = true 5868 5869 tabs.forEach((tab) => { 5870 tab.addEventListener('click', changeTab) 5871 tab.addEventListener('mouseenter', changeTab) 5872 }) 5873 5874 function changeTab (e) { 5875 e.stopPropagation() 5876 clearTimeout(timeout) 5877 timeout = setTimeout(() => toggle(this),100) 5878 5879 function toggle (that) { 5880 if (!that.closest('.library-cap__filter-wrap')?.querySelector('.library-cap__filter-tab:hover') && !firstToggle) return 5881 firstToggle = false 5882 filterSubjectWrap.removeEventListener('scroll', wrapScrollHandler, { passive: true }) 5883 const oldTab = filterSubjectWrap.querySelector('.library-cap__filter-tab.active') 5884 if (oldTab) oldTab.classList.remove('active') 5885 5886 that.classList.add('active') 5887 if (filterHeadline) filterHeadline.innerHTML = that.getAttribute('data-text') 5888
5889 subjectsBoxes.forEach((subjectsBox) => { 5890 subjectsBox.classList.add('hide') 5891 }) 5892 5893 const index = that.getAttribute('data-index') 5894 const activeSubjectsBox = list.querySelector('[data-index="' + index + '"]') 5895 activeSubjectsBox.classList.remove('hide') 5896 5897 filterSubjectWrap.scrollTop = activeSubjectsBox.offsetTop - 90 - 60 5898 5899 tabsParent.scrollLeft = that.offsetLeft - tabsParent.clientWidth/2 + that.clientWidth/2 5900 setTimeout(() => filterSubjectWrap.addEventListener('scroll', wrapScrollHandler, { passive: true }), 200) 5901 } 5902 } 5903 5904 setTimeout(() => tabs[0].click(),200) 5905 } 5906 5907 } 5908 5909initLibraryPosters() 5910 5911function initLibraryPosters () { 5912 const videoBoxes = document.querySelectorAll('.library-tile__video-box') 5913 for (let i = 0; i < videoBoxes.length; i++) { 5914 videoBoxes[i].addEventListener('click', function () { 5915 videoBoxes[i].classList.add('active') 5916 const iframe = videoBoxes[i].querySelector('iframe') 5917 iframe.src = iframe.src.replace('autoplay=0', 'autoplay=1') 5918 }) 5919 } 5920 5921 } 5922 5923const lottieAnimations = document.querySelectorAll('[data-path]') 5924 5925for (let i = 0; i < lottieAnimations.length; i++) { 5926 lottie.loadAnimation({ 5927 container: lottieAnimations[i], 5928 renderer: 'svg', 5929 loop: true, 5930 autoplay: true, 5931 path: lottieAnimations[i].getAttribute('data-path') 5932 }) 5933} 5934 5935const marathonChildThemes = document.querySelector('[data-element="marathon-child__themes"]') 5936
5937if (marathonChildThemes) marathonChildThemesInit() 5938 5939function marathonChildThemesInit () { 5940 const navItems = document.querySelectorAll('[data-element="marathon-child__nav-item"]') 5941 const boxes = document.querySelectorAll('[data-element="marathon-child__box"]') 5942 5943 for (let i = 0; i < navItems.length; i++) { 5944 navItems[i].addEventListener('click', toggleBox) 5945 } 5946 5947 function toggleBox () { 5948 const oldNav = marathonChildThemes.querySelector('.marathon-child__nav-item_active') 5949 oldNav.classList.remove('marathon-child__nav-item_active') 5950 this.classList.add('marathon-child__nav-item_active') 5951 const oldBox = marathonChildThemes.querySelector('.marathon-child__box_active') 5952 oldBox.classList.remove('marathon-child__box_active') 5953 const index = this.getAttribute('data-index') 5954 boxes[index].classList.add('marathon-child__box_active') 5955 } 5956 5957 const marathonChildClose = document.querySelector('[data-element="marathon-child__close"]') 5958 5959 marathonChildThemes.addEventListener('click', openModal) 5960 marathonChildClose.addEventListener('click', closeModal) 5961 window.addEventListener('click', windowCloseModal) 5962 5963 function openModal () { 5964 marathonChildThemes.classList.add('marathon-child__themes_active') 5965 } 5966 5967 function closeModal (e) { 5968 e.stopPropagation() 5969 marathonChildThemes.classList.remove('marathon-child__themes_active') 5970 } 5971 5972 function windowCloseModal (e) { 5973 if (!e.target.classList.contains('marathon-child__themes') && !e.target.closest('.marathon-child__themes')) { 5974 marathonChildThemes.classList.remove('marathon-child__themes_active') 5975 } 5976 } 5977} 5978 5979const marathonInformer = document.querySelector('[data-element="marathon-informer"]') 5980 5981if (marathonInformer) marathonInformerInit() 5982 5983function marathonInformerInit () { 5984 const close = document.querySelector('[data-element="marathon-informer__close"]') 5985 close.addEventListener('click', removeMarathon) 5986 5987 function removeMarathon (e) { 5988 e.preventDefault() 5989 localStorage.setItem('isMarathonInformerShown', 'true') 5990 marathonInformer.remove() 5991 } 5992 5993 const isShown = localStorage.getItem('isMarathonInformerShown') 5994 5995 if (!isShown || marathonInformer.getAttribute('show-always')) { 5996 marathonInformer.style.display = 'block' 5997 } 5998} 5999 6000const marathonOrderSelect = document.querySelector("[data-element='marathon-order__select']") 6001 6002if (marathonOrderSelect) marathonOrderSelectInit() 6003 6004function marathonOrderSelectInit () { 6005 const button = document.querySelector("[data-element='marathon-order__button']") 6006 const priceOld = document.querySelector("[data-element='marathon-order__price-old']") 6007 const priceNew = document.querySelector("[data-element='marathon-order__price-new']") 6008 const opener = marathonOrderSelect.closest('.custom-select-container').querySelector('.custom-select-opener') 6009 6010 marathonOrderSelect.addEventListener('change', updateButton) 6011 button.addEventListener('click', validateButton) 6012 6013 function validateButton (e) { 6014 if (!marathonOrderSelect.value) { 6015 e.preventDefault() 6016 opener.classList.add('error') 6017 } else { 6018 window.open(button.href) 6019 } 6020 } 6021 6022 function updateButton () { 6023 opener.classList.remove('error') 6024 6025 const link = this.options[this.selectedIndex].getAttribute('data-product-link') 6026 const priceOldValue = this.options[this.selectedIndex].getAttribute('data-product-old-price') 6027 const priceNewValue = this.options[this.selectedIndex].getAttribute('data-product-new-price') 6028 6029 button.href = link 6030 if (priceOldValue) { 6031 priceOld.style.display = 'block' 6032 priceOld.innerHTML =`${priceOldValue}` 6033 } else { 6034 priceOld.style.display = 'none' 6035 } 6036 priceNew.innerHTML =`${priceNewValue}` 6037 } 6038} 6039 6040const maxDiscount = document.querySelector('.max-discount') 6041 6042if (maxDiscount) maxDiscountInit() 6043 6044function maxDiscountInit () { 6045 const stickyHeader = document.querySelector('.sticky-header') 6046 const timer = maxDiscount.querySelector('.max-discount__timer') 6047 6048 window.addEventListener('scroll', checkScroll, { passive: true }) 6049 6050 function checkScroll () { 6051 if (window.scrollY > 100) { 6052 stickyHeader.classList.add('predzaps-top-hide') 6053 setTimeout(() => stickyHeader.classList.add('predzaps-top-hide-no-transition'), 300) 6054 } else if (window.scrollY <= 20) { 6055 stickyHeader.classList.remove('predzaps-top-hide-no-transition') 6056 setTimeout(() => stickyHeader.classList.remove('predzaps-top-hide'), 100) 6057 } 6058 } 6059 6060 if (timer) offerTimerInit(timer) 6061 6062 function offerTimerInit (timer) { 6063 const date = timer.getAttribute('date-end') 6064 const countDownDate = new Date(date).getTime() 6065 6066 const nodes = timer.querySelectorAll('.max-discount__number') 6067 6068 const interval = setInterval(updateTimer, 1000) 6069 6070 function updateTimer () { 6071 const now = new Date().getTime(); 6072 const distance = countDownDate - now; 6073 6074 const days = Math.floor(distance / (1000 * 60 * 60 * 24)) 6075 const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)) 6076 const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)) 6077 const seconds = Math.floor((distance % (1000 * 60)) / 1000) 6078 6079 nodes[0].innerHTML = days 6080 nodes[1].innerHTML = hours 6081 nodes[2].innerHTML = minutes 6082 nodes[3].innerHTML = seconds 6083 6084 if (distance < 0) { 6085 clearInterval(interval); 6086 nodes[0].innerHTML = "0" 6087 nodes[1].innerHTML = "0" 6088 nodes[2].innerHTML = "0" 6089 nodes[3].innerHTML = "0" 6090 } 6091 } 6092 } 6093} 6094 6095(function () { 6096 const configs = [ 6097 { 6098 id: 'offer-tile', 6099 itemSelector: '.offer-tile__item', 6100 tileSelector: '.offer-tile__tile', 6101 requestFromAttribute: true, 6102 isEnrich: false 6103 }, 6104 { 6105 id: 'enrich-tile', 6106 itemSelector: '.all-courses__item', 6107 tileSelector: '.all-courses__tile', 6108 requestFromAttribute: false, 6109 isEnrich: true 6110 } 6111 ] 6112
6113 configs.forEach(initTile) 6114 6115 function initTile (config) { 6116 const root = document.getElementById(config.id) 6117 if (!root) return 6118 6119 const isEnrich = config.isEnrich 6120 const filterTops = root.querySelectorAll('.offer-tile__filter-top') 6121 const filterSubject = root.querySelector('.offer-tile__filter_subject') 6122 const filterClass = root.querySelector('.offer-tile__filter_class') 6123 const stickyHeader = document.querySelector('.sticky-header') 6124 const body = document.body 6125 const tile = root.querySelector(config.tileSelector) 6126 const classInputs = root.querySelectorAll('.offer-tile__filter-input_class') 6127 const subjectInputs = root.querySelectorAll('.offer-tile__filter-input_subject') 6128 const reset = root.querySelector('.offer-tile__reset-filter') 6129 const configObserver = { 6130 attributes: true, 6131 childList: true, 6132 characterData: true, 6133 subtree: true 6134 } 6135 const isSumPage = root.classList.contains('offer-tile_sum') 6136 const requestFunction = root.getAttribute('data-request-function') 6137 const filterSumr = root.querySelector('[data-role="filter-sumr"]') 6138 const filterNewy = root.querySelector('[data-role="filter-newy"]') 6139 6140 if (!filterTops.length || !filterSubject || !filterClass) return 6141 6142 initAnchorScroll() 6143 initFilterOpeners() 6144 initResetButtons() 6145 initInputs() 6146 initObserver() 6147 moreBtnInit() 6148 6149 if (isEnrich) { 6150 if (tile) togglePrice() 6151 initSimpleTabs() 6152 } else { 6153 sortSubjectsInit() 6154 initAdvancedTabs() 6155 } 6156 6157 function initAnchorScroll () { 6158 if (!window.location.href.includes(`#${config.id}`)) return 6159 6160 window.addEventListener('load', function () { 6161 const offset = window.innerWidth < 744 ? 60 : 80 6162 6163 window.scrollTo({ 6164 top: root.getBoundingClientRect().top + window.scrollY - offset, 6165 behavior: 'smooth' 6166 }) 6167 }, { once: true }) 6168 } 6169 6170 function initFilterOpeners () { 6171 filterTops.forEach((opener) => { 6172 opener.addEventListener('click', (e) => openFilter(opener, e)) 6173 6174 const wrap = opener.nextElementSibling 6175 6176 const informerButtons = wrap.querySelectorAll('.all-courses__filter-informer-button') 6177 informerButtons.forEach(informerButton => { 6178 informerButton.addEventListener('click', function () { 6179 const input = this.closest('.offer-tile__filter-box')?.querySelector("[data-element='offer-tile-filter-input']") 6180 if (input) { 6181 input.checked = true 6182 input.dispatchEvent(new Event('change', { bubbles: true })) 6183 } 6184 }) 6185 }) 6186 }) 6187 6188 document.addEventListener('click', () => { 6189 filterTops.forEach((opener) => opener.classList.remove('active')) 6190 showHeader() 6191 }) 6192 } 6193 6194 function openFilter (opener, e) { 6195 e.stopPropagation() 6196 6197 if (!opener.classList.contains('active')) { 6198 root.querySelector('.offer-tile__filter-top.active')?.classList.remove('active') 6199 root.querySelector('.offer-tile__filter.active')?.classList.remove('active') 6200 closeSelectFilter() 6201 } 6202 6203 if (opener.classList.contains('active')) { 6204 opener.classList.remove('active') 6205 opener.parentElement.classList.remove('active') 6206 showHeader() 6207 } else { 6208 opener.classList.add('active') 6209 opener.parentElement.classList.add('active') 6210 hideHeader() 6211 } 6212 } 6213 6214 function closeSelectFilter () { 6215 const opened = document.querySelector('.select-filter.active') 6216 if (!opened) return 6217
6218 opened.classList.remove('active') 6219 opened.querySelector('.select-filter__top')?.classList.remove('active') 6220 } 6221 6222 function showHeader () { 6223 stickyHeader?.classList.remove('hide') 6224 body.classList.remove('no-scroll') 6225 } 6226 6227 function hideHeader () { 6228 if (window.innerWidth < 744) { 6229 stickyHeader?.classList.add('hide') 6230 body.classList.add('no-scroll') 6231 } 6232 } 6233 6234 function initResetButtons () { 6235 if (isEnrich) { 6236 reset?.addEventListener('click', resetFilters) 6237 return 6238 } 6239 6240 const resetClassButton = filterClass.querySelector( 6241 '.offer-tile__filter-top-reset' 6242 ) 6243 6244 const resetSubjectButton = filterSubject.querySelector( 6245 '.offer-tile__filter-top-reset' 6246 ) 6247 6248 resetClassButton?.addEventListener('click', resetClass) 6249 resetSubjectButton?.addEventListener('click', () => resetSubject(true)) 6250 reset?.addEventListener('click', resetFilters) 6251 6252 function resetClass () { 6253 const activeInput = filterClass.querySelector( 6254 '.offer-tile__filter-input:checked' 6255 ) 6256 6257 if (!activeInput) return 6258 6259 activeInput.checked = false 6260 const defaultClassInput = filterClass.querySelector('input[value=""],input[value="all"]') 6261 if (defaultClassInput) defaultClassInput.checked = true 6262 resetClassButton.classList.remove('active') 6263 setTopText(filterTops[0], 'ÐÑе клаÑÑÑ') 6264 resetSortSubjects() 6265 makeFiltration() 6266 } 6267 6268 function resetSubject (shouldFilter = false) { 6269 setTopText(filterTops[1], 'ÐÑе пÑедмеÑÑ') 6270 resetSubjectButton.classList.remove('active') 6271 6272 const activeInput = filterSubject.querySelector( 6273 '.offer-tile__filter-input:checked' 6274 ) 6275 6276 if (activeInput) activeInput.checked = false 6277 6278 sortGradesInit() 6279 6280 if (shouldFilter) makeFiltration() 6281 } 6282 } 6283 6284 function resetFilters () { 6285 if (isEnrich) { 6286 root.querySelectorAll('input').forEach((input) => { 6287 input.checked = 6288 input.hasAttribute('data-default-garde') || 6289 input.hasAttribute('data-default-subject') 6290 }) 6291 } else { 6292 root.querySelectorAll('input').forEach((input) => { 6293 input.checked = false 6294 }) 6295 6296 filterClass 6297 .querySelector('.offer-tile__filter-top-reset') 6298 ?.classList.remove('active') 6299 6300 filterSubject 6301 .querySelector('.offer-tile__filter-top-reset') 6302 ?.classList.remove('active') 6303 6304 resetSortSubjects() 6305 sortGradesInit() 6306 } 6307 6308 setTopText(filterTops[0], 'ÐÑе клаÑÑÑ') 6309 setTopText(filterTops[1], 'ÐÑе пÑедмеÑÑ') 6310 6311 const defaultClassInput = filterClass.querySelector('input[value=""],input[value="all"]') 6312 if (defaultClassInput) defaultClassInput.checked = true 6313 6314 makeFiltration() 6315 } 6316 6317 function initInputs () { 6318 const updateEnrich = () => updateFilter() 6319 const updateOffer = (isClass) => updateFilter(isClass) 6320 6321 classInputs.forEach((input) => { 6322 input.addEventListener('change', () => { 6323 isEnrich ? updateEnrich() : updateOffer(true) 6324 }) 6325 6326 input.addEventListener('change', changeClassInputText) 6327 }) 6328 6329 subjectInputs.forEach((input) => { 6330 input.addEventListener('change', () => { 6331 isEnrich ? updateEnrich() : updateOffer(false) 6332 }) 6333 6334 input.addEventListener('change', changeSubjectInputText) 6335 }) 6336 6337 filterSumr?.addEventListener('change', updateFilter) 6338 filterNewy?.addEventListener('change', updateFilter) 6339 } 6340 6341 function changeClassInputText () { 6342 setTopText(filterTops[0], this.getAttribute('data-text')) 6343 6344 if (!isEnrich) { 6345 filterClass 6346 .querySelector('.offer-tile__filter-top-reset') 6347 ?.classList.toggle('active', this.value !== 'all' && this.value !== '') 6348 } 6349 } 6350 6351 function changeSubjectInputText () { 6352 setTopText(filterTops[1], this.getAttribute('data-text')) 6353 6354 if (!isEnrich) { 6355 filterSubject 6356 .querySelector('.offer-tile__filter-top-reset') 6357 ?.classList.add('active') 6358 } 6359 } 6360 6361 function setTopText (element, text) { 6362 if (element) { 6363 if (text === 'ÐÑе пÑедмеÑÑ' || text === 'ÐÑе клаÑÑÑ') { 6364 element.innerHTML = `${text || ''}` 6365 } else { 6366 element.innerHTML = `<span>${text || ''}</span>` 6367 } 6368 } 6369 } 6370 6371 function updateFilter (isClassUpdated) { 6372 if (!isEnrich) { 6373 if (isClassUpdated) { 6374 sortSubjectsInit() 6375 } else { 6376 sortGradesInit() 6377 } 6378 } 6379 6380 makeFiltration() 6381 } 6382 6383 function selectedClass () { 6384 return filterClass.querySelector('input:checked') 6385 } 6386 6387 function sortSubjectsInit () { 6388 resetSortSubjects() 6389 6390 const subjects = selectedClass()?.getAttribute('data-subjects') 6391 6392 if (subjects) { 6393 hideAllSubjects() 6394 sortSubjects(subjects) 6395 } 6396 } 6397 6398 function sortGradesInit () { 6399 const checkedSubject = filterSubject.querySelector('input:checked') 6400 const hasSubject = !!checkedSubject 6401 const allowedGrades = getParsedData(checkedSubject, 'data-grades') 6402 filterBlockInputs(filterClass, allowedGrades, hasSubject) 6403 } 6404 6405 const getParsedData = (element, attribute) => { 6406 if (!element) return []
6407 try { 6408 const data = element.getAttribute(attribute) 6409 return data ? JSON.parse(data) : [] 6410 } catch (e) { 6411 console.error(`ÐÑибка паÑÑинга JSON в аÑÑибÑÑе ${attribute}:`, e) 6412 return [] 6413 } 6414 } 6415 6416 const filterBlockInputs = (blockElement, allowedValues, hasActiveFilters) => { 6417 const inputs = blockElement.querySelectorAll('input') 6418 const allowedStrings = allowedValues.map(String) 6419 6420 inputs.forEach(input => { 6421 const parent = input.closest('.offer-tile__filter-item') 6422 if (!parent || input.value === "" || input.value === "all") return 6423 6424 const dataItemId = input.getAttribute('data-item-id') 6425 const inputValues = dataItemId ? [dataItemId] : input.value.split('|') 6426 6427 const isAllowed = inputValues.some(val => allowedStrings.includes(val)) 6428 const isForbidden = hasActiveFilters && !isAllowed 6429 6430 parent.classList.toggle('disabled', isForbidden) 6431 }) 6432 } 6433 6434 function sortSubjects (subjectsJSON) { 6435 let subjectsParsed 6436 6437 try { 6438 subjectsParsed = JSON.parse(subjectsJSON) 6439 } catch (e) { 6440 return 6441 } 6442 6443 if (!subjectsParsed) return 6444 6445 let activeTabSet = false 6446 6447 const allowedSubjects = new Set(subjectsParsed.map(String)) 6448 6449 subjectInputs.forEach((subject) => { 6450 const dataItemId = subject.getAttribute('data-item-id') 6451 const inputValues = dataItemId ? [dataItemId] : subject.value.split('|') 6452 const isAllowed = inputValues.some(val => allowedSubjects.has(val)) 6453 if (!isAllowed) return 6454 6455 const label = subject.closest('.offer-tile__filter-item') 6456 if (!label) return 6457 6458 label.style.display = 'block' 6459 6460 const index = label.getAttribute('data-index') 6461 6462 const tab = filterSubject.querySelector( 6463 `.offer-tile__filter-tab[data-index="${index}"]` 6464 ) 6465 6466 if (tab) { 6467 tab.classList.remove('hide') 6468 6469 if (!activeTabSet) { 6470 tab.click() 6471 activeTabSet = true 6472 } 6473 } 6474 }) 6475 6476 updateTabsCounters() 6477 } 6478 6479 function updateTabsCounters () { 6480 const wrap = filterSubject.querySelector('.offer-tile__filter-wrap') 6481 const boxes = wrap?.querySelectorAll('.offer-tile__filter-box') || [] 6482 6483 boxes.forEach((box) => { 6484 const index = box.getAttribute('data-index') 6485 const tab = wrap.querySelector(`[data-index="${index}"]`) 6486 const labels = box.querySelectorAll('[style*="display: block"]') 6487 const counter = tab?.querySelector('span') 6488 const title = box.previousElementSibling 6489 6490 if (counter) counter.innerText = labels.length 6491 6492 box.classList.toggle('hide-mob', labels.length === 0) 6493 title?.classList.toggle('hide-mob', labels.length === 0) 6494 }) 6495 } 6496 6497 function hideAllSubjects () { 6498 filterSubject 6499 .querySelectorAll('.offer-tile__filter-tab') 6500 .forEach((tab) => tab.classList.add('hide')) 6501 6502 filterSubject 6503 .querySelector('.offer-tile__filter-tab.active') 6504 ?.classList.remove('active') 6505 6506 filterSubject 6507 .querySelectorAll('.offer-tile__filter-item') 6508 .forEach((item) => { 6509 item.style.display = 'none' 6510 }) 6511 } 6512 6513 function resetSortSubjects () { 6514 filterSubject 6515 .querySelectorAll('.offer-tile__filter-tab') 6516 .forEach((tab) => tab.classList.remove('hide')) 6517 6518 filterSubject 6519 .querySelector('.offer-tile__filter-tab.active') 6520 ?.classList.remove('active') 6521 6522 filterSubject 6523 .querySelector('.offer-tile__filter-tab') 6524 ?.click() 6525 6526 filterSubject 6527 .querySelectorAll('.offer-tile__filter-item') 6528 .forEach((item) => { 6529 item.style.display = 'block' 6530 }) 6531 6532 updateTabsCounters() 6533 } 6534 6535 function initObserver () { 6536 if (!tile) return 6537 6538 const observer = new MutationObserver((mutations) => { 6539 mutations.forEach((mutation) => { 6540 if (!mutation.addedNodes.length) return 6541 6542 mutation.addedNodes.forEach((node) => { 6543 if (!node?.classList?.contains(config.itemSelector.slice(1))) return 6544 6545 dataHrefLinksInit(node) 6546 6547 if (isEnrich) togglePrice(node) 6548 6549 fancyboxAjaxCardsReInit(node) 6550 initCommonAnalytics(node) 6551 }) 6552 }) 6553
6554 moreBtnInit() 6555 }) 6556 6557 observer.observe(tile, configObserver) 6558 } 6559 6560 function togglePrice (node) { 6561 const items = node 6562 ? [node] 6563 : [...tile.querySelectorAll('.all-courses__item')] 6564 6565 items.forEach((item) => { 6566 const toggles = item.querySelectorAll('.all-courses__radio-input') 6567 6568 if (!toggles.length) return 6569 6570 const boxes = item.querySelectorAll('.all-courses__box') 6571 const textReplace = item.querySelector('.all-courses__info.text-replace') 6572 const texts = textReplace?.querySelectorAll('.all-courses__info-span') 6573 6574 toggles.forEach((toggle) => { 6575 toggle.addEventListener('change', () => toggleElements(boxes)) 6576 6577 if (texts) { 6578 toggle.addEventListener('change', () => toggleElements(texts)) 6579 } 6580 }) 6581 }) 6582 } 6583 6584 function toggleElements (elements) { 6585 elements.forEach((element) => element.classList.toggle('hide')) 6586 } 6587 6588 function moreBtnInit () { 6589 const moreBtn = root.querySelector('.all-courses__more-button') 6590 6591 if (!moreBtn) return 6592 6593 const newBtn = replaceBtn(moreBtn) 6594 6595 newBtn.addEventListener('click', () => { 6596 makeFiltration(newBtn.getAttribute('data-v')) 6597 }) 6598 } 6599 6600 function replaceBtn (element) { 6601 const newElement = element.cloneNode(true) 6602 6603 element.parentNode.replaceChild(newElement, element) 6604 6605 return newElement 6606 } 6607 6608 function makeFiltration (page = 1) { 6609 const activeClass = filterClass.querySelector('input:checked') 6610 const activeSubject = filterSubject.querySelector('input:checked') 6611 6612 if (!activeSubject && (activeClass?.value === "" || activeClass?.value === "all")) { 6613 if (reset) reset.style.display = 'none' 6614 } else { 6615 if (reset) reset.style.display = 'flex' 6616 } 6617 6618 const gradesResult = [ 6619 ...root.querySelectorAll( 6620 '.offer-tile__filter-input_class:checked' 6621 ) 6622 ].map((item) => item.value).join('|') 6623 6624 const subjectsResult = [ 6625 ...root.querySelectorAll( 6626 '.offer-tile__filter-input_subject:checked' 6627 ) 6628 ].map((item) => item.value).join('|') 6629 6630 const requestData = { 6631 grade: gradesResult, 6632 subject: subjectsResult, 6633 utm_t: tile?.getAttribute('data-utm'), 6634 promo: tile?.getAttribute('data-promo'), 6635 pagePaginate: page 6636 } 6637 6638 if (isEnrich) { 6639 requestData.summerny = getSummerny() 6640 } 6641 6642 if (page === 1) { 6643 $('.filtered_elements').html("<div class='tile-loader'></div>") 6644 $('.more_b').html('') 6645 } 6646 6647 $.request( 6648 isEnrich 6649 ? 'DirectionFunctions::onPaginateAllCourses' 6650 : requestFunction, 6651 { 6652 data: requestData 6653 } 6654 ) 6655 6656 if (!isEnrich && isSumPage && gradesResult && gradesResult !== 'all') { 6657 6658 const url = new URL(window.location.href) 6659 url.searchParams.set('gr', gradesResult.split('|')[0]) 6660 history.replaceState(null, '', url.toString()) 6661 6662 } else if (gradesResult === 'all') { 6663 6664 const url = new URL(window.location.href) 6665 url.searchParams.delete('gr') 6666 history.replaceState(null, '', url.toString()) 6667 6668 } 6669 } 6670 6671 function getSummerny () { 6672 if (filterSumr?.checked) { 6673 return filterSumr.getAttribute('data-value') || '' 6674 } 6675 6676 if (filterNewy?.checked) { 6677 return filterNewy.getAttribute('data-value') || '' 6678 } 6679 6680 return '' 6681 } 6682 6683 function initSimpleTabs () { 6684 const tabsParent = filterSubject.querySelector( 6685 '.offer-tile__filter-tabs' 6686 ) 6687 6688 const tabs = filterSubject.querySelectorAll( 6689 '.offer-tile__filter-tab' 6690 ) 6691 6692 const subjects = filterSubject.querySelectorAll( 6693 '.offer-tile__filter-item' 6694 ) 6695 6696 if (!tabs.length || !subjects.length) return 6697
6698 tabs.forEach((tab) => { 6699 tab.addEventListener('click', (e) => { 6700 e.stopPropagation() 6701 6702 filterSubject 6703 .querySelector('.offer-tile__filter-tab.active') 6704 ?.classList.remove('active') 6705 6706 tab.classList.add('active') 6707 6708 subjects.forEach((subject) => { 6709 subject.classList.add('hide') 6710 }) 6711 6712 const index = tab.getAttribute('data-index') 6713 6714 filterSubject 6715 .querySelectorAll(`[data-index="${index}"]`) 6716 .forEach((subject) => { 6717 subject.classList.remove('hide') 6718 }) 6719 6720 if (tabsParent) { 6721 tabsParent.scrollLeft = 6722 tab.offsetLeft - 6723 tabsParent.clientWidth / 2 + 6724 tab.clientWidth / 2 6725 } 6726 }) 6727 }) 6728 6729 tabs[0].click() 6730 } 6731 6732 function initAdvancedTabs () { 6733 const wrap = filterSubject.querySelector( 6734 '.offer-tile__filter-wrap' 6735 ) 6736 6737 const tabsParent = wrap?.querySelector( 6738 '.offer-tile__filter-tabs' 6739 ) 6740 6741 const list = wrap?.querySelector( 6742 '.offer-tile__filter-list' 6743 ) 6744 6745 const tabs = wrap?.querySelectorAll( 6746 '.offer-tile__filter-tab' 6747 ) || [] 6748 6749 const boxes = wrap?.querySelectorAll( 6750 '.offer-tile__filter-box' 6751 ) || [] 6752 6753 const headline = filterSubject.querySelector( 6754 '.offer-tile__filter-headline.desk' 6755 ) 6756 6757 if (!wrap || !tabs.length || !boxes.length) return 6758 6759 let timeout 6760 let firstToggle = true 6761 6762 const toggle = (tab, event) => { 6763 if ( 6764 !tab.closest('.offer-tile__filter-wrap') 6765 ?.querySelector('.offer-tile__filter-tab:hover') && 6766 !firstToggle && 6767 event.type !== 'click' 6768 ) { 6769 return 6770 } 6771 6772 firstToggle = false 6773 6774 wrap.removeEventListener('scroll', onScroll) 6775 6776 wrap 6777 .querySelector('.offer-tile__filter-tab.active') 6778 ?.classList.remove('active') 6779 6780 tab.classList.add('active') 6781 6782 if (headline) { 6783 headline.innerHTML = tab.getAttribute('data-text') || '' 6784 } 6785 6786 boxes.forEach((box) => { 6787 box.classList.add('hide') 6788 6789 if ( 6790 box.previousElementSibling?.classList.contains( 6791 'all-courses__filter-box-title' 6792 ) 6793 ) { 6794 box.previousElementSibling.style.display = 'none' 6795 } 6796 }) 6797 6798 const index = tab.getAttribute('data-index') 6799 6800 const activeBox = list?.querySelector( 6801 `[data-index="${index}"]` 6802 ) 6803 6804 if (activeBox) { 6805 activeBox.classList.remove('hide') 6806 6807 if (activeBox.previousElementSibling) { 6808 activeBox.previousElementSibling.style.display = '' 6809 } 6810 6811 wrap.scrollTop = activeBox.offsetTop - 150 6812 } 6813 6814 if (tabsParent) { 6815 tabsParent.scrollLeft = 6816 tab.offsetLeft - 6817 tabsParent.clientWidth / 2 + 6818 tab.clientWidth / 2 6819 } 6820 6821 setTimeout(() => { 6822 wrap.addEventListener('scroll', onScroll, { passive: true }) 6823 }, 200) 6824 } 6825 6826 const onScroll = () => { 6827 const visibleBoxes = [...boxes].filter( 6828 (box) => !box.classList.contains('hide-mob') 6829 ) 6830 6831 visibleBoxes.forEach((box) => { 6832 if (wrap.scrollTop >= box.offsetTop - 155) { 6833 wrap 6834 .querySelector('.offer-tile__filter-tab.active') 6835 ?.classList.remove('active') 6836 6837 const tab = wrap.querySelector( 6838 `[data-index="${box.getAttribute('data-index')}"]` 6839 ) 6840 6841 if (tab) { 6842 tab.classList.add('active') 6843 6844 if (tabsParent) { 6845 tabsParent.scrollLeft = 6846 tab.offsetLeft - 6847 tabsParent.clientWidth / 2 + 6848 tab.clientWidth / 2 6849 } 6850 } 6851 } 6852 }) 6853 } 6854 6855 wrap.addEventListener('scroll', onScroll, { passive: true }) 6856
6857 tabs.forEach((tab) => { 6858 const handler = (event) => { 6859 clearTimeout(timeout) 6860 event.stopPropagation() 6861 timeout = setTimeout(() => toggle(tab, event), 100) 6862 } 6863 6864 tab.addEventListener('click', handler) 6865 tab.addEventListener('mouseenter', handler) 6866 }) 6867 6868 tabs[0]?.click() 6869 } 6870 } 6871})() 6872 6873 6874$("[data-fancybox]").fancybox({ 6875 beforeShow: function(instance){ 6876 try { 6877 const form = document.querySelector(this.src) 6878 const openButton = instance.current.opts.$orig 6879 if (form) { 6880 setDataFtitle(openButton, form) 6881 setBannerName(openButton, form) 6882 } 6883 } catch (e) {} 6884 }, 6885 afterClose: function() { 6886 try { 6887 const form = document.querySelector(this.src) 6888 if (form) { 6889 setDefaultDataFtitle(form) 6890 setDefaultBannerName(form) 6891 } 6892 } catch (e) {} 6893 } 6894}) 6895 6896function setBannerName (button, form) { 6897 const input = form.querySelector('input[name="banner_v"]') 6898 const value = button.attr('data-banner') 6899 if (input && value) input.value = value 6900} 6901 6902function setDefaultBannerName (form) { 6903 const input = form.querySelector('input[name="banner_v"]') 6904 if (input) input.value = '' 6905} 6906 6907function setDataFtitle (button, form) { 6908 const title = button.attr('data-ftitle') 6909 const titleTag = form.querySelector('.modal-order-new__title') 6910 if (title && title?.length > 1 && titleTag) { 6911 titleTag.innerHTML = title 6912 } 6913} 6914 6915function setDefaultDataFtitle (form) { 6916 const titleTag = form.querySelector('.modal-order-new__title') 6917 if (titleTag) { 6918 const defaultTitle = titleTag.getAttribute('data-default-title') 6919 if (defaultTitle) titleTag.innerHTML = defaultTitle 6920 } 6921} 6922 6923 6924const modalOrderNewSelects = document.querySelectorAll(".modal-order-new__select") 6925 6926for (let i = 0; i < modalOrderNewSelects.length; i++) { 6927 modalOrderNewSelectInit(modalOrderNewSelects[i]) 6928} 6929 6930function modalOrderNewSelectInit (modalOrderNewSelect) { 6931 const top = modalOrderNewSelect.querySelector('.modal-order-new__select-top') 6932 const placeholder = modalOrderNewSelect.querySelector('.modal-order-new__select-placeholder') 6933 const inputs = modalOrderNewSelect.querySelectorAll('.modal-order-new__select-input') 6934 6935 for (let i = 0; i < inputs.length; i++) { 6936 inputs[i].addEventListener('change', setValue) 6937 } 6938 6939 top.addEventListener('click', openSelect) 6940 window.addEventListener('click', closeSelect) 6941 6942 function openSelect (e) { 6943 e.stopPropagation() 6944 top.classList.toggle('active') 6945 } 6946 6947 function closeSelect () { 6948 top.classList.remove('active') 6949 } 6950 6951 function setValue () { 6952 placeholder.innerHTML = this.parentElement.querySelector('.modal-order-new__select-view').innerHTML 6953 } 6954} 6955 6956const nav = document.querySelector('.header .nav') 6957 6958 if (nav) navInit() 6959 6960 function navInit () { 6961 const buttons = nav.querySelectorAll('button.nav__box-link') 6962 const headerArea = document.querySelector('.header__area') 6963 const navBackButtons = nav.querySelectorAll('.nav__back') 6964 const navScrollers = nav.querySelectorAll('.nav__scroller') 6965 const navLeftScroller = nav.querySelector('.nav__left-scroller') 6966 let timeout 6967 6968 for (let i = 0; i < buttons.length; i++) { 6969 buttons[i].addEventListener('click', toggleArea) 6970 buttons[i].addEventListener('mouseenter', toggleArea) 6971 } 6972 6973 for (let i = 0; i < navBackButtons.length; i++) { 6974 navBackButtons[i].addEventListener('click', backArea) 6975 } 6976 6977 function backArea () { 6978 const activeArea = nav.querySelector('.nav__area.active-mob') 6979 if (activeArea) activeArea.classList.remove('active-mob') 6980 headerArea.classList.remove('hide') 6981 } 6982 6983 function toggleArea () { 6984 clearTimeout(timeout) 6985 timeout = setTimeout(() => toggle(this),50) 6986 6987 function toggle (that) { 6988 if (!that.closest('.nav__left').querySelector('.nav__box-link:hover')) return 6989 const id = that.getAttribute('data-nav-id') 6990 const oldArea = nav.querySelector('.nav__area.active') 6991 if (oldArea) oldArea.classList.remove('active') 6992 if (oldArea) oldArea.classList.remove('active-mob') 6993 const oldButton = nav.querySelector('button.nav__box-link.active') 6994 if (oldButton) oldButton.classList.remove('active') 6995 const area = nav.querySelector("[data-nav-area='" + id + "']") 6996 if (area) area.classList.add('active') 6997 if (area) area.classList.add('active-mob') 6998 headerArea.classList.add('hide') 6999 that.classList.add('active') 7000 } 7001 } 7002 initSimpleBar() 7003 7004 function initSimpleBar () { 7005 if (window.innerWidth >= 744) { 7006 for (let i = 0; i < navScrollers.length; i++) { 7007 new SimpleBar(navScrollers[i]) 7008 } 7009 new SimpleBar(navLeftScroller) 7010 } 7011 } 7012 } 7013 7014// const enrichTile = document.getElementById("enrich-tile") 7015 7016// if (enrichTile) enrichTileInit() 7017 7018// function enrichTileInit () { 7019// if (window.location.href.includes('#enrich-tile')) { 7020// window.addEventListener('load', function() { 7021// let offset 7022// if (window.innerWidth < 744) { 7023// offset = 60 7024// } else if (window.innerWidth < 1200) { 7025// offset = 80 7026// } else { 7027// offset = 80 7028// } 7029// window.scrollTo({ 7030// top: enrichTile.getBoundingClientRect().top + window.scrollY - offset, 7031// behavior: 'smooth' 7032// }) 7033// }, { once: true }) 7034// } 7035 7036// const enrichTileFilterTops = enrichTile.querySelectorAll(".offer-tile__filter-top") 7037// const filterSubject = enrichTile.querySelector(".offer-tile__filter_subject") 7038// const filterClass = enrichTile.querySelector(".offer-tile__filter_class") 7039// const stickyHeader = document.querySelector('.sticky-header') 7040// const body = document.querySelector('body') 7041// const filterSumr = enrichTile.querySelector('[data-role="filter-sumr"]') 7042// const filterNewy = enrichTile.querySelector('[data-role="filter-newy"]') 7043 7044// filterSumr?.addEventListener('change', updateFilter) 7045// filterNewy?.addEventListener('change', updateFilter) 7046 7047 7048// enrichTileFilterTops[0].addEventListener("click", (e)=> openFilter(enrichTileFilterTops[0], e)) 7049// enrichTileFilterTops[1].addEventListener("click", (e)=> openFilter(enrichTileFilterTops[1], e)) 7050 7051// document.addEventListener('click', function () { 7052// enrichTileFilterTops[0].classList.remove('active') 7053// enrichTileFilterTops[1].classList.remove('active') 7054// showHeader() 7055// }) 7056 7057// function openFilter (opener, e) { 7058// e.stopPropagation() 7059// if (!opener.classList.contains('active')) { 7060// const oldActive = enrichTile.querySelector('.offer-tile__filter-top.active') 7061// if (oldActive) oldActive.classList.remove('active') 7062// const oldActiveFilter = enrichTile.querySelector('.offer-tile__filter.active') 7063// if (oldActiveFilter) oldActiveFilter.classList.remove('active') 7064// closeSelectFilter() 7065// } 7066// if (opener.classList.contains('active')) { 7067// opener.classList.remove('active') 7068// showHeader() 7069// opener.parentElement.classList.remove('active') 7070// } else { 7071// opener.classList.add('active') 7072// opener.parentElement.classList.add('active') 7073// hideHeader() 7074// } 7075// } 7076 7077// function closeSelectFilter () { 7078// const oldSelectFilterOpen = document.querySelector(".select-filter.active") 7079// if (oldSelectFilterOpen) { 7080// oldSelectFilterOpen.classList.remove('active') 7081// oldSelectFilterOpen.querySelector('.select-filter__top').classList.remove('active') 7082// } 7083// } 7084 7085// function showHeader () { 7086// stickyHeader.classList.remove('hide') 7087// body.classList.remove('no-scroll') 7088// } 7089 7090// function hideHeader () { 7091// if (window.innerWidth < 744) { 7092// stickyHeader.classList.add('hide') 7093// body.classList.add('no-scroll') 7094// } 7095// } 7096 7097// const config = { attributes: true, childList: true, characterData: true, subtree: true } 7098// const tile = enrichTile.querySelector('.all-courses__tile') 7099// const classInputs = enrichTile.querySelectorAll('.offer-tile__filter-input_class') 7100// const classInputText = enrichTile.querySelector('.offer-tile__filter_class .offer-tile__filter-top-text') 7101// const subjectInputs = enrichTile.querySelectorAll('.offer-tile__filter-input_subject') 7102// const subjectInputText = enrichTile.querySelector('.offer-tile__filter_subject .offer-tile__filter-top-text') 7103 7104// const observer = new MutationObserver(function observerCallback(mutations) { 7105// mutations.forEach( 7106// (mutation) => { 7107// if (mutation.addedNodes.length) {
7108// mutation.addedNodes.forEach((node) => { 7109// if (node?.classList?.contains('all-courses__item')) { 7110// dataHrefLinksInit(node) 7111// togglePrice(node) 7112// fancyboxAjaxCardsReInit(node) 7113// initCommonAnalytics(node) 7114// } 7115// }) 7116// } 7117// }) 7118 7119// moreBtnInit() 7120// }) 7121 7122// if (tile) togglePrice() 7123 7124// function togglePrice (node) { 7125// if (node) { 7126// togglePriceHandler(node) 7127// } else { 7128// const items = tile?.querySelectorAll(".all-courses__item") 7129// items.forEach((item) => { 7130// togglePriceHandler(item) 7131// }) 7132// } 7133// function togglePriceHandler (item) { 7134// const toggle = item.querySelectorAll('.all-courses__radio-input') 7135// if (!toggle.length) return 7136// const boxes = item.querySelectorAll('.all-courses__box') 7137// const textReplace = item.querySelector('.all-courses__info.text-replace') 7138// let texts 7139// if (textReplace) { 7140// texts = textReplace.querySelectorAll('.all-courses__info-span') 7141// } 7142// for (let i = 0; i < toggle.length; i++) { 7143// toggle[i].addEventListener('change', toggleBoxes) 7144// if (texts) toggle[i].addEventListener('change', toggleTexts) 7145// } 7146 7147// function toggleBoxes () { 7148// for (let i = 0; i < boxes.length; i++) { 7149// if (boxes[i].classList.contains('hide')) { 7150// boxes[i].classList.remove('hide') 7151// } else { 7152// boxes[i].classList.add('hide') 7153// } 7154// } 7155// } 7156 7157// function toggleTexts () { 7158// for (let i = 0; i < texts.length; i++) { 7159// if (texts[i].classList.contains('hide')) { 7160// texts[i].classList.remove('hide') 7161// } else { 7162// texts[i].classList.add('hide') 7163// } 7164// } 7165// } 7166// } 7167// } 7168 7169 7170 7171 7172 7173// if (tile) observer.observe(tile, config) 7174 7175// const reset = enrichTile.querySelector('.offer-tile__reset-filter') 7176// if (reset) reset.addEventListener('click', resetFilters) 7177 7178// function resetFilters () { 7179// const items = enrichTile.querySelectorAll("input") 7180// items.forEach((item) => { 7181// if (item.hasAttribute('data-default-garde') || item.hasAttribute('data-default-subject')) { 7182// item.checked = true 7183// }else{ 7184// item.checked = false 7185// } 7186// }) 7187// reset.style.display = 'none' 7188// classInputText.innerHTML = "ÐÑе клаÑÑÑ" 7189// subjectInputText.innerHTML = "ÐÑе пÑедмеÑÑ" 7190// makeFiltration(); 7191// } 7192 7193// for (let i = 0; i < classInputs.length; i++) { 7194// classInputs[i].addEventListener('change', updateFilter) 7195// classInputs[i].addEventListener('change', changeClassInputText) 7196// } 7197 7198// function changeClassInputText () { 7199// classInputText.innerHTML = this.getAttribute('data-text') 7200// } 7201 7202// for (let i = 0; i < subjectInputs.length; i++) { 7203// subjectInputs[i].addEventListener('change', updateFilter) 7204// subjectInputs[i].addEventListener('change', changeSubjectInputText) 7205// } 7206 7207// function changeSubjectInputText () { 7208// subjectInputText.innerHTML = this.getAttribute('data-text') 7209// } 7210 7211// moreBtnInit() 7212 7213// function moreBtnInit () { 7214// const moreBtn = enrichTile.querySelector('.all-courses__more-button') 7215// if (moreBtn) { 7216// const newBtn = replaceBtn(moreBtn) 7217// newBtn.addEventListener('click', () => makeFiltration(newBtn.getAttribute('data-v'))) 7218// } 7219// } 7220 7221// function replaceBtn (oldElement) { 7222// const newElement = oldElement.cloneNode(true) 7223// oldElement.parentNode.replaceChild(newElement, oldElement) 7224// return newElement 7225// } 7226 7227 7228// function updateFilter () { 7229// const itemsAll = enrichTile.querySelectorAll(["input:checked"]) 7230// if (itemsAll.length) { 7231// if (reset) reset.style.display = 'flex' 7232// } else { 7233// if (reset) reset.style.display = 'none' 7234// } 7235// makeFiltration() 7236// } 7237 7238// function makeFiltration (p_paginate = 1) { 7239// const grades_items = enrichTile.querySelectorAll('.offer-tile__filter-input_class:checked') 7240// let grades_result = '' 7241// let grade_first = 0
7242// grades_items.forEach((item, i) => { 7243// if (i > 0) grades_result += '|' 7244// if (grade_first == 0) grade_first = item.value 7245// grades_result += item.value 7246// }) 7247// let subjects_result = '' 7248// try{ 7249// const subjects_items = enrichTile.querySelectorAll('.offer-tile__filter-input_subject:checked') 7250// subjects_items.forEach((item, i) => { 7251// if (i > 0) subjects_result += '|' 7252// subjects_result += item.value 7253// }) 7254// }catch(e){} 7255 7256// let utm_f = tile.getAttribute('data-utm'); 7257// let promo_f = tile.getAttribute('data-promo'); 7258// // let oge_ege_type = tile.getAttribute('data-oge-ege'); 7259 7260// if(p_paginate === 1 ){ 7261// $('.filtered_elements').html("<div class='tile-loader'></div>"); 7262// $('.more_b').html(""); 7263// } 7264 7265 7266// var obData = { 7267// 'grade': grades_result, 7268// 'subject': subjects_result, 7269// 'utm_t': utm_f, 7270// 'promo': promo_f, 7271// 'pagePaginate': p_paginate, 7272// 'summerny': getSummerny(), 7273// }; 7274// $.request('DirectionFunctions::onPaginateAllCourses', { 7275// data: obData 7276// }) 7277// // if (grade_first > 0){ 7278// // let url = new URL(window.location.href) 7279// // url.searchParams.set('gr', grade_first); 7280// // history.replaceState(null, "", url.toString()) 7281// // } 7282// // } 7283// } 7284// function getSummerny () { 7285// let summerny = '' 7286// if (filterSumr?.checked) { 7287// summerny = filterSumr.getAttribute('data-value') 7288// } else if (filterNewy?.checked) { 7289// summerny = filterNewy.getAttribute('data-value') 7290// } 7291// return summerny 7292// } 7293 7294 7295// initTabs() 7296 7297// function initTabs () { 7298// const tabsParent = filterSubject.querySelector('.offer-tile__filter-tabs') 7299// const tabs = filterSubject.querySelectorAll('.offer-tile__filter-tab') 7300// const subjects = filterSubject.querySelectorAll('.offer-tile__filter-item') 7301 7302// if (!tabs.length || !subjects.length) return 7303
7304// tabs.forEach((tab) => { 7305// tab.addEventListener('click', changeTab) 7306 7307// function changeTab (e) { 7308// e.stopPropagation() 7309// const oldTab = filterSubject.querySelector('.offer-tile__filter-tab.active') 7310// if (oldTab) oldTab.classList.remove('active') 7311 7312// this.classList.add('active') 7313 7314// subjects.forEach((subject) => { 7315// subject.classList.add('hide') 7316// }) 7317 7318// const index = this.getAttribute('data-index') 7319// const activeSubjects = filterSubject.querySelectorAll('[data-index="' + index + '"]') 7320// activeSubjects.forEach((subject) => { 7321// subject.classList.remove('hide') 7322// }) 7323 7324// tabsParent.scrollLeft = this.offsetLeft - tabsParent.clientWidth/2 + this.clientWidth/2 7325// } 7326// }) 7327 7328// tabs[0].click() 7329// } 7330 7331// } 7332 7333// const offerTile = document.getElementById("offer-tile") 7334 7335// if (offerTile) offerTileInit() 7336 7337// function offerTileInit () { 7338// if (window.location.href.includes('#offer-tile')) { 7339// window.addEventListener('load', function() { 7340// let offset 7341// if (window.innerWidth < 744) { 7342// offset = 60 7343// } else if (window.innerWidth < 1200) { 7344// offset = 80 7345// } else { 7346// offset = 80 7347// } 7348// window.scrollTo({ 7349// top: offerTile.getBoundingClientRect().top + window.scrollY - offset, 7350// behavior: 'smooth' 7351// }) 7352// }, { once: true }) 7353// } 7354 7355// const offerTileFilterTops = offerTile.querySelectorAll(".offer-tile__filter-top") 7356// const filterSubject = offerTile.querySelector(".offer-tile__filter_subject") 7357// const filterClass = offerTile.querySelector(".offer-tile__filter_class") 7358// const stickyHeader = document.querySelector('.sticky-header') 7359// const body = document.querySelector('body') 7360// const isSumPage = offerTile.classList.contains('offer-tile_sum') 7361// const requestFunction = offerTile.getAttribute('data-request-function') 7362// const openers = offerTile.querySelectorAll(".offer-tile__filter-top") 7363// const config = { attributes: true, childList: true, characterData: true, subtree: true } 7364// const tile = offerTile.querySelector('.offer-tile__tile') 7365// const classInputs = offerTile.querySelectorAll('.offer-tile__filter-input_class') 7366// const classInputText = offerTile.querySelector('.offer-tile__filter_class .offer-tile__filter-top-text') 7367// const subjectInputs = offerTile.querySelectorAll('.offer-tile__filter-input_subject') 7368// const subjectInputText = offerTile.querySelector('.offer-tile__filter_subject .offer-tile__filter-top-text') 7369 7370 7371 7372// offerTileFilterTops[0].addEventListener("click", (e)=> openFilter(offerTileFilterTops[0], e)) 7373// offerTileFilterTops[1].addEventListener("click", (e)=> openFilter(offerTileFilterTops[1], e)) 7374 7375// document.addEventListener('click', function () { 7376// offerTileFilterTops[0].classList.remove('active') 7377// offerTileFilterTops[1].classList.remove('active') 7378// showHeader() 7379// }) 7380 7381// function openFilter (opener, e) { 7382// e.stopPropagation() 7383// if (opener.getAttribute('data-ftype') === 'class_subjects' && !selectedClass() && isSumPage) { 7384// setError() 7385// return 7386// } else { 7387// resetError() 7388// } 7389// if (!opener.classList.contains('active')) { 7390// const oldActive = offerTile.querySelector('.offer-tile__filter-top.active') 7391// if (oldActive) oldActive.classList.remove('active') 7392// const oldActiveFilter = offerTile.querySelector('.offer-tile__filter.active') 7393// if (oldActiveFilter) oldActiveFilter.classList.remove('active') 7394// } 7395// if (opener.classList.contains('active')) { 7396// opener.classList.remove('active') 7397// showHeader() 7398// opener.parentElement.classList.remove('active') 7399// } else { 7400// opener.classList.add('active') 7401// opener.parentElement.classList.add('active') 7402// hideHeader() 7403// } 7404// } 7405 7406// function showHeader () { 7407// stickyHeader.classList.remove('hide') 7408// body.classList.remove('no-scroll') 7409// } 7410 7411// function hideHeader () { 7412// if (window.innerWidth < 744) { 7413// stickyHeader.classList.add('hide') 7414// body.classList.add('no-scroll') 7415// } 7416// } 7417 7418 7419 7420// const observer = new MutationObserver(function observerCallback(mutations) { 7421// mutations.forEach( 7422// (mutation) => { 7423// if (mutation.addedNodes.length) {
7424// mutation.addedNodes.forEach((node) => { 7425// if (node?.classList?.contains('offer-tile__item')) { 7426// dataHrefLinksInit(node) 7427// fancyboxAjaxCardsReInit(node) 7428// initCommonAnalytics(node) 7429// } 7430// }) 7431// } 7432// }) 7433// moreBtnInit() 7434// }) 7435 7436// if (tile) observer.observe(tile, config) 7437 7438// const reset = offerTile.querySelector('.offer-tile__reset-filter') 7439// if (reset) reset.addEventListener('click', resetFilters) 7440 7441// function resetFilters () { 7442// const items = offerTile.querySelectorAll("input") 7443// items.forEach((item) => { 7444// if (item.hasAttribute('data-default-garde') || item.hasAttribute('data-default-subject')) { 7445// item.checked = true 7446// }else{ 7447// item.checked = false 7448// } 7449// }) 7450// reset.style.display = 'none' 7451// classInputText.innerHTML = "ÐÑе клаÑÑÑ" 7452// subjectInputText.innerHTML = "ÐÑе пÑедмеÑÑ" 7453// resetSortSubjects() 7454// makeFiltration() 7455// } 7456 7457// for (let i = 0; i < classInputs.length; i++) { 7458// classInputs[i].addEventListener('change', () => updateFilter(true)) 7459// classInputs[i].addEventListener('change', changeClassInputText) 7460// } 7461 7462// function sortSubjectsInit () { 7463// resetSortSubjects() 7464// const subjectsArray = selectedClass()?.getAttribute('data-subjects') 7465// if (subjectsArray) { 7466// hideAllSubjects() 7467// sortSubjects(subjectsArray) 7468// } 7469// } 7470 7471// sortSubjectsInit() 7472 7473// function selectedClass () { 7474// return filterClass.querySelector(["input:checked"]) 7475// } 7476 7477 7478 7479// function sortSubjects (subjectsJSON) { 7480// const subjectsParsed = JSON.parse(subjectsJSON) 7481// if (!subjectsParsed) return 7482// let isTabActiveSet = false 7483// subjectInputs.forEach((subject) => { 7484// if (subjectsParsed.includes(+subject.value)) { 7485// const label = subject.closest('.offer-tile__filter-item') 7486// if (label) { 7487// label.style.display = 'block' 7488// const index = label.getAttribute('data-index') 7489// const tab = document.querySelector('.offer-tile__filter-tab[data-index="' + index + '"]') 7490// if (tab) { 7491// tab.classList.remove('hide') 7492// if (!isTabActiveSet) { 7493// tab.click() 7494// isTabActiveSet = true 7495// } 7496// } 7497// } 7498// } 7499// }) 7500// } 7501 7502// function hideAllSubjects () { 7503// const tabs = document.querySelectorAll('.offer-tile__filter-tab') 7504// for (let i = 0; i < tabs.length; i++) { 7505// tabs[i].classList.add('hide') 7506// } 7507// const activeTab = document.querySelector('.offer-tile__filter-tab.active') 7508// if (activeTab) activeTab.classList.remove('active') 7509// const subjectLabels = filterSubject.querySelectorAll('.offer-tile__filter-item') 7510// for (let i = 0; i < subjectLabels.length; i++) { 7511// subjectLabels[i].style.display = 'none' 7512// } 7513// } 7514 7515// function resetSortSubjects () { 7516// const tabs = document.querySelectorAll('.offer-tile__filter-tab') 7517// for (let i = 0; i < tabs.length; i++) { 7518// tabs[i].classList.remove('hide') 7519// } 7520// const activeTab = document.querySelector('.offer-tile__filter-tab.active') 7521// if (activeTab) activeTab.classList.remove('active') 7522// if (tabs[0]) tabs[0].click() 7523// const subjectLabels = filterSubject.querySelectorAll('.offer-tile__filter-item') 7524// for (let i = 0; i < subjectLabels.length; i++) { 7525// subjectLabels[i].style.display = 'block' 7526// } 7527// const activeSubject = filterSubject.querySelector(["input:checked"]) 7528// if (activeSubject) activeSubject.checked = false 7529// subjectInputText.innerHTML = "ÐÑе пÑедмеÑÑ" 7530// } 7531 7532// function setError () { 7533// openers[0].parentElement.classList.add('offer-tile__filter_error') 7534// openers[1].parentElement.classList.add('offer-tile__filter_error') 7535// } 7536 7537// function resetError () { 7538// openers[0].parentElement.classList.remove('offer-tile__filter_error') 7539// openers[1].parentElement.classList.remove('offer-tile__filter_error') 7540// } 7541 7542 7543// function changeClassInputText () { 7544// classInputText.innerHTML = this.getAttribute('data-text') 7545// } 7546 7547// for (let i = 0; i < subjectInputs.length; i++) { 7548// subjectInputs[i].addEventListener('change', () => updateFilter(false)) 7549// subjectInputs[i].addEventListener('change', changeSubjectInputText) 7550// } 7551 7552// function changeSubjectInputText () { 7553// subjectInputText.innerHTML = this.getAttribute('data-text') 7554// } 7555
7556// moreBtnInit() 7557 7558// function moreBtnInit () { 7559// const moreBtn = offerTile.querySelector('.all-courses__more-button') 7560// if (moreBtn) { 7561// const newBtn = replaceBtn(moreBtn) 7562// newBtn.addEventListener('click', () => makeFiltration(newBtn.getAttribute('data-v'))) 7563// } 7564// } 7565 7566// function replaceBtn (oldElement) { 7567// const newElement = oldElement.cloneNode(true) 7568// oldElement.parentNode.replaceChild(newElement, oldElement) 7569// return newElement 7570// } 7571 7572 7573// function updateFilter (isClassUpdated) { 7574// if (isClassUpdated && isSumPage) sortSubjectsInit() 7575// const itemsAll = offerTile.querySelectorAll(["input:checked"]) 7576// if (itemsAll.length) { 7577// if (reset) reset.style.display = 'flex' 7578// } else { 7579// if (reset) reset.style.display = 'none' 7580// } 7581// makeFiltration() 7582// } 7583 7584// function makeFiltration (p_paginate = 1) { 7585// const grades_items = offerTile.querySelectorAll('.offer-tile__filter-input_class:checked') 7586// let grades_result = '' 7587// let grade_first = 0 7588// grades_items.forEach((item, i) => { 7589// if (i > 0) grades_result += '|' 7590// if (grade_first == 0) grade_first = item.value 7591// grades_result += item.value 7592// }) 7593// let subjects_result = '' 7594// try{ 7595// const subjects_items = offerTile.querySelectorAll('.offer-tile__filter-input_subject:checked') 7596// subjects_items.forEach((item, i) => { 7597// if (i > 0) subjects_result += '|' 7598// subjects_result += item.value 7599// }) 7600// }catch(e){} 7601 7602// let utm_f = tile.getAttribute('data-utm'); 7603// let promo_f = tile.getAttribute('data-promo'); 7604 7605// if(p_paginate === 1 ){ 7606// $('.filtered_elements').html("<div class='tile-loader'></div>"); 7607// $('.more_b').html(""); 7608// } 7609 7610// var obData = { 7611// 'grade': grades_result, 7612// 'subject': subjects_result, 7613// 'utm_t': utm_f, 7614// 'promo': promo_f, 7615// 'pagePaginate': p_paginate, 7616// }; 7617// // console.log(obData) 7618// $.request(requestFunction, { 7619// data: obData 7620// }) 7621// // if (grade_first > 0){ 7622// // let url = new URL(window.location.href) 7623// // url.searchParams.set('gr', grade_first); 7624// // history.replaceState(null, "", url.toString()) 7625// // } 7626// // } 7627// if (grade_first > 0 && isSumPage) { 7628// let url = new URL(window.location.href) 7629// url.searchParams.set('gr', grade_first); 7630// history.replaceState(null, "", url.toString()) 7631// } 7632 7633// } 7634 7635// initTabs() 7636 7637// function initTabs () { 7638// const tabsParent = filterSubject.querySelector('.offer-tile__filter-tabs') 7639// const tabs = filterSubject.querySelectorAll('.offer-tile__filter-tab') 7640// const subjects = filterSubject.querySelectorAll('.offer-tile__filter-item') 7641 7642// if (!tabs.length || !subjects.length) return 7643
7644// tabs.forEach((tab) => { 7645// tab.addEventListener('click', changeTab) 7646 7647// function changeTab (e) { 7648// e.stopPropagation() 7649// const oldTab = filterSubject.querySelector('.offer-tile__filter-tab.active') 7650// if (oldTab) oldTab.classList.remove('active') 7651 7652// this.classList.add('active') 7653 7654// subjects.forEach((subject) => { 7655// subject.classList.add('hide') 7656// }) 7657 7658// const index = this.getAttribute('data-index') 7659// const activeSubjects = filterSubject.querySelectorAll('[data-index="' + index + '"]') 7660// activeSubjects.forEach((subject) => { 7661// subject.classList.remove('hide') 7662// }) 7663 7664// tabsParent.scrollLeft = this.offsetLeft - tabsParent.clientWidth/2 + this.clientWidth/2 7665// } 7666// }) 7667 7668// tabs[0].click() 7669// } 7670 7671// } 7672 7673const offerTimers = document.querySelectorAll('.offer-timer') 7674 7675 if (offerTimers.length) offerTimersInit() 7676 7677 function offerTimersInit () { 7678 for (let i = 0; i < offerTimers.length; i++) { 7679 offerTimerInit(offerTimers[i]) 7680 } 7681 } 7682 7683 function offerTimerInit (timer) { 7684 const date = timer.getAttribute('date-end') 7685 const countDownDate = new Date(date).getTime() 7686 7687 const nodes = timer.querySelectorAll('.offer-timer__number') 7688 7689 const interval = setInterval(updateTimer, 1000) 7690 7691 function updateTimer () { 7692 const now = new Date().getTime(); 7693 const distance = countDownDate - now; 7694 7695 const days = Math.floor(distance / (1000 * 60 * 60 * 24)) 7696 const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)) 7697 const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)) 7698 const seconds = Math.floor((distance % (1000 * 60)) / 1000) 7699 7700 nodes[0].innerHTML = days 7701 nodes[1].innerHTML = hours 7702 nodes[2].innerHTML = minutes 7703 nodes[3].innerHTML = seconds 7704 7705 if (distance < 0) { 7706 clearInterval(interval); 7707 nodes[0].innerHTML = "0" 7708 nodes[1].innerHTML = "0" 7709 nodes[2].innerHTML = "0" 7710 nodes[3].innerHTML = "0" 7711 } 7712 } 7713 } 7714 7715const preAboutVideo = document.querySelector("[data-element='pre-about-video']") 7716 7717if (preAboutVideo) preAboutVideoInit() 7718 7719function preAboutVideoInit () { 7720 const videoWrap = document.querySelector("[data-element='pre-about-video-wrap']") 7721 const timeNode = document.querySelector("[data-element='pre-about-time']") 7722 const soundBtn = document.querySelector(".pre-about__sound") 7723 7724 preAboutVideo.addEventListener("timeupdate", timeupdateHandler) 7725 7726 function timeupdateHandler () { 7727 const date = new Date(null) 7728 date.setSeconds(Math.round(preAboutVideo.currentTime)) 7729 timeNode.innerHTML = date.toISOString().slice(14, 19) 7730 } 7731 7732 videoWrap.addEventListener('click', playVideo) 7733 7734 function playVideo (e) { 7735 e.stopPropagation() 7736 if (preAboutVideo.muted) { 7737 preAboutVideo.muted = false 7738 preAboutVideo.loop = false 7739 preAboutVideo.currentTime = 0 7740 preAboutVideo.play() 7741 soundBtn.classList.add('active') 7742 } else { 7743 preAboutVideo.muted = true 7744 soundBtn.classList.remove('active') 7745 } 7746 } 7747} 7748 7749const preFaqItems = document.querySelectorAll("[data-element='pre-faq-item']") 7750 7751for (let i = 0; i < preFaqItems.length; i++) { 7752 preFaqItems[i].addEventListener("click", toggleFaqItem) 7753 7754 function toggleFaqItem () { 7755 this.classList.toggle('active') 7756 } 7757} 7758 7759 7760 7761const preReviewsSlider = document.querySelector('[data-element="pre-reviews-slider"]') 7762 7763if (preReviewsSlider) preReviewsSliderInit() 7764 7765function preReviewsSliderInit () { 7766 const preReviewsSliderSwiper = new Swiper(preReviewsSlider, { 7767 mousewheel: { forceToAxis: true }, 7768 slidesPerView: 'auto', 7769 spaceBetween: 25, 7770 a11y: false, 7771 navigation: { 7772 nextEl: '.pre-reviews__nav-btn_right', 7773 prevEl: '.pre-reviews__nav-btn_left', 7774 }, 7775 scrollbar: { 7776 el: '.pre-reviews__scrollbar', 7777 draggable: true, 7778 }, 7779 breakpoints: { 7780 1440: { 7781 spaceBetween: 30, 7782 } 7783 } 7784 }) 7785} 7786 7787const preReviewsVideoWraps = document.querySelectorAll("[data-element='pre-reviews-video-wrap']") 7788 7789if (preReviewsVideoWraps.length) preReviewsVideoWrapsInit() 7790 7791function preReviewsVideoWrapsInit () { 7792 for (let i = 0; i < preReviewsVideoWraps.length; i++) { 7793 videoInit(preReviewsVideoWraps[i]) 7794 const video = preReviewsVideoWraps[i].querySelector("[data-element='pre-reviews-video']") 7795 video.addEventListener('play', stopOtherVideo) 7796 } 7797 7798 function stopOtherVideo () { 7799 const index = this.getAttribute('data-index') 7800 for (let i = 0; i < preReviewsVideoWraps.length; i++) { 7801 if (index != i) { 7802 let videoOther = preReviewsVideoWraps[i].querySelector("[data-element='pre-reviews-video']") 7803 videoOther.pause() 7804 } 7805 } 7806 } 7807 7808 function videoInit (wrap) { 7809 const video = wrap.querySelector("[data-element='pre-reviews-video']") 7810 wrap.addEventListener('click', playVideo, {once: true}) 7811 7812 function playVideo () { 7813 wrap.classList.add('active') 7814 video.controls = true 7815 setTimeout(() => video.play(), 100) 7816 } 7817 } 7818} 7819 7820const preStudySlider = document.querySelector('[data-element="pre-study-slider"]') 7821 7822if (preStudySlider) { 7823 var preStudySliderSwiper 7824 var animationPlayed = false 7825 const wrapper = preStudySlider.querySelector('.pre-study__wrapper') 7826 window.addEventListener('resize', watchSlider, {passive: true}) 7827 window.addEventListener('scroll', animateSlider, {passive: true}) 7828 watchSlider() 7829 7830 function initSlider () { 7831 preStudySliderSwiper = new Swiper(preStudySlider, { 7832 mousewheel: { forceToAxis: true }, 7833 slidesPerView: 'auto', 7834 spaceBetween: 25, 7835 loop: true, 7836 pagination: { 7837 el: ".pre-study__pagination", 7838 }, 7839 }) 7840 } 7841 7842 function watchSlider () { 7843 if (window.innerWidth < 1440) { 7844 preStudySliderSwiper?.destroy() 7845 initSlider() 7846 } else { 7847 preStudySliderSwiper?.destroy() 7848 } 7849 } 7850 7851 function animateSlider () { 7852 if (preStudySlider.getBoundingClientRect().top < window.innerHeight/2 && !animationPlayed && window.innerWidth < 992) { 7853 animationPlayed = true 7854 wrapper.style.transitionDuration = '0.5s' 7855 wrapper.style.transform = 'translate3d(-160px, 0, 0)' 7856 setTimeout(function () { 7857 wrapper.style.transform = 'translate3d(0, 0, 0)' 7858 }, 500) 7859 } 7860 } 7861} 7862 7863const preThanks = document.querySelector('.pre-thanks') 7864 7865if (preThanks) preThanksInit() 7866 7867function preThanksInit () { 7868 const url = new URL(window.location.href) 7869 //url.searchParams.delete('email') 7870// url.searchParams.delete('cemail') 7871// history.replaceState(null, "", url.toString()) 7872} 7873 7874const preWaysSlideArray = document.querySelectorAll('[data-element="pre-ways-slide"]') 7875 7876if (preWaysSlideArray.length) preWaysSlideArrayInit() 7877 7878function preWaysSlideArrayInit () { 7879 for (let i = 0; i < preWaysSlideArray.length; i++) { 7880 preWaysSlideInit(preWaysSlideArray[i]) 7881 } 7882 7883 function preWaysSlideInit (slide) { 7884 const list = slide.querySelector('[data-element="pre-ways-list"]') 7885 const btn = slide.querySelector('[data-element="pre-ways-more"]') 7886 7887 if (window.innerWidth >= 1200 ? list?.clientHeight > 140 : list?.clientHeight > 70) { 7888 btn.classList.add('show') 7889 btn.addEventListener('click', toggleList) 7890 slide.classList.add('hide') 7891 } 7892 7893 function toggleList () { 7894 if (slide.classList.contains('hide')) { 7895 slide.classList.remove('hide') 7896 btn.textContent = 'СвеÑнÑÑÑ' 7897 } else { 7898 slide.classList.add('hide') 7899 btn.textContent = 'ÐоказаÑÑ Ð²Ñе пÑедмеÑÑ' 7900 } 7901 } 7902 } 7903} 7904 7905const preWaysSlider = document.querySelector('[data-element="pre-ways__slider"]') 7906 7907if (preWaysSlider) preWaysSliderInit() 7908 7909function preWaysSliderInit () { 7910 let preWaysSliderSwiper 7911 window.addEventListener('resize', watchSlider, {passive: true}) 7912 watchSlider() 7913 7914 function watchSlider () { 7915 if (window.innerWidth < 1200) { 7916 preWaysSliderSwiper?.destroy() 7917 } else { 7918 preWaysSliderSwiper?.destroy() 7919 initSlider() 7920 } 7921 } 7922 7923 function initSlider () { 7924 preWaysSliderSwiper = new Swiper(preWaysSlider, { 7925 mousewheel: { forceToAxis: true }, 7926 slidesPerView: 'auto', 7927 spaceBetween: 25, 7928 pagination: { 7929 el: ".pre-ways__pagination", 7930 }, 7931 navigation: {
7932 nextEl: '.pre-ways__nav-btn_right', 7933 prevEl: '.pre-ways__nav-btn_left', 7934 }, 7935 scrollbar: { 7936 el: '.pre-ways__scrollbar', 7937 draggable: true, 7938 }, 7939 breakpoints: { 7940 1440: { 7941 spaceBetween: 30, 7942 } 7943 } 7944 }) 7945 } 7946} 7947 7948const predzapsNewWaysInners = document.querySelectorAll('.predzaps-new-ways__inner') 7949 7950let predzapsNewWaysInnerTimer 7951for (let i = 0; i < predzapsNewWaysInners.length; i++) { 7952 predzapsNewWaysInnerInit(predzapsNewWaysInners[i]) 7953} 7954 7955function predzapsNewWaysInnerInit (inner) { 7956 const tags = inner.querySelectorAll('.predzaps-new-ways__tag') 7957 7958 const toggle = inner.querySelector('.predzaps-new-ways__toggle') 7959 if (toggle) toggle.addEventListener('click', toggleTags) 7960 7961 if (getCountOfHiddenTags() === 0) { 7962 toggle.style.display = 'none' 7963 } else { 7964 toggle.innerHTML = `ÐоказаÑÑ ÐµÑÑ +${getCountOfHiddenTags()}` 7965 } 7966 7967 function toggleTags () { 7968 if (inner.classList.contains('active')) { 7969 inner.classList.remove('active') 7970 toggle.innerHTML = `ÐоказаÑÑ ÐµÑÑ +${getCountOfHiddenTags()}` 7971 if (predzapsNewWaysInnerTimer) clearInterval(predzapsNewWaysInnerTimer) 7972 } else { 7973 const oldActiveInner = document.querySelector('.predzaps-new-ways__inner.active') 7974 if (oldActiveInner) { 7975 oldActiveInner.classList.remove('active') 7976 const oldToggle = oldActiveInner.querySelector('.predzaps-new-ways__toggle') 7977 oldToggle.innerHTML = `ÐоказаÑÑ ÐµÑÑ +${getCountOfHiddenTags()}` 7978 } 7979 inner.classList.add('active') 7980 toggle.innerHTML = 'СвеÑнÑÑÑ' 7981 toggleTimer() 7982 } 7983 } 7984 7985 function toggleTimer () { 7986 if (predzapsNewWaysInnerTimer) clearInterval(predzapsNewWaysInnerTimer) 7987 7988 predzapsNewWaysInnerTimer = setInterval(() => { 7989 const oldActiveInner = document.querySelector('.predzaps-new-ways__inner.active') 7990 if (oldActiveInner) { 7991 oldActiveInner.classList.remove('active') 7992 const oldToggle = oldActiveInner.querySelector('.predzaps-new-ways__toggle') 7993 oldToggle.innerHTML = `ÐоказаÑÑ ÐµÑÑ +${getCountOfHiddenTags()}` 7994 } 7995 }, 10000) 7996 } 7997 7998 function getCountOfHiddenTags () { 7999 const height = inner.querySelector('.predzaps-new-ways__tags').clientHeight
8000 let counter = 0 8001 for (let i = 0; i < tags.length; i++) { 8002 if (tags[i].getBoundingClientRect().top - inner.getBoundingClientRect().top >= height) { 8003 counter += 1 8004 } 8005 } 8006 return counter 8007 } 8008} 8009 8010const predzapsThanks = document.querySelector('.predzaps-thanks') 8011 8012if (predzapsThanks) predzapsThanksInit() 8013 8014function predzapsThanksInit () { 8015// const isSubjectSort = false 8016 const isSubjectSort = true 8017 const form = predzapsThanks.querySelector('.predzaps-thanks__slide_form') 8018 const tgSlide = predzapsThanks.querySelector('.predzaps-thanks__slide_tg') 8019 const stickyHeader = document.querySelector('.sticky-header') 8020 const body = document.querySelector('body') 8021 const addButton = predzapsThanks.querySelector(".predzaps-thanks__form-add") 8022 const btnSubmit = predzapsThanks.querySelector(".predzaps-thanks__form-submit") 8023 const inners = predzapsThanks.querySelectorAll('.predzaps-thanks__form-line-inner') 8024 const lines = predzapsThanks.querySelector(".predzaps-thanks__form-lines") 8025 const innerCleanCopy = inners[inners.length - 1].cloneNode(true) 8026 let counter = inners.length 8027 8028 function initOpeners (inner) { 8029 const openers = inner.querySelectorAll("[data-element='all-courses-filter-opener']") 8030 for (let i = 0; i < openers.length; i++) { 8031 openers[i].addEventListener("click", (e)=> openFilter(openers[i], e)) 8032 8033 const wrap = openers[i].nextElementSibling 8034 8035 const closeBtn = wrap.querySelector('.all-courses__filter-close') 8036 if (closeBtn) closeBtn.addEventListener('click', () => closeFilter(openers[i])) 8037 8038 const items = wrap.querySelectorAll("[data-element='all-courses-filter-input']") 8039 const subjectSelect = wrap.closest('.predzaps-thanks__form-line-inner')?.querySelector('.all-courses__filter_subject') 8040 items.forEach((item) => { 8041 item.addEventListener('change', function () { 8042 updateFilter(openers[i], wrap) 8043 const isClass = !this.closest('.all-courses__filter-list').parentElement.classList.contains('class_subjects') 8044 if (this.hasAttribute('data-disable-subject') && isClass) { 8045 subjectSelect?.classList.add('all-courses__filter_college') 8046 if (subjectSelect) resetSubjects(subjectSelect, "ÐÑбеÑиÑе напÑавление") 8047 } else if (isClass) { 8048 subjectSelect?.classList.remove('all-courses__filter_college') 8049 if (subjectSelect) resetSubjects(subjectSelect) 8050 } 8051 }) 8052 8053 }) 8054 8055 const confirm = wrap.querySelector('.all-courses__confirm') 8056 if (confirm) confirm.addEventListener('click', () => closeFilter(openers[i])) 8057 } 8058 } 8059 8060 function resetSubjects (subjectSelect, textDefault='ÐÑбеÑиÑе пÑедмеÑ') { 8061 const checkedSubjects = subjectSelect.querySelectorAll('.all-courses__filter-input:checked') 8062 checkedSubjects.forEach((subject) => { 8063 subject.checked = false 8064 }) 8065 const text = subjectSelect.querySelector('.all-courses__filter-top-text') 8066 text.style.color = 'rgba(0,0,0,.62)' 8067 const headline = subjectSelect.querySelector('.all-courses__filter-headline') 8068 text.innerHTML = textDefault 8069 headline.innerHTML = textDefault 8070 } 8071 function subjectsSort (subjectSelect, subjectsList) { 8072 const subjects = subjectSelect.querySelectorAll('.all-courses__filter-input') 8073 subjects.forEach((subject) => { 8074 if (subjectsList.includes(+subject.value)) { 8075 subject.closest('.all-courses__filter-item').style.display = 'block' 8076 } else { 8077 subject.closest('.all-courses__filter-item').style.display = 'none' 8078 } 8079 }) 8080 const line = subjectSelect.closest('.predzaps-thanks__form-line') 8081 const boxes = line.querySelectorAll('.all-courses__filter-box') 8082 let isTabNotSet = false 8083 boxes.forEach((box) => { 8084 const subjects = box.querySelectorAll('.all-courses__filter-input') 8085 let isEmpty = true 8086 subjects.forEach((subject) => { 8087 if (subject.closest('.all-courses__filter-item').style.display === 'block') isEmpty = false 8088 }) 8089 const index = box.getAttribute('data-index') 8090 if (isEmpty && index) { 8091 const tab = line.querySelector(".all-courses__filter-tab[data-index='" + index + "']") 8092 tab.style.display = 'none' 8093 const box = line.querySelector(".all-courses__filter-box[data-index='" + index + "']") 8094 box.classList.add('all-courses__filter-box_hide-sort') 8095 box.previousElementSibling.classList.add('hide') 8096 } else if (index && !isTabNotSet) { 8097 isTabNotSet = true 8098 line.querySelector('.all-courses__filter-tab.active')?.classList.remove('active') 8099 const newTab = line.querySelector(".all-courses__filter-tab[data-index='" + index + "']") 8100 if (newTab) newTab.click() 8101 } 8102 }) 8103 } 8104 8105 function showAllSubjects (subjectSelect) { 8106 const subjects = subjectSelect.querySelectorAll('.all-courses__filter-input')
8107 subjects.forEach((subject) => { 8108 subject.closest('.all-courses__filter-item').style.display = 'block' 8109 }) 8110 const tabs = subjectSelect.querySelectorAll('.all-courses__filter-tab') 8111 tabs[0]?.click() 8112 tabs.forEach((tab) => { 8113 tab.style.display = 'flex' 8114 }) 8115 const line = subjectSelect.closest('.predzaps-thanks__form-line') 8116 const boxes = line.querySelectorAll('.all-courses__filter-box') 8117 const tempBoxes = Array.from(boxes).filter(box => !box.classList.contains('all-courses__filter-box_college')) 8118 tempBoxes.forEach((box, index) => { 8119 box.classList.remove('all-courses__filter-box_hide-sort') 8120 box.previousElementSibling.classList.remove('hide') 8121 }) 8122 } 8123 8124 8125 function removeInputNameError (inner) { 8126 const input = inner.querySelector('.predzaps-thanks__form-input') 8127 input.addEventListener('input', () => input.classList.remove('error-input')) 8128 } 8129 8130 inners.forEach(inner => { 8131 removeInputNameError(inner) 8132 initTabs(inner) 8133 initOpeners(inner) 8134 initDeleteButton(inner) 8135 }) 8136 8137 function initDeleteButton (inner) { 8138 const buttonDelete = inner.querySelector('.predzaps-thanks__form-delete') 8139 buttonDelete.addEventListener('click', () => { 8140 const dataCounter = buttonDelete.getAttribute('data-counter') 8141 inner.remove() 8142 counter -= 1 8143 updateCounter(dataCounter) 8144 if (counter < 7) addButton.disabled = false 8145 }) 8146 } 8147 8148 function updateCounter (dataCounter) { 8149 const inners = document.querySelectorAll('.predzaps-thanks__form-line-inner') 8150 for (let i = dataCounter - 1; i < inners.length; i++) { 8151 const lineName = inners[i].querySelector('.predzaps-thanks__form-line-name') 8152 if (lineName) lineName.innerHTML = `РебÑнок ${i+1}` 8153 const inputName = inners[i].querySelector('.predzaps-thanks__form-input') 8154 if (inputName) inputName.setAttribute('name', `name${i+1}`) 8155 const classInputs = inners[i].querySelectorAll('.all-courses__filter_class input') 8156 classInputs.forEach((input) => { 8157 input.setAttribute('name', `grade${i+1}`) 8158 }) 8159 const subjectInputs = inners[i].querySelectorAll('.all-courses__filter_subject input') 8160 subjectInputs.forEach((input) => { 8161 input.setAttribute('name', `subject${i+1}`) 8162 }) 8163 const deleteButton = inners[i].querySelector('.predzaps-thanks__form-delete') 8164 if (deleteButton) deleteButton.setAttribute('data-counter', i+1) 8165 } 8166 } 8167 8168 8169 function initTabs (inner) { 8170 const filterSubjectWrap = inner.querySelector('.all-courses__filter-wrap_subject') 8171 const list = filterSubjectWrap.querySelector('.all-courses__filter-list') 8172 const tabsParent = filterSubjectWrap.querySelector('.all-courses__filter-tabs') 8173 const tabs = filterSubjectWrap.querySelectorAll('.all-courses__filter-tab') 8174 const subjectsBoxes = filterSubjectWrap.querySelectorAll('.all-courses__filter-box') 8175 8176 if (!tabs.length || !subjectsBoxes.length) return 8177 8178 filterSubjectWrap.addEventListener('scroll', wrapScrollHandler, { passive: true }) 8179 8180 function wrapScrollHandler () { 8181 subjectsBoxes.forEach((subjectBox) => { 8182 if (filterSubjectWrap.scrollTop >= subjectBox.offsetTop - 90 - 65) { 8183 const oldTab = filterSubjectWrap.querySelector('.all-courses__filter-tab.active') 8184 if (oldTab) oldTab.classList.remove('active') 8185 const index = subjectBox.getAttribute('data-index') 8186 const tab = filterSubjectWrap.querySelector('[data-index="' + index + '"]') 8187 if (tab) { 8188 tabsParent.scrollLeft = tab.offsetLeft - tabsParent.clientWidth/2 + tab.clientWidth/2 8189 tab.classList.add('active') 8190 } 8191 } 8192 }) 8193 } 8194
8195 tabs.forEach((tab) => { 8196 tab.addEventListener('click', changeTab) 8197 8198 function changeTab (e) { 8199 e.stopPropagation() 8200 filterSubjectWrap.removeEventListener('scroll', wrapScrollHandler, { passive: true }) 8201 const oldTab = filterSubjectWrap.querySelector('.all-courses__filter-tab.active') 8202 if (oldTab) oldTab.classList.remove('active') 8203 8204 this.classList.add('active') 8205 8206 subjectsBoxes.forEach((subjectsBox) => { 8207 subjectsBox.classList.add('hide') 8208 }) 8209 8210 const index = this.getAttribute('data-index') 8211 const activeSubjectsBox = list.querySelector('[data-index="' + index + '"]') 8212 activeSubjectsBox.classList.remove('hide') 8213 8214 filterSubjectWrap.scrollTop = activeSubjectsBox.offsetTop - 90 - 60 8215 8216 tabsParent.scrollLeft = this.offsetLeft - tabsParent.clientWidth/2 + this.clientWidth/2 8217 setTimeout(() => filterSubjectWrap.addEventListener('scroll', wrapScrollHandler, { passive: true }), 1000) 8218 } 8219 }) 8220 8221 tabs[0].click() 8222 } 8223 8224 function updateFilter(opener, wrap) { 8225 opener.classList.remove('error-input') 8226 if (opener.getAttribute('data-ftype') === 'class_select') { 8227 let subjectsList 8228 try { 8229 subjectsList = JSON.parse(wrap.querySelector('.all-courses__filter-input:checked').getAttribute('data-subjects')) 8230 } catch (e) { 8231 console.log(e) 8232 } 8233 const subjectSelect = wrap.closest('.predzaps-thanks__form-line-inner')?.querySelector('.all-courses__filter_subject') 8234 showAllSubjects(subjectSelect) 8235 subjectSelect.classList.remove('all-courses__filter_disabled') 8236 if (subjectsList && subjectSelect && isSubjectSort) subjectsSort(subjectSelect, subjectsList) 8237 const text = opener.querySelector('.all-courses__filter-top-text') 8238 text.style.color = '#000' 8239 text.innerHTML = wrap.querySelector('.all-courses__filter-input:checked').nextElementSibling.textContent 8240 closeFilter(opener, wrap) 8241 } 8242 if (opener.getAttribute('data-ftype') === 'class_subjects') { 8243 const isCollege = opener.closest('.all-courses__filter').classList.contains('all-courses__filter_college') 8244 const headline = wrap.querySelector('.all-courses__filter-headline') 8245 const text = opener.querySelector('.all-courses__filter-top-text') 8246 text.style.color = '#000' 8247 if (!isCollege) { 8248 headline.innerHTML = `ÐÑбÑано пÑедмеÑов: ${wrap.querySelectorAll('.all-courses__filter-input:checked').length}` 8249 text.innerHTML = `ÐÑбÑано пÑедмеÑов: ${wrap.querySelectorAll('.all-courses__filter-input:checked').length}` 8250 } else { 8251 text.innerHTML = wrap.querySelector('.all-courses__filter-input:checked').getAttribute('data-text') 8252 closeFilter(opener, wrap) 8253 } 8254 } 8255 } 8256 8257 function openFilter (opener, e) { 8258 e.stopPropagation() 8259 if (opener.classList.contains('active')) { 8260 closeFilter(opener) 8261 } else { 8262 const oldOpen = predzapsThanks.querySelector(".all-courses__filter-top.active") 8263 if (oldOpen) oldOpen.classList.remove('active') 8264 opener.classList.add('active') 8265 8266 const filter = opener.parentElement 8267 const oldFilter = predzapsThanks.querySelector(".all-courses__filter.open") 8268 if (oldFilter) oldFilter.classList.remove('open') 8269 if (filter) filter.classList.add('open') 8270 } 8271 hideHeader() 8272 } 8273 8274 function closeFilter (opener) { 8275 opener.classList.remove('active') 8276 const filter = opener.parentElement 8277 if (filter) filter.classList.remove('open') 8278 showHeader() 8279 } 8280 8281 function showHeader () { 8282 stickyHeader.classList.remove('hide') 8283 body.classList.remove('no-scroll') 8284 } 8285 function hideHeader () { 8286 if (window.innerWidth < 744) { 8287 stickyHeader.classList.add('hide') 8288 body.classList.add('no-scroll') 8289 } 8290 } 8291 8292 8293 8294 form.addEventListener('submit', submitForm) 8295 8296 function createSendData () { 8297 const names = [] 8298 const nameInputs = form.querySelectorAll('.predzaps-thanks__form-input') 8299 nameInputs.forEach(nameInput => { 8300 names.push(nameInput.value) 8301 }) 8302 const classes = [] 8303 const classes_ids = [] 8304 const classInputs = form.querySelectorAll('.all-courses__filter_class input:checked')
8305 classInputs.forEach(classInput => { 8306 classes.push(classInput.dataset.text) 8307 classes_ids.push(classInput.value) 8308 }) 8309 const subjects = [] 8310 const subjects_ids = [] 8311 const inners = form.querySelectorAll('.predzaps-thanks__form-line-inner') 8312 8313 inners.forEach(inner => { 8314 const temp = [] 8315 const temp_ids = [] 8316 const subjectsOneChild = inner.querySelectorAll('.all-courses__filter_subject input:checked') 8317 subjectsOneChild.forEach(subject => { 8318 temp.push(subject.dataset.text) 8319 temp_ids.push(subject.value) 8320 }) 8321 subjects.push(temp) 8322 subjects_ids.push(temp_ids) 8323 }) 8324 8325 const summer_answers = [] 8326 const checkboxes = form.querySelectorAll('.predzaps-thanks__summer-input') 8327 checkboxes.forEach(checkbox => { 8328 summer_answers.push(checkbox.checked ? 'да' : 'неÑ') 8329 }) 8330 8331 const formData = new FormData(form); 8332 const formObject = {}; 8333 const childrenFieldNames = new Set(); 8334 8335 nameInputs.forEach(input => childrenFieldNames.add(input.name)); 8336 classInputs.forEach(input => childrenFieldNames.add(input.name)); 8337 inners.forEach(inner => { 8338 inner.querySelectorAll('.all-courses__filter_subject input').forEach(input => { 8339 childrenFieldNames.add(input.name); 8340 }); 8341 }); 8342 8343 formData.forEach((value, key) => { 8344 if (!childrenFieldNames.has(key)) { 8345 if (key in formObject) { 8346 if (Array.isArray(formObject[key])) { 8347 formObject[key].push(value); 8348 } else { 8349 formObject[key] = [formObject[key], value]; 8350 } 8351 } else { 8352 formObject[key] = value; 8353 } 8354 } 8355 }); 8356 const children = []; 8357 const children_ids = []; 8358 const maxLen = Math.max(names.length, classes.length, subjects.length, summer_answers.length); 8359 8360 for (let i = 0; i < maxLen; i++) { 8361 children.push({ 8362 name: names[i] ?? null, 8363 class: classes[i] ?? null, 8364 subjects: subjects[i] ?? [], 8365 summer_answer: summer_answers[i] ?? null, 8366 }); 8367 children_ids.push({ 8368 name: names[i] ?? null, 8369 class: classes_ids[i] ?? null, 8370 subjects: subjects_ids[i] ?? [], 8371 summer_answer: summer_answers[i] ?? null, 8372 }); 8373 } 8374 8375 formObject.children = children; 8376 formObject.children_ids = children_ids; 8377 8378 return formObject; 8379 } 8380 8381 function submitForm (e) { 8382 e.preventDefault() 8383 e.stopPropagation() 8384 if (validate()) { 8385 btnSubmit.disabled = true 8386 btnSubmit.classList.add('loading') 8387 const data = createSendData() 8388 console.log(data) 8389 const dataRequest = form.getAttribute('data-request'); 8390 $.request('MainFunctions::' + dataRequest, { 8391 data: data, 8392 success: function(response) { 8393 // console.log('ÐÑвеÑ:', response); 8394 let hasErrors = false; 8395 8396 for (let key in response) { 8397 if (key.startsWith('.')) { 8398 const className = key.substring(1); 8399 const element = document.querySelector('.' + className); 8400 8401 if (element) { 8402 element.innerHTML = response[key]; 8403 hasErrors = true; 8404 btnSubmit.disabled = false 8405 btnSubmit.classList.remove('loading') 8406 } 8407 } 8408 } 8409 8410 8411 8412 if (hasErrors) { 8413 // isSubmitting = false; 8414 return; 8415 } 8416 removeParameterFromUrl('cemail') 8417 form.classList.remove('active') 8418 tgSlide.classList.add('active') 8419 window.scrollTo({ top: 0, left: 0, behavior: 'smooth' }); 8420 }, 8421 error: function (error) { 8422 // console.error('â ÐÑибка оÑпÑавки:', error); 8423 } 8424 }); 8425 } 8426 } 8427 8428 function removeParameterFromUrl (keyToRemove) { 8429 const url = new URL(window.location.href) 8430 const params = url.searchParams 8431 params.delete(keyToRemove) 8432 window.history.replaceState({}, document.title, url.toString()) 8433 } 8434 8435 8436 addButton.addEventListener('click', addLine) 8437 8438 function addLine () { 8439 if (validate()) { 8440 counter += 1 8441 lines.append(innerCleanCopy.cloneNode(true)) 8442 const inners = predzapsThanks.querySelectorAll('.predzaps-thanks__form-line-inner') 8443 const inner = inners[inners.length - 1] 8444 removeInputNameError(inner) 8445 updateNames(inner) 8446 initTabs(inner) 8447 initOpeners(inner) 8448 initDeleteButton(inner) 8449 if (window.innerHeight - inner.getBoundingClientRect().bottom < 0) { 8450 inner.scrollIntoView({ 8451 behavior: 'smooth', 8452 block: 'end' 8453 }) 8454 } 8455 if (counter >= 7) addButton.disabled = true 8456 } 8457 } 8458 8459 function updateNames (inner) { 8460 const lineName = inner.querySelector('.predzaps-thanks__form-line-name') 8461 lineName.innerHTML = `Ребенок ${counter}` 8462 const inputs = inner.querySelectorAll('input') 8463 for (let i = 0; i < inputs.length; i++) { 8464 inputs[i].name = `${inputs[i].name}${counter}` 8465 } 8466 const deleteButton = inner.querySelector('.predzaps-thanks__form-delete') 8467 if (deleteButton) deleteButton.setAttribute('data-counter', counter) 8468 } 8469 8470 function validate () { 8471 const inners = predzapsThanks.querySelectorAll('.predzaps-thanks__form-line-inner') 8472 for (let i = 0; i < inners.length; i++) { 8473 const isValid = checkInputs(inners[i]) 8474 if (!isValid) return false 8475 } 8476 function checkInputs(inner) { 8477 const nameInput = inner.querySelector(".predzaps-thanks__form-input") 8478 if (!nameInput.value) { 8479 nameInput.classList.add('error-input') 8480 return false 8481 } 8482 const classInput = inner.querySelector(".all-courses__filter_class input:checked") 8483 if (!classInput) { 8484 const top = inner.querySelector(".all-courses__filter_class .all-courses__filter-top") 8485 top.classList.add('error-input') 8486 return false 8487 } 8488 const isCollege = inner.querySelector('.all-courses__filter_subject.all-courses__filter_disabled') 8489 if (!isCollege) { 8490 const subjectInput = inner.querySelector(".all-courses__filter_subject input
8490:checked") 8491 if (!subjectInput) { 8492 const top = inner.querySelector(".all-courses__filter_subject .all-courses__filter-top") 8493 top.classList.add('error-input') 8494 return false 8495 } 8496 } 8497 return true 8498 } 8499 return true 8500 } 8501} 8502 8503 8504 8505const teacherCostArray = document.querySelectorAll('.teacher-cost .cost__area') 8506 8507if (teacherCostArray.length) teacherCostArrayInit() 8508 8509 function teacherCostArrayInit () { 8510 for (let i = 0; i < teacherCostArray.length; i++) { 8511 teacherCostInit(teacherCostArray[i]) 8512 } 8513 } 8514 8515 function teacherCostInit(node) { 8516 const btn = node.querySelector('.cost__button') 8517 const checkbox = node.querySelector('.cost__teacher-checkbox') 8518 const price = node.querySelector('.cost__price-current') 8519 8520 8521 checkbox.addEventListener('change', checkboxChangeHandler) 8522 8523 function checkboxChangeHandler () { 8524 const newPrice = checkbox.getAttribute('new-price') 8525 const oldPrice = btn.getAttribute('old-price') 8526 8527 const newHref = checkbox.getAttribute('new-href') 8528 const oldHref = btn.getAttribute('old-href') 8529 8530 if (checkbox.checked) { 8531 price.textContent = newPrice 8532 btn.href = newHref 8533 } else { 8534 price.textContent = oldPrice 8535 btn.href = oldHref 8536 } 8537 } 8538 } 8539 8540 const profStockAboutShow = document.querySelector('.prof-stock-about__show') 8541 8542if (profStockAboutShow) profStockAboutShow.addEventListener('click', 8543 () => profStockAboutShow.classList.toggle('active') 8544) 8545 8546const profStockTimers = document.querySelectorAll('[data-element="prof-stock-timer"]') 8547 8548if (profStockTimers.length > 0) { 8549 if (getCookie('prof_stock_expired') !== 'true') { 8550 profStockTimers.forEach(timer => { 8551 timer.classList.add('active') 8552 }) 8553 if (getCookie('prof_stock_shown') !== 'true') { 8554 const date = new Date() 8555 date.setHours(date.getHours() + 24) 8556 document.cookie = `user_prof_stock_date_end=${date.toISOString().replace(/T(\d)(?=:)/, 'T0$1')}; max-age=31536000;`; 8557 } 8558 document.cookie = `prof_stock_shown=true; max-age=31536000;`; 8559 profStockTimers.forEach(timer => { 8560 initProfStockTimer(timer) 8561 }) 8562 } 8563} 8564 8565function initProfStockTimer (timer) { 8566 let date = new Date(getCookie('user_prof_stock_date_end')) 8567 if (!(date instanceof Date && !isNaN(date.getTime()))) { 8568 date = new Date() 8569 date.setHours(date.getHours() + 24) 8570 } 8571 const countDownDate = date.getTime() 8572 8573 const nodes = timer.querySelectorAll('[data-element="prof-stock-timer-number"]') 8574 8575 const interval = setInterval(updateTimer, 1000) 8576 8577 function updateTimer () { 8578 const now = new Date().getTime(); 8579 const distance = countDownDate - now; 8580 8581 const days = Math.floor(distance / (1000 * 60 * 60 * 24)) 8582 const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)) 8583 const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)) 8584 const seconds = Math.floor((distance % (1000 * 60)) / 1000) 8585 8586 if (nodes.length < 4) { 8587 nodes[0].innerHTML = String(hours).padStart(2, '0') 8588 nodes[1].innerHTML = String(minutes).padStart(2, '0') 8589 nodes[2].innerHTML = String(seconds).padStart(2, '0') 8590 } else { 8591 nodes[0].innerHTML = days 8592 nodes[1].innerHTML = hours 8593 nodes[2].innerHTML = minutes 8594 nodes[3].innerHTML = seconds 8595 } 8596 // console.log(distance) 8597 if (distance < 0) { 8598 clearInterval(interval); 8599 nodes[0].innerHTML = "0" 8600 nodes[1].innerHTML = "0" 8601 nodes[2].innerHTML = "0" 8602 document.cookie = `prof_stock_expired=true; max-age=31536000;` 8603 profStockTimers.forEach(timer => { 8604 timer.classList.remove('active') 8605 }) 8606 if (nodes[3]) nodes[3].innerHTML = "0" 8607 } 8608 } 8609} 8610 8611 const profStockBar = document.querySelector('.prof-stock-bar') 8612 8613 if (profStockBar) profStockBarInit() 8614 8615 function profStockBarInit () { 8616 const cake = document.querySelector('.cake') 8617 if (cake) cake.classList.add('cake_prof-stock-bar') 8618 8619 const order = document.querySelector('.prof-stock-order'); 8620 const footer = document.querySelector('.footer-quiz'); 8621 8622 const observer = new IntersectionObserver((entries) => {
8623 entries.forEach(entry => { 8624 if (entry.isIntersecting) { 8625 profStockBar.style.display = 'none' 8626 if (cake) cake.classList.remove('cake_prof-stock-bar') 8627 } else { 8628 profStockBar.style.display = 'block' 8629 if (cake) cake.classList.add('cake_prof-stock-bar') 8630 } 8631 }) 8632 }, { 8633 threshold: 0 8634 }) 8635 8636 if (order) observer.observe(order) 8637 if (footer) observer.observe(footer) 8638 } 8639 8640 8641 const programBoxes = document.querySelectorAll('.program__box') 8642 8643 if (programBoxes.length) programBoxesInit() 8644 8645 function programBoxesInit () { 8646 for (let i = 0; i < programBoxes.length; i++) { 8647 programBoxInit(programBoxes[i]) 8648 } 8649 8650 function programBoxInit (box) { 8651 const items = box.querySelectorAll('.program__item') 8652 let span 8653 8654 if (window.innerWidth >= 1440 && items.length > 12 || window.innerWidth >= 744 && items.length > 10 || window.innerWidth < 744 && items.length > 6) { 8655 box.classList.add('hide') 8656 const btn = box.querySelector('.program__more') 8657 btn.addEventListener('click', toogleBox) 8658 span = btn.querySelector('span') 8659 } 8660 8661 function toogleBox () { 8662 if (box.classList.contains('active')) { 8663 box.classList.remove('active') 8664 span.innerHTML = 'ÐоказаÑÑ Ð¿Ð¾Ð»Ð½Ð¾ÑÑÑÑ' 8665 box.scrollIntoView() 8666 } else { 8667 box.classList.add('active') 8668 span.innerHTML = 'СкÑÑÑÑ ÑпиÑок' 8669 } 8670 } 8671 } 8672 } 8673 8674 8675const promo = document.querySelector('.promo') 8676 8677 if (promo) promoInit() 8678 8679 function promoInit () { 8680 const closeBtn = promo.querySelector('.promo__close') 8681 const promoView = promo.querySelector('.promo__view') 8682 const cake = document.querySelector('.cake.cake_active') 8683 const footer = document.querySelector('footer') 8684 8685 promoView.addEventListener('click', switchPromo) 8686 closeBtn.addEventListener('click', closePromo) 8687 8688 if (footer) window.addEventListener('scroll', togglePromo, { passive: true }) 8689 window.addEventListener('click', closePromo) 8690 8691 function switchPromo (e) { 8692 e.stopPropagation() 8693 promo.classList.toggle('active') 8694 } 8695 8696 function closePromo () { 8697 promo.classList.remove('active') 8698 } 8699 8700 function togglePromo () { 8701 const scrollHeight = document.documentElement.scrollHeight 8702 const currentScroll = window.scrollY 8703 const clientHeight = document.documentElement.clientHeight 8704 8705 const distanceToBottom = scrollHeight - (currentScroll + clientHeight); 8706 if (distanceToBottom < footer.clientHeight) { 8707 promo.classList.add('hide') 8708 } else { 8709 promo.classList.remove('hide') 8710 } 8711 } 8712 8713 8714 if (cake) promo.classList.add('transition-with-cake') 8715 } 8716 8717const quizNew = document.querySelector('[data-element="quiz-new"]') 8718 8719if (quizNew) quizSoInit() 8720 8721function quizSoInit () { 8722 let index = 0 8723 const slides = quizNew.querySelectorAll('[data-element="quiz-so-slide"]') 8724 const buttonsNext = quizNew.querySelectorAll('[data-element="quiz-so-slide-next"]') 8725 const buttonsBack = quizNew.querySelectorAll('[data-element="quiz-so-slide-back"]') 8726 const btnSubmit = quizNew.querySelector('.btn-warning') 8727 const input = quizNew.querySelector("[data-element='input-phone-intl']") 8728 const inputName = quizNew.querySelector(".quiz-so-slide__form-input_name") 8729 const inputHidden = quizNew.querySelector("[data-element='input-phone-hidden']") 8730// const inputsAll = quizNew.querySelectorAll('input'); 8731 const policyCheckboxes = quizNew.querySelectorAll('.quiz-so-slide__checkbox-input') 8732 const linkTo = quizNew.getAttribute("data-docex") 8733 const utm_input = quizNew.querySelector('[name="utm"]') 8734 const inputsRadio = quizNew.querySelectorAll('.quiz-so-slide__input[type="radio"]') 8735 8736 buttonsNext.forEach(button => { 8737 button.addEventListener('click', nextSlide) 8738 }) 8739 8740 window.addEventListener('resize', () => { 8741 quizNew.style.height = `${slides[index].clientHeight}px` 8742 }, { passive: true }) 8743 8744 function nextSlide () { 8745 if (slides[index].querySelector('.quiz-so-slide__input') && !slides[index].querySelector('.quiz-so-slide__input
8745:checked')) { 8746 const inputs = slides[index].querySelectorAll('.quiz-so-slide__input') 8747 inputs.forEach(input => { 8748 input.classList.add('error') 8749 input.addEventListener('change', resetError, { once: true }) 8750 }) 8751 function resetError () { 8752 inputs.forEach(input => { 8753 input.classList.remove('error') 8754 }) 8755 } 8756 } else if (index === slides.length - 1) { 8757 8758 } else { 8759 slides[index].classList.remove('active') 8760 index += 1 8761 slides[index].classList.add('active') 8762 quizNew.style.height = `${slides[index].clientHeight}px` 8763 } 8764 } 8765 8766 policyCheckboxes.forEach(policyCheckbox => { 8767 policyCheckbox.addEventListener('change', () => { 8768 policyCheckbox.parentNode.classList.remove('error') 8769 }) 8770 }) 8771 8772 if (inputName) inputName.addEventListener('input', () => { 8773 inputName.classList.remove('error') 8774 }) 8775 8776 buttonsBack.forEach(button => { 8777 button.addEventListener('click', prevSlide) 8778 }) 8779 8780 function prevSlide () { 8781 if (index === 0) return 8782 slides[index].classList.remove('active') 8783 index -= 1 8784 slides[index].classList.add('active') 8785 quizNew.style.height = `${slides[index].clientHeight}px` 8786 } 8787 8788 initLoaders() 8789 8790 function initLoaders () { 8791 slides.forEach((slide, index) => { 8792 const quizSoSlideLoaderFill = slide.querySelector('.quiz-so-slide__loader-fill') 8793 if (quizSoSlideLoaderFill) quizSoSlideLoaderFill.style.width = `${100 * index / slides.length}%` 8794 const quizSoSlideLoaderMobValue = slide.querySelector('.quiz-so-slide__loader-mob-value') 8795 if (quizSoSlideLoaderMobValue) quizSoSlideLoaderMobValue.innerHTML = Math.round(`${100 * index / slides.length}`) + '%' 8796 const quizSoSlideLoaderMobProgress = slide.querySelector('.quiz-so-slide__loader-mob-progress') 8797 if (quizSoSlideLoaderMobProgress) quizSoSlideLoaderMobProgress.style.strokeDashoffset = 250 - (140 * `${index / slides.length}`) 8798 }) 8799 } 8800 8801 if (input && inputHidden) { 8802 iti = window.intlTelInput(input, { 8803 utilsScript: "../libs/intlTelInputWithUtils.min", 8804 initialCountry: 'ru', 8805 separateDialCode: true, 8806 strictMode: true 8807 }) 8808 8809 input.addEventListener('input', function () { 8810 input.classList.remove('error') 8811 let tempValue = input.value 8812 inputHidden.value = input.value 8813 const cleanNumber = tempValue.replace(/[^+\d]/g, '') 8814 if (iti.selectedCountryData.dialCode === "7" && cleanNumber.length > 10) { 8815 inputHidden.value = cleanNumber.substring(cleanNumber.length - 10) 8816 } 8817 inputHidden.value = iti.selectedCountryData.dialCode + ' ' + inputHidden.value 8818 }) 8819 } 8820 quizNew.addEventListener('submit', async (e) => { 8821 e.preventDefault() 8822 let isValid = true 8823 if (input && !input?.value?.trim() || !iti?.isValidNumber()) { 8824 input.classList.add("error") 8825 isValid = false 8826 } 8827 if (!inputName.value) { 8828 inputName.classList.add("error") 8829 isValid = false 8830 } 8831 if (!policyCheckboxes[0].checked) { 8832 policyCheckboxes[0].parentNode.classList.add("error") 8833 isValid = false 8834 } 8835 if (!policyCheckboxes[1].checked) { 8836 policyCheckboxes[1].parentNode.classList.add("error") 8837 isValid = false 8838 } 8839 8840 if (!isValid) { 8841 return false; 8842 } 8843 let linkTo_ = linkTo; 8844 if (utm_input) { 8845 utm_f = utm_input.value; 8846 if(utm_f != null && utm_f != '' && utm_f != undefined){ 8847 }else{ 8848 utm_f = '' 8849 } 8850 if (utm_f.length > 0) { 8851 linkTo_ = linkTo_ + utm_f; 8852 } 8853 } 8854 btnSubmit.disabled = true; 8855 //quizNew.submit() 8856 // var obData = {}; 8857 // const whitelist = [ 8858 // 'tel', 8859 // 'name', 8860 // 'policy', 8861 // 'news', 8862 // 'page_name', 8863 // 'utm', 8864 // 'class', 8865 // 'current-education-plan', 8866 // 'has-troubles', 8867 // 'school-position', 8868 // 'family-education-plan', 8869 // 'study-format', 8870 // 'need-help', 8871 // 'pay-format']; 8872 8873 // inputsAll.forEach(input => { 8874 // if (input.name && whitelist.includes(input.name)) { 8875 // if (input.type === 'radio') { 8876 // if (input.checked) { 8877 // obData[input.name] = input.value; 8878 // } 8879 // }else { 8880 // obData[input.name] = input.value; 8881 // } 8882 // } 8883 // }); 8884 8885 // $.request('MainFunctions::onSendQuizSo', { 8886 // data: obData, 8887 // // success: function(data) { 8888 // // console.log(linkTo) 8889 // // //location.assign(linkTo) 8890 // // }, 8891 // }) 8892 8893 setTimeout(() => { 8894 location.assign(linkTo_) 8895 }, 100) 8896 8897 }) 8898
8899 slides.forEach(slide => { 8900 const hidden = slide.querySelector('.quiz-so-slide__hidden-checkbox') 8901 if (!hidden) return 8902 const inputs = slide.querySelectorAll('.quiz-so-slide__input') 8903 for (let i = 0; i < inputs.length; i++) { 8904 inputs[i].addEventListener('input', function () { 8905 if (inputs[i].hasAttribute('data-single-check')) { 8906 const checked = slide.querySelectorAll("input:checked") 8907 for (let j = 0; j < checked.length; j++) { 8908 checked[j].checked = false 8909 } 8910 inputs[i].checked = true 8911 hidden.value = inputs[i].value 8912 } else { 8913 const inputSingleCheck = slide.querySelector("[data-single-check]") 8914 if (inputSingleCheck) inputSingleCheck.checked = false 8915 const checked = slide.querySelectorAll("input:checked") 8916 let temp = '' 8917 for (let j = 0; j < checked.length; j++) { 8918 temp += checked[j].value 8919 if (j !== checked.length - 1) temp += ', ' 8920 } 8921 hidden.value = temp 8922 } 8923 }) 8924 } 8925 }) 8926 inputsRadio.forEach(input => { 8927 const link = input.getAttribute('data-redirect-quiz') 8928 if (link) { 8929 input.addEventListener('click', function () { 8930 let link_tr = link; 8931 if (utm_input) { 8932 utm_paramsToInsert = utm_input.value 8933 if(utm_paramsToInsert != null && utm_paramsToInsert != '' && utm_paramsToInsert != undefined){ 8934 }else{ 8935 utm_paramsToInsert = '' 8936 } 8937 if (utm_paramsToInsert.length > 0) { 8938 const link_parts = link_tr.split('#') 8939 if (link_parts.length === 1) { 8940 link_tr += utm_paramsToInsert 8941 }else{ 8942 link_tr = `${link_parts[0]}${utm_paramsToInsert}#${link_parts[1]}`; 8943 } 8944 } 8945 } 8946 8947 location.replace(link_tr) 8948 }) 8949 } else { 8950 input.addEventListener('change', nextSlide) 8951 } 8952 }) 8953} 8954 8955 8956const quiz = document.querySelector('[data-element="quiz"]') 8957 8958if (quiz) quizInit() 8959 8960function quizInit () { 8961 const generateData = { 8962 list_4: [ 8963 ['ÐаÑемаÑика','Ð ÑÑÑкий ÑзÑк','ÐиÑеÑаÑÑÑное ÑÑение','ÐнглийÑкий ÑзÑк','Ðе планиÑÑÑ'], 8964 ['ÐаÑемаÑика','Ð ÑÑÑкий ÑзÑк','ÐкÑÑжаÑÑий миÑ','ÐиÑеÑаÑÑÑное ÑÑение','ÐнглийÑкий ÑзÑк','ÐÑзÑка','ФизиÑеÑÐºÐ°Ñ ÐºÑлÑÑÑÑа','ÐÐРи ÑÐµÑ Ð½Ð¾Ð»Ð¾Ð³Ð¸Ñ','Ðе планиÑÑÑ'], 8965 ['ÐаÑемаÑика','Ð ÑÑÑкий ÑзÑк','ÐкÑÑжаÑÑий миÑ','ÐиÑеÑаÑÑÑное ÑÑение','ÐнглийÑкий ÑзÑк','ÐÑзÑка','ФизиÑеÑÐºÐ°Ñ ÐºÑлÑÑÑÑа','ÐÐРи ÑÐµÑ Ð½Ð¾Ð»Ð¾Ð³Ð¸Ñ','Ðе планиÑÑÑ'], 8966 ['ÐаÑемаÑика','Ð ÑÑÑкий ÑзÑк','ÐкÑÑжаÑÑий миÑ','ÐиÑеÑаÑÑÑное ÑÑение','ÐнглийÑкий ÑзÑк','ÐÑзÑка','ФизиÑеÑÐºÐ°Ñ ÐºÑлÑÑÑÑа','ÐÐРи ÑÐµÑ Ð½Ð¾Ð»Ð¾Ð³Ð¸Ñ','Ðе планиÑÑÑ'], 8967 ['ÐаÑемаÑика','Ð ÑÑÑкий ÑзÑк','ÐкÑÑжаÑÑий миÑ','ÐиÑеÑаÑÑÑное ÑÑение','ÐнглийÑкий ÑзÑк','ÐÑзÑка','ФизиÑеÑÐºÐ°Ñ ÐºÑлÑÑÑÑа','ÐÐРи ÑÐµÑ Ð½Ð¾Ð»Ð¾Ð³Ð¸Ñ','Ðе планиÑÑÑ'], 8968 ['ÐаÑемаÑика','Ð ÑÑÑкий ÑзÑк','ÐиÑеÑаÑÑÑа','ÐиологиÑ','ÐÑÑоÑиÑ','ÐеогÑаÑиÑ','ÐнглийÑкий ÑзÑк','ÐÑзÑка','ФизиÑеÑÐºÐ°Ñ ÐºÑлÑÑÑÑа','ÐÐРи ÑÐµÑ Ð½Ð¾Ð»Ð¾Ð³Ð¸Ñ','Ðе планиÑÑÑ'], 8969 ['ÐаÑемаÑика','Ð ÑÑÑкий ÑзÑк','ÐиÑеÑаÑÑÑа','ÐиологиÑ','ÐÑÑоÑиÑ','ÐеогÑаÑиÑ','ÐнглийÑкий ÑзÑк','ÐÑзÑка','ФизиÑеÑÐºÐ°Ñ ÐºÑлÑÑÑÑа','ÐÐРи ÑÐµÑ Ð½Ð¾Ð»Ð¾Ð³Ð¸Ñ','ÐбÑеÑÑвознание','Ðе планиÑÑÑ'], 8970 ['ÐаÑемаÑика','Ð ÑÑÑкий ÑзÑк','ÐиÑеÑаÑÑÑа','ÐиологиÑ','ÐÑÑоÑиÑ','ÐеогÑаÑиÑ','ÐнглийÑкий ÑзÑк','ÐÑзÑка', 8971 'ФизиÑеÑÐºÐ°Ñ ÐºÑлÑÑÑÑа','ÐÐРи ÑÐµÑ Ð½Ð¾Ð»Ð¾Ð³Ð¸Ñ','ÐбÑеÑÑвознание','Физика','ХимиÑ','ÐнÑоÑмаÑика','Ðе планиÑÑÑ'], 8972 ['ÐаÑемаÑика','Ð ÑÑÑкий ÑзÑк','ÐиÑеÑаÑÑÑа','ÐиологиÑ','ÐÑÑоÑиÑ','ÐеогÑаÑиÑ','ÐнглийÑкий ÑзÑк','ÐÑзÑка', 8973 'ФизиÑеÑÐºÐ°Ñ ÐºÑлÑÑÑÑа','ÐÐРи ÑÐµÑ Ð½Ð¾Ð»Ð¾Ð³Ð¸Ñ','ÐбÑеÑÑвознание','Физика','ХимиÑ','ÐнÑоÑмаÑика','Ðе планиÑÑÑ'], 8974 ['Ð ÑÑÑкий ÑзÑк','ÐиÑеÑаÑÑÑа','ÐнглийÑкий ÑзÑк','ÐаÑемаÑика','ÐнÑоÑмаÑика','Физика','ÐбÑеÑÑво','ÐÑÑоÑиÑ','ÐеогÑаÑиÑ', 8975 'ÐиологиÑ','ХимиÑ','ФизиÑеÑÐºÐ°Ñ ÐºÑлÑÑÑÑа','Ð¢ÐµÑ Ð½Ð¾Ð»Ð¾Ð³Ð¸Ñ','ÐÐÐÐ ','Ðе планиÑÑÑ'], 8976 ['Ð ÑÑÑкий ÑзÑк','ÐиÑеÑаÑÑÑа','ÐнглийÑкий ÑзÑк','ÐаÑемаÑика','ÐнÑоÑмаÑика','Физика','ÐбÑеÑÑво','ÐÑÑоÑиÑ','ÐеогÑаÑиÑ', 8977 'ÐиологиÑ','ХимиÑ','ФизиÑеÑÐºÐ°Ñ ÐºÑлÑÑÑÑа','ÐÐÐÐ ','Ðе планиÑÑÑ'], 8978 ['Ð ÑÑÑкий ÑзÑк','ÐиÑеÑаÑÑÑа','ÐнглийÑкий ÑзÑк','ÐаÑемаÑика','ÐнÑоÑмаÑика','Физика','ÐбÑеÑÑво','ÐÑÑоÑиÑ','ÐеогÑаÑиÑ', 8979 'ÐиологиÑ','ХимиÑ','ФизиÑеÑÐºÐ°Ñ ÐºÑлÑÑÑÑа','ÐÐÐÐ ','Ðе планиÑÑÑ'], 8980 ], 8981 list_5: [ 8982 [], 8983 ['ÐиÑайÑкий ÑзÑк','ФÑанÑÑзÑкий ÑзÑк','ÐомпÑÑÑеÑÐ½Ð°Ñ Ð³ÑамоÑноÑÑÑ','ÐÑогÑаммиÑование в Minecraft','ÐÑогÑаммиÑование в Scratch', 8984 'Ð¨Ð°Ñ Ð¼Ð°ÑÑ','Ðлогинг','ÐÑпанÑкий ÑзÑк','ÐемеÑкий ÑзÑк','ÐлимпиаднÑй ÑÑÑÑкий ÑзÑк','Ðе планиÑÑÑ'], 8985 ['ÐиÑайÑкий ÑзÑк','ФÑанÑÑзÑкий ÑзÑк','ÐаÑемаÑика и логика. ÐеÑвÑе Ñаги в Ð¾Ð»Ð¸Ð¼Ð¿Ð¸Ð°Ð´Ð°Ñ ','ÐомпÑÑÑеÑÐ½Ð°Ñ Ð³ÑамоÑноÑÑÑ', 8986 'ÐÑогÑаммиÑование в Minecraft','ÐÑогÑаммиÑование в Scratch','Ð¨Ð°Ñ Ð¼Ð°ÑÑ','Ðлогинг','ÐÑпанÑкий ÑзÑк','ÐемеÑкий ÑзÑк', 8987 'ÐлимпиаднÑй ÑÑÑÑкий ÑзÑк','Ðе планиÑÑÑ'], 8988 ['ÐиÑайÑкий ÑзÑк','ФÑанÑÑзÑкий ÑзÑк','ÐаÑемаÑика и логика. ÐеÑвÑе Ñаги в Ð¾Ð»Ð¸Ð¼Ð¿Ð¸Ð°Ð´Ð°Ñ ','ÐомпÑÑÑеÑÐ½Ð°Ñ Ð³ÑамоÑноÑÑÑ', 8989 'ÐÑогÑаммиÑование в Minecraft','ÐÑогÑаммиÑование в Scratch','ÐÑÑÑ Ð¿Ð¾ ÑазÑабоÑке Ð¸Ð³Ñ Ð² Roblox','ÐÑаÑоÑÑкое маÑÑеÑÑÑво', 8990 'ФинанÑÐ¾Ð²Ð°Ñ Ð³ÑамоÑноÑÑÑ','ÐмоÑионалÑнÑй инÑеллекÑ','Ð¨Ð°Ñ Ð¼Ð°ÑÑ','Ðлогинг','ÐÑпанÑкий ÑзÑк','ÐемеÑкий ÑзÑк', 8991 'ÐлимпиаднÑй ÑÑÑÑкий ÑзÑк','Ðе планиÑÑÑ'], 8992 ['ÐиÑайÑкий ÑзÑк','ФÑанÑÑзÑкий ÑзÑк','ÐаÑемаÑика и логика. ÐеÑвÑе Ñаги в Ð¾Ð»Ð¸Ð¼Ð¿Ð¸Ð°Ð´Ð°Ñ ','ÐомпÑÑÑеÑÐ½Ð°Ñ Ð³ÑамоÑноÑÑÑ', 8993 'ÐÑогÑаммиÑование в Minecraft','ÐÑогÑаммиÑование в Scratch','ÐÑÑÑ Ð¿Ð¾ ÑазÑабоÑке Ð¸Ð³Ñ Ð² Roblox','ÐÑаÑоÑÑкое маÑÑеÑÑÑво', 8994 'ФинанÑÐ¾Ð²Ð°Ñ Ð³ÑамоÑноÑÑÑ','ÐмоÑионалÑнÑй инÑеллекÑ','Ð¨Ð°Ñ Ð¼Ð°ÑÑ','Ðлогинг','ÐÑпанÑкий ÑзÑк','ÐемеÑкий ÑзÑк', 8995 'ÐлимпиаднÑй ÑÑÑÑкий ÑзÑк','Ðе планиÑÑÑ'], 8996 ['ÐиÑайÑкий ÑзÑк','ФÑанÑÑзÑкий ÑзÑк','ÐаÑемаÑика и логика. ÐеÑвÑе Ñаги в Ð¾Ð»Ð¸Ð¼Ð¿Ð¸Ð°Ð´Ð°Ñ ','ÐÑогÑаммиÑование на Python', 8997 'Создание ÑайÑов','ÐомпÑÑÑеÑÐ½Ð°Ñ Ð³ÑамоÑноÑÑÑ','ÐÑогÑаммиÑование в Minecraft','ÐÑогÑаммиÑование в Scratch', 8998 'ÐÑÑÑ Ð¿Ð¾ ÑазÑабоÑке Ð¸Ð³Ñ Ð² Roblox','ÐÑаÑиÑеÑкий дизайн в Figma','ÐÑаÑоÑÑкое маÑÑеÑÑÑво','ФинанÑÐ¾Ð²Ð°Ñ Ð³ÑамоÑноÑÑÑ', 8999 'ÐмоÑионалÑнÑй инÑеллекÑ','Ð¨Ð°Ñ Ð¼Ð°ÑÑ','Ðлогинг','ÐÑпанÑкий ÑзÑк','ÐемеÑкий ÑзÑк', 9000 'ÐлимпиаднÑй ÑÑÑÑкий ÑзÑк','Ðе планиÑÑÑ'], 9001 ['ÐиÑайÑкий ÑзÑк','ФÑанÑÑзÑкий ÑзÑк','ÐаÑемаÑика и логика. ÐеÑвÑе Ñаги в Ð¾Ð»Ð¸Ð¼Ð¿Ð¸Ð°Ð´Ð°Ñ ','ÐÑогÑаммиÑование на Python', 9002 'Создание ÑайÑов','ÐомпÑÑÑеÑÐ½Ð°Ñ Ð³ÑамоÑноÑÑÑ','ÐÑогÑаммиÑование в Minecraft','ÐÑогÑаммиÑование в Scratch', 9003 'ÐÑÑÑ Ð¿Ð¾ ÑазÑабоÑке Ð¸Ð³Ñ Ð² Roblox','ÐÑаÑиÑеÑкий дизайн в Figma','ÐÑаÑоÑÑкое маÑÑеÑÑÑво','ФинанÑÐ¾Ð²Ð°Ñ Ð³ÑамоÑноÑÑÑ', 9004 'ÐмоÑионалÑнÑй инÑеллекÑ','Ð¨Ð°Ñ Ð¼Ð°ÑÑ','Ðлогинг','ÐÑпанÑкий ÑзÑк','ÐемеÑкий ÑзÑк', 9005 'ÐлимпиаднÑй ÑÑÑÑкий ÑзÑк','Ðе планиÑÑÑ'], 9006 ['ÐиÑайÑкий ÑзÑк','ФÑанÑÑзÑкий ÑзÑк','ÐаÑемаÑика и логика. ÐеÑвÑе Ñаги в Ð¾Ð»Ð¸Ð¼Ð¿Ð¸Ð°Ð´Ð°Ñ ','ÐÑогÑаммиÑование на Python', 9007 'Создание ÑайÑов','ÐомпÑÑÑеÑÐ½Ð°Ñ Ð³ÑамоÑноÑÑÑ','ÐÑÑÑ Ð¿Ð¾ ÑазÑабоÑке Ð¸Ð³Ñ Ð² Roblox','ÐÑаÑиÑеÑкий дизайн в Figma', 9008 'ÐÑаÑоÑÑкое маÑÑеÑÑÑво','ФинанÑÐ¾Ð²Ð°Ñ Ð³ÑамоÑноÑÑÑ','ÐмоÑионалÑнÑй инÑеллекÑ','Ð¨Ð°Ñ Ð¼Ð°ÑÑ','Ðлогинг','ÐÑпанÑкий ÑзÑк', 9009 'ÐемеÑкий ÑзÑк','ÐлимпиаднÑй ÑÑÑÑкий ÑзÑк','Ðе планиÑÑÑ'], 9010 ['ÐиÑайÑкий ÑзÑк','ФÑанÑÑзÑкий ÑзÑк','ÐаÑемаÑика и логика. ÐеÑвÑе Ñаги в Ð¾Ð»Ð¸Ð¼Ð¿Ð¸Ð°Ð´Ð°Ñ ','ÐÑогÑаммиÑование на Python', 9011 'Создание ÑайÑов','ÐомпÑÑÑеÑÐ½Ð°Ñ Ð³ÑамоÑноÑÑÑ','ÐÑÑÑ Ð¿Ð¾ ÑазÑабоÑке Ð¸Ð³Ñ Ð² Roblox','ÐÑаÑиÑеÑкий дизайн в Figma', 9012 'ÐÑаÑоÑÑкое маÑÑеÑÑÑво','ФинанÑÐ¾Ð²Ð°Ñ Ð³ÑамоÑноÑÑÑ','ÐмоÑионалÑнÑй инÑеллекÑ','Ð¨Ð°Ñ Ð¼Ð°ÑÑ','Ðлогинг','ÐÑпанÑкий ÑзÑк', 9013 'ÐемеÑкий ÑзÑк','ÐлимпиаднÑй ÑÑÑÑкий ÑзÑк','Ðе планиÑÑÑ'], 9014 ['ÐодгоÑовка к ÐÐРпо маÑемаÑике','ÐодгоÑовка к ÐÐРпо ÑÑÑÑÐºÐ¾Ð¼Ñ ÑзÑкÑ','ÐодгоÑовка к ÐÐРпо биологии','ÐодгоÑовка к ÐÐРпо иÑÑоÑии', 9015 'ÐодгоÑовка к ÐÐРпо английÑÐºÐ¾Ð¼Ñ ÑзÑкÑ','ÐодгоÑовка к ÐÐРпо обÑеÑÑвознаниÑ','ÐодгоÑовка к ÐÐРпо Ñизике','ÐодгоÑовка к ÐÐРпо Ñ Ð¸Ð¼Ð¸Ð¸', 9016 'ÐодгоÑовка к ÐÐРпо инÑоÑмаÑике','ÐодгоÑовка к ÐÐРпо геогÑаÑии','ÐодгоÑовка к ÐÐРпо лиÑеÑаÑÑÑе', 9017 'ÐиÑайÑкий ÑзÑк','ФÑанÑÑзÑкий ÑзÑк','ÐÑогÑаммиÑование на Python','Создание ÑайÑов','ÐомпÑÑÑеÑÐ½Ð°Ñ Ð³ÑамоÑноÑÑÑ', 9018 'ÐÑÑÑ Ð¿Ð¾ ÑазÑабоÑке Ð¸Ð³Ñ Ð² Roblox','ÐÑаÑиÑеÑкий дизайн в Figma','ÐÑаÑоÑÑкое маÑÑеÑÑÑво','ФинанÑÐ¾Ð²Ð°Ñ Ð³ÑамоÑноÑÑÑ', 9019 'ÐмоÑионалÑнÑй инÑеллекÑ','Ð¨Ð°Ñ Ð¼Ð°ÑÑ','Ðлогинг','ЦиÑÑовÑе пÑоÑеÑÑии','ÐÑпанÑкий ÑзÑк','ÐемеÑкий ÑзÑк', 9020 'ÐодгоÑовка к пеÑеÑневÑм олимпиадам по маÑемаÑике','ÐлимпиаднÑй ÑÑÑÑкий ÑзÑк','Ðе планиÑÑÑ'], 9021 ['ÐодгоÑовка к ÐÐРпо маÑемаÑике','ÐодгоÑовка к ÐÐРпо ÑÑÑÑÐºÐ¾Ð¼Ñ ÑзÑкÑ','ÐодгоÑовка к ÐÐРпо биологии','ÐодгоÑовка к ÐÐРпо иÑÑоÑии', 9022 'ÐодгоÑовка к ÐÐРпо английÑÐºÐ¾Ð¼Ñ ÑзÑкÑ','ÐодгоÑовка к ÐÐРпо обÑеÑÑвознаниÑ','ÐодгоÑовка к ÐÐРпо Ñизике','ÐодгоÑовка к ÐÐРпо Ñ Ð¸Ð¼Ð¸Ð¸', 9023 'ÐодгоÑовка к ÐÐРпо инÑоÑмаÑике','ÐодгоÑовка к ÐÐРпо геогÑаÑии','ÐодгоÑовка к ÐÐРпо лиÑеÑаÑÑÑе', 9024 'ÐиÑайÑкий ÑзÑк','ФÑанÑÑзÑкий ÑзÑк','ÐÑогÑаммиÑование на Python','Создание ÑайÑов','ÐÑаÑиÑеÑкий дизайн в Figma', 9025 'ÐÑаÑоÑÑкое маÑÑеÑÑÑво','ФинанÑÐ¾Ð²Ð°Ñ Ð³ÑамоÑноÑÑÑ','ÐмоÑионалÑнÑй инÑеллекÑ','Ð¨Ð°Ñ Ð¼Ð°ÑÑ','Ðлогинг','ЦиÑÑовÑе пÑоÑеÑÑии', 9026 'ÐÑпанÑкий ÑзÑк','ÐемеÑкий ÑзÑк','ÐодгоÑовка к пеÑеÑневÑм олимпиадам по маÑемаÑике','ÐлимпиаднÑй ÑÑÑÑкий ÑзÑк','Ðе планиÑÑÑ' 9027 ], 9028 ['ÐодгоÑовка к ÐÐРпо пÑоÑилÑной маÑемаÑике','ÐодгоÑовка к ÐÐРпо базовой маÑемаÑике','ÐодгоÑовка к ÐÐРпо ÑÑÑÑÐºÐ¾Ð¼Ñ ÑзÑкÑ', 9029 'ÐодгоÑовка к ÐÐРпо биологии','ÐодгоÑовка к ÐÐРпо иÑÑоÑии', 9030 'ÐодгоÑовка к ÐÐРпо английÑÐºÐ¾Ð¼Ñ ÑзÑкÑ','ÐодгоÑовка к ÐÐРпо обÑеÑÑвознаниÑ','ÐодгоÑовка к ÐÐРпо Ñизике','ÐодгоÑовка к ÐÐРпо Ñ Ð¸Ð¼Ð¸Ð¸', 9031 'ÐодгоÑовка к ÐÐРпо инÑоÑмаÑике','ÐодгоÑовка к ÐÐРпо геогÑаÑии','ÐодгоÑовка к ÐÐРпо лиÑеÑаÑÑÑе', 9032 'ÐиÑайÑкий ÑзÑк','ФÑанÑÑзÑкий ÑзÑк','ÐÑогÑаммиÑование на Python','Создание ÑайÑов','ÐÑаÑиÑеÑкий дизайн в Figma', 9033 'ÐÑаÑоÑÑкое маÑÑеÑÑÑво','ФинанÑÐ¾Ð²Ð°Ñ Ð³ÑамоÑноÑÑÑ','ÐмоÑионалÑнÑй инÑеллекÑ','Ð¨Ð°Ñ Ð¼Ð°ÑÑ','Ðлогинг','ЦиÑÑовÑе пÑоÑеÑÑии', 9034 'ÐÑпанÑкий ÑзÑк','ÐемеÑкий ÑзÑк','ÐодгоÑовка к пеÑеÑневÑм олимпиадам по маÑемаÑике','ÐлимпиаднÑй ÑÑÑÑкий ÑзÑк', 9035 'Ðе планиÑÑÑ'] 9036 ] 9037 } 9038 9039 let currentSlide = 0 9040 let classChosen 9041 const nextBtns = quiz.querySelectorAll('[data-element="quiz-next"]') 9042 const prevBtns = quiz.querySelectorAll('[data-element="quiz-prev"]') 9043 const slides = quiz.querySelectorAll('[data-element="quiz-inner"]') 9044 const form = quiz.querySelector('[data-element="quiz-form"]') 9045 const linkTo = form.getAttribute("data-docex") 9046 const wrap = quiz.querySelector('.quiz__wrap') 9047 const progress = quiz.querySelector('[data-element="quiz-progress"]') 9048 const progressFill = quiz.querySelector('[data-element="quiz-progress-bar-fill"]') 9049 9050 function initValidate () { 9051 const button = slides[currentSlide].querySelector("[data-element='quiz-next']") 9052 const input = slides[currentSlide].querySelectorAll('.quiz__input') 9053 if (input[0].type === 'text') { 9054 for (let i = 0; i < input.length; i++) { 9055 input[i].addEventListener('input', function () { 9056 button.disabled = !input[0].value || !input[1].value 9057 }) 9058 } 9059 } else if (input[0].type === 'radio') { 9060 for (let i = 0; i < input.length; i++)
9060{ 9061 input[i].addEventListener('input', function () { 9062 const checked = slides[currentSlide].querySelector("input:checked") 9063 button.disabled = !checked 9064 }) 9065 } 9066 } else { 9067 const hidden = slides[currentSlide].querySelector('.quiz__hidden-checkbox') 9068 for (let i = 0; i < input.length; i++) { 9069 input[i].addEventListener('input', function () { 9070 const checked = slides[currentSlide].querySelectorAll("input:checked") 9071 button.disabled = !checked.length 9072 let temp = '' 9073 for (let j = 0; j < checked.length; j++) { 9074 temp += checked[j].value 9075 if (j !== checked.length - 1) temp += ', ' 9076 } 9077 hidden.value = temp 9078 }) 9079 } 9080 } 9081 } 9082 9083 function initValidateLastSlide () { 9084 const inputs = slides[currentSlide].querySelectorAll('input') 9085 9086 for (let i = 0; i < inputs.length; i++) { 9087 inputs[i].addEventListener('change', validate) 9088 } 9089 function validate () { 9090 if (inputs[inputs.length - 1].checked) { 9091 for (let i = 0; i < inputs.length - 1; i++) { 9092 if (inputs[i].getAttribute('type') != 'hidden') { 9093 inputs[i].disabled = true 9094 inputs[i].closest('.quiz__label')?.classList?.add('disable') 9095 } 9096 } 9097 } else { 9098 for (let i = 0; i < inputs.length - 1; i++) { 9099 inputs[i].disabled = false 9100 inputs[i].closest('.quiz__label')?.classList?.remove('disable') 9101 } 9102 } 9103 let disableLastInput = false 9104 for (let i = 0; i < inputs.length - 1; i++) { 9105 if (inputs[i].checked) { 9106 inputs[inputs.length - 1].disabled = true 9107 inputs[inputs.length - 1].closest('.quiz__label').classList.add('disable') 9108 disableLastInput = true 9109 } 9110 } 9111 if (!disableLastInput) { 9112 inputs[inputs.length - 1].disabled = false 9113 inputs[inputs.length - 1].closest('.quiz__label').classList.remove('disable') 9114 } 9115 } 9116 } 9117 9118 for (let i = 0; i < nextBtns.length; i++) { 9119 nextBtns[i].addEventListener('click', nextSlide) 9120 } 9121 9122 for (let i = 0; i < prevBtns.length; i++) { 9123 prevBtns[i].addEventListener('click', prevSlide) 9124 } 9125 9126 initValidate() 9127 9128 function nextSlide () { 9129 window.scrollTo({ top: 0, behavior: 'smooth' }) 9130 if (currentSlide === 0) { 9131 progress.classList.remove('hide') 9132 wrap.classList.remove('quiz__wrap_first-slide') 9133 } 9134 if (currentSlide === 1) { 9135 classChosen = slides[currentSlide].querySelector('input:checked').value 9136 const button = slides[currentSlide + 2].querySelector('.quiz__button') 9137 if (classChosen === "0") { 9138 currentSlide += 1 9139 button.type = 'submit' 9140 button.textContent = 'ÐÑпÑавиÑÑ Ð¾ÑвеÑÑ' 9141 button.disabled = true 9142 } else { 9143 button.type = 'button' 9144 button.textContent = 'ÐалÑÑе' 9145 button.disabled = true 9146 } 9147 } else if (currentSlide === 2) { 9148 if (slides[currentSlide].querySelector('input:checked').value === "Ðа") { 9149 currentSlide += 1 9150 } 9151 } else if (currentSlide === 3 && classChosen === "0") { 9152 sendData() 9153 } 9154 9155 if (currentSlide < slides.length - 1) { 9156 const generateListNode = slides[currentSlide + 1].querySelector('[data-element="quiz-generate"]') 9157 if (generateListNode) generateList(generateListNode) 9158 9159 const oldActiveSlide = quiz.querySelector('.quiz__inner.active') 9160 oldActiveSlide.classList.remove('active') 9161 currentSlide += 1 9162 slides[currentSlide].classList.add('active') 9163 initValidate() 9164 if (currentSlide === slides.length - 1 || generateListNode) initValidateLastSlide() 9165 } else { 9166 sendData() 9167 } 9168 progressFill.style.width = Math.round(currentSlide/(slides.length - 1) * 100) + '%' 9169 } 9170 9171 function prevSlide () { 9172 if (currentSlide > 0) { 9173 if (currentSlide === 1) { 9174 progress.classList.add('hide') 9175 wrap.classList.add('quiz__wrap_first-slide') 9176 } 9177 9178 if (currentSlide === 4 && slides[2].querySelector('input:checked').value === "Ðа") { 9179 currentSlide -= 1 9180 } else if (currentSlide === 3 && classChosen === "0") { 9181 currentSlide -= 1 9182 } 9183 9184 const oldActiveSlide = quiz.querySelector('.quiz__inner.active') 9185 oldActiveSlide.classList.remove('active') 9186 currentSlide -= 1 9187 slides[currentSlide].classList.add('active') 9188 9189 progressFill.style.width = Math.round(currentSlide/(slides.length - 1) * 100) + '%' 9190 } 9191 } 9192 9193 function sendData () { 9194 if (checkHoneypot()) return 9195 form.submit() 9196 setTimeout(() => { 9197 location.assign(linkTo) 9198 }, 100) 9199 } 9200 9201 function checkHoneypot() { 9202 const honeypots = form.querySelector('.modal-exter__input') 9203 return honeypots && honeypots?.value 9204 } 9205 9206 9207 function generateList (list) { 9208 const type = list.getAttribute('data-type') 9209 const name = list.getAttribute('data-name') 9210 const array = (generateData[list.getAttribute('data-list')])[classChosen] 9211 list.innerHTML = '' 9212 for (let i = 0; i < array.length; i++) { 9213 const nameInput = type === "radio" ? name : false 9214 let item 9215 if (nameInput) { 9216 item = `<label class="quiz__label"> 9217 <input class="quiz__input" type="${type}" name="${nameInput}" value="${array[i]}"> 9218 <div class="${'quiz__input-view quiz__input-view_' + type}"></div> 9219 <div class="quiz__input-text">${array[i]}</div> 9220 </label>` 9221 } else { 9222 item = `<label class="quiz__label"> 9223 <input class="quiz__input" type="${type}" value="${array[i]}"> 9224 <div class="${'quiz__input-view quiz__input-view_' + type}"></div> 9225 <div class="quiz__input-text">${array[i]}</div> 9226 </label>` 9227 } 9228
9229 list.innerHTML += item 9230 } 9231 } 9232} 9233 9234const reasons = document.querySelector('.reasons') 9235 9236if (reasons) reasonsInit() 9237 9238function reasonsInit () { 9239 window.scrollTo(0, 0) 9240 const body = document.querySelector('body') 9241 body.classList.add('no-scroll') 9242 const area = reasons.querySelector('.reasons__area') 9243 const circles = reasons.querySelectorAll('.reasons__circle') 9244 const caption = reasons.querySelector('.reasons__caption') 9245 const image = reasons.querySelector('.reasons__image') 9246 9247 const step = 300 9248 let index = -1 9249 let touchstartY = 0 9250 let touchendY = 0 9251 const swipeThreshold = 50 9252 9253 function throttle(func, delay) { 9254 let inThrottle 9255 let lastFn 9256 let lastTime 9257 9258 return function() { 9259 const context = this 9260 const args = arguments 9261 9262 if (!inThrottle) { 9263 func.apply(context, args) 9264 lastTime = Date.now() 9265 inThrottle = true 9266 } else { 9267 clearTimeout(lastFn) 9268 lastFn = setTimeout(function() { 9269 if (Date.now() - lastTime >= delay) { 9270 func.apply(context, args) 9271 lastTime = Date.now() 9272 } 9273 }, Math.max(delay - (Date.now() - lastTime), 0)) 9274 } 9275 } 9276 } 9277 9278 let lock = false 9279 9280 function update (e) { 9281 if (lock) return 9282 if (e.deltaY < 0) { 9283 prevSlide() 9284 } else if (e.deltaY > 0) { 9285 nextSlide() 9286 } 9287 lock = true 9288 setTimeout(() => {lock = false}, 600) 9289 } 9290 9291 window.addEventListener('touchstart', e => { 9292 touchstartY = e.touches[0].clientY 9293 }) 9294 9295 window.addEventListener('touchend', e => { 9296 touchendY = e.changedTouches[0].clientY 9297 handleGesture() 9298 }) 9299 9300 function handleGesture() { 9301 if (touchendY < touchstartY - swipeThreshold) { 9302 nextSlide() 9303 } 9304 9305 if (touchendY > touchstartY + swipeThreshold) { 9306 prevSlide() 9307 } 9308 } 9309 9310 window.addEventListener('wheel', update, { passive: true }) 9311 9312 function prevSlide () { 9313 if (index > -1 && window.scrollY === 0) { 9314 body.classList.add('no-scroll') 9315 if (area) area.classList.remove('end') 9316 hideOldSlide() 9317 index-- 9318 showNewSlide() 9319 animateBg() 9320 if (index === -1) { 9321 caption.classList.remove('animate') 9322 image.classList.remove('animate') 9323 area.classList.remove('animate') 9324 circles[0].classList.remove('animate-end') 9325 } 9326 } 9327 } 9328 9329 function nextSlide () { 9330 if (index < circles.length - 1) { 9331 hideOldSlide() 9332 index++ 9333 showNewSlide() 9334 animateBg() 9335 if (index === 0) { 9336 caption.classList.add('animate') 9337 image.classList.add('animate') 9338 area.classList.add('animate') 9339 circles[0].classList.add('animate-end') 9340 } 9341 if (index === circles.length - 1) { 9342 area.classList.add('end') 9343 body.classList.remove('no-scroll') 9344 } 9345 } 9346 } 9347 9348 function hideOldSlide () { 9349 if (circles[index]) circles[index].classList.remove('animate') 9350 } 9351 9352 function showNewSlide () { 9353 if (circles[index]) circles[index].classList.add('animate') 9354 } 9355 9356 function animateBg () { 9357 reasons.style.backgroundPositionY = `${step * (index+1)}px` 9358 } 9359} 9360 9361const reviewDetailVideoBox = document.querySelector('.review-detail__video-box') 9362 9363if (reviewDetailVideoBox) { 9364 const video = reviewDetailVideoBox.querySelector('.review-detail__video') 9365 9366 reviewDetailVideoBox.addEventListener('click', function () { 9367 playVideo() 9368 }, {once: true}) 9369 9370 9371 function playVideo () { 9372 video.play() 9373 reviewDetailVideoBox.classList.add('active') 9374 } 9375 9376} 9377 9378 9379const review = document.querySelector('.review') 9380 9381if (review) reviewInit() 9382 9383function reviewInit() { 9384 const textReplace = { 9385 parent: [ 9386 { selector: '.review__caption_thanks-1', text: 'СпаÑибо, ÑÑо поделилиÑÑ Ð¾Ð¿ÑÑом!' }, 9387 { selector: '.review__caption_thanks-2', text: 'СпаÑибо за Ð²Ð°Ñ Ð¾ÑзÑв!' }, 9388 { selector: '.review__headline-thanks-1', text: 'ÐайÑе ваÑÐµÐ¼Ñ Ð¼Ð½ÐµÐ½Ð¸Ñ ÑеалÑнÑÑ ÑилÑ' }, 9389 { selector: '.review__thanks-title', text: 'ÐÐ°Ñ Ð¾ÑзÑв â оÑиенÑÐ¸Ñ Ð´Ð»Ñ Ð´ÑÑÐ³Ð¸Ñ ÑодиÑелей.' }, 9390 { selector: '.review__thanks-text_1', text: 'Ðногие ÑодиÑели ÑейÑÐ°Ñ Ð¸ÑÑÑ ÑеÑÑнÑе оÑзÑвÑ, ÑÑÐ¾Ð±Ñ ÑделаÑÑ Ð²ÑÐ±Ð¾Ñ Ð´Ð»Ñ Ñвоего Ñебенка.' }, 9391 // { selector: '.review__thanks-text_2', text: 'ÐÐ°Ñ Ð¾ÑзÑв на <a href="https://www.rbc.ru/courses/school-reviews/tocka-znanii" data-redirect>
9391Ð ÐÐ</a> ÑÑÐ°Ð½ÐµÑ Ð´Ð»Ñ Ð½Ð¸Ñ Ð²ÐµÑомÑм аÑгÑменÑом, коÑоÑÑй ÑÑÐºÐ¾Ð½Ð¾Ð¼Ð¸Ñ Ð²ÑемÑ, денÑги и неÑвÑ.' }, 9392 { selector: '.review__thanks-text_2', text: 'ÐÐ°Ñ Ð¾ÑзÑв на ÐÑзовике ÑÑÐ°Ð½ÐµÑ Ð´Ð»Ñ Ð½Ð¸Ñ Ð²ÐµÑомÑм аÑгÑменÑом, коÑоÑÑй ÑÑÐºÐ¾Ð½Ð¾Ð¼Ð¸Ñ Ð²ÑемÑ, денÑги и неÑвÑ.' }, 9393 // { selector: '.review__thanks-headline_1', text: 'ÐожалÑйÑÑа, ÑкопиÑÑйÑе Ñвой оÑзÑв и добавÑÑе на Ð ÐÐ.' }, 9394 { selector: '.review__thanks-headline_1', text: 'ÐожалÑйÑÑа, ÑкопиÑÑйÑе Ñвой оÑзÑв и добавÑÑе на ÐÑзовик.' }, 9395 { selector: '.review__thanks-headline_2', text: 'ÐÑо займÑÑ 2 минÑÑÑ. ÐÑÑÑÑ Ð²Ð°Ñ Ð³Ð¾Ð»Ð¾Ñ Ð¿Ð¾Ð¼Ð¾Ð¶ÐµÑ Ñ Ð²ÑбоÑом и ÑÑÐ°Ð½ÐµÑ Ð¾ÑиенÑиÑом.' }, 9396 { selector: '.review__thanks-headline_3', text: 'ÐÑÑавÑÑе оÑзÑв и помогиÑе дÑÑгим ÑодиÑелÑм!' }, 9397 { selector: '.review__thanks-2-title', text: 'ÐÑли Ð²Ñ Ñ Ð¾ÑиÑе оÑÑавиÑÑ Ð¾ÑзÑв на дÑÑÐ³Ð¸Ñ ÑÑиÑелей или ÑÑÑÑоÑов, нажмиÑе на кнопки ниже' }, 9398 ], 9399 student: [ 9400 { selector: '.review__caption_thanks-1', text: 'СпаÑибо, ÑÑо делиÑÑÑÑ Ð¾Ð¿ÑÑом!' }, 9401 { selector: '.review__caption_thanks-2', text: 'СпаÑибо за Ñвой оÑзÑв!' }, 9402 { selector: '.review__headline-thanks-1', text: 'ÐайÑе ÑÐ²Ð¾ÐµÐ¼Ñ Ð¼Ð½ÐµÐ½Ð¸Ñ ÑеалÑнÑÑ ÑилÑ' }, 9403 { selector: '.review__thanks-title', text: 'Твой оÑзÑв â оÑиенÑÐ¸Ñ Ð´Ð»Ñ Ð´ÑÑÐ³Ð¸Ñ ÑÑеников.' }, 9404 { selector: '.review__thanks-text_1', text: 'ÐовиÑкам онлайн-обÑÑÐµÐ½Ð¸Ñ Ñоже бÑÐ²Ð°ÐµÑ ÑÑÑдно: кÑо-Ñо боиÑÑÑ Ð½ÐµÐ¿Ð¾Ð½ÑÑнÑÑ Ñем, Ñложной домаÑки или оÑÑаÑÑÑÑ Ð±ÐµÐ· поддеÑжки ÑÑиÑелей.' }, 9405 { selector: '.review__thanks-text_2', text: 'Твой оÑзÑв Ð¿Ð¾Ð¼Ð¾Ð¶ÐµÑ Ð¸Ð¼ понÑÑÑ, ÑÑо ÑÑÑдноÑÑи ÑеÑÐ°ÐµÐ¼Ñ Ð¸ поддеÑжка ÑÑдом. ÐлагодаÑÑ Ñебе дÑÑгие ÑебÑÑа ÑмогÑÑ ÑделаÑÑ ÑвеÑеннÑй вÑбоÑ' }, 9406 // { selector: '.review__thanks-headline_1', text: 'ÐожалÑйÑÑа, ÑкопиÑÑй Ñвой оÑзÑв и Ð´Ð¾Ð±Ð°Ð²Ñ Ð½Ð° Ð ÐÐ.' }, 9407 { selector: '.review__thanks-headline_1', text: 'ÐожалÑйÑÑа, ÑкопиÑÑй Ñвой оÑзÑв и Ð´Ð¾Ð±Ð°Ð²Ñ Ð½Ð° ÐÑзовик.' }, 9408 { selector: '.review__thanks-headline_2', text: 'ÐÑо займÑÑ 2 минÑÑÑ.' }, 9409 { selector: '.review__thanks-headline_3', text: 'ÐÑÑÐ°Ð²Ñ Ð¾ÑзÑв и помоги дÑÑгим ÑколÑникам!' }, 9410 { selector: '.review__thanks-2-title', text: 'ÐÑли ÑÑ Ñ Ð¾ÑеÑÑ Ð¾ÑÑавиÑÑ Ð¾ÑзÑв на дÑÑÐ³Ð¸Ñ ÑÑиÑелей или ÑÑÑÑоÑов, нажми на кнопки ниже' }, 9411 ] 9412 } 9413 9414 const selectTops = review.querySelectorAll('.review__select-top') 9415 const body = document.querySelector('body') 9416 const copy = review.querySelector('.review__thanks-copy') 9417 const textarea = review.querySelector('.review__textarea') 9418 const buttonNext = review.querySelector('.review__button') 9419 const buttonBack = review.querySelector('.review__back') 9420 const buttonMobBack = review.querySelector('.review__mob-back') 9421 const slides = review.querySelectorAll('.review__slide') 9422 const steps = review.querySelectorAll('.review__step') 9423 const form = review.querySelector('.review__form') 9424 const inputRate = review.querySelector('.review__rate-hidden') 9425 const inputRateDesktop = review.querySelectorAll('.review__rate-desktop-input') 9426 const selectSearchArray = review.querySelectorAll('.review__select-search') 9427 const simpleBars = review.querySelectorAll('[data-role="review-simplebar"]') 9428 const btnSubmit = form.querySelector('.review__submit') 9429 const role = review.querySelector('.review__role') 9430 const roleInputs = review.querySelectorAll('.review__role-input') 9431 const nameInput = review.querySelector("[name='st_name']") 9432 const surnameInput = review.querySelector("[name='st_surname']") 9433 const emailInput = review.querySelector("[name='email']") 9434 const selectClass = review.querySelector(".review__select_class") 9435 const selectClassInputs = selectClass.querySelectorAll(".review__select-input") 9436 const rateDesktop = review.querySelector(".review__rate-desktop") 9437 const selectsOnSecondSlide = slides[1].querySelectorAll('.review__select') 9438 const selectTopCloseArray = slides[1].querySelectorAll('.review__select-top-close') 9439 const subjectItems = document.querySelectorAll('.review__select_subject .review__select-item') 9440 const boxSubject = document.querySelector('.review__box_subject') 9441 const closeArrows = document.querySelectorAll('.review__select-top-close-arrow') 9442 const selectTeacherOrTutor = document.querySelector('.review__select_teacher') || document.querySelector('.review__select_tutor') 9443 const head_1 = review.querySelector('.review__thanks-headline_1') 9444 const head_2 = review.querySelector('.review__thanks-headline_2') 9445 const copyBox = review.querySelector('.review__thanks-copy-box') 9446 9447 9448 for (let i = 0; i < closeArrows.length; i++) { 9449 closeArrows[i].addEventListener('click', function (e) { 9450 e.stopPropagation() 9451 closeSelect(closeArrows[i].closest('.review__select-top')) 9452 }) 9453 } 9454 9455 for (let i = 0; i < selectsOnSecondSlide.length; i++) { 9456 const inputs = selectsOnSecondSlide[i].querySelectorAll('.review__select-input') 9457 for (let j = 0; j < inputs.length; j++) { 9458 inputs[j].addEventListener('change', () => { 9459 selectsOnSecondSlide[i].classList.remove('review-error') 9460 }) 9461 } 9462 } 9463 9464 for (let i = 0; i < selectClassInputs.length; i++) { 9465 const selectSearch = selectTeacherOrTutor.querySelector('.review__select-search') 9466 selectClassInputs[i].addEventListener('change', function () { 9467 selectClass.classList.remove('review-error') 9468 resetTeachersSort() 9469 resetSubjectCheckedInput(true) 9470 resetSearchCheckedInput() 9471 selectSort(selectSearch) 9472 clearSelectText(selectTeacherOrTutor) 9473 teachersSort(this.value) 9474 }) 9475 } 9476 9477 function teachersSort (selectedClass) { 9478 const searchLabels = selectTeacherOrTutor.querySelectorAll('.review__select-item')
9479 searchLabels.forEach(label => { 9480 const input = label.querySelector('.review__select-input') 9481 const dataGrades = input.getAttribute('data-grades') 9482 if (!dataGrades) return 9483 const dataGradesParsed = JSON.parse(dataGrades) 9484 if (!(dataGradesParsed.find((data) => data == selectedClass))) label.classList.add('review__select-item_hide') 9485 }) 9486 } 9487 9488 function resetTeachersSort () { 9489 const searchLabels = selectTeacherOrTutor.querySelectorAll('.review__select-item') 9490 searchLabels.forEach(label => { 9491 label.classList.remove('review__select-item_hide') 9492 }) 9493 } 9494 9495 for (let i = 0; i < roleInputs.length; i++) { 9496 roleInputs[i].addEventListener('change', () => { 9497 role.classList.remove('review-error') 9498 const value = review.querySelector('.review__role-input:checked')?.value 9499 replaceTexts(value) 9500 }) 9501 } 9502 9503 function replaceTexts(value) { 9504 if (value === 'student') { 9505 review.classList.add('review_student') 9506 } else { 9507 review.classList.remove('review_student') 9508 } 9509 textReplace[value].forEach((item) => { 9510 const node = review.querySelector(item.selector) 9511 node.innerHTML = item.text 9512 const dataRedirectLinks = node.querySelectorAll('[data-redirect]') 9513 for (let i = 0; i < dataRedirectLinks.length; i++) { 9514 dataRedirectLinks[i].addEventListener('click', dataRedirect) 9515 } 9516 }) 9517 9518 } 9519 9520 nameInput.addEventListener('input', () => nameInput.classList.remove('review-error')) 9521 surnameInput.addEventListener('input', () => surnameInput.classList.remove('review-error')) 9522 emailInput.addEventListener('input', () => emailInput.classList.remove('review-error')) 9523 9524 function validateEmail (email) { 9525 if (/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(email.value)) { 9526 email.classList.remove('review-error') 9527 return true 9528 } else { 9529 email.classList.add('review-error') 9530 return false 9531 } 9532 } 9533 9534 for (let i = 0; i < simpleBars.length; i++) { 9535 new SimpleBar(simpleBars[i]) 9536 } 9537 9538 selectTopCloseArray.forEach((topClose) => { 9539 topClose.addEventListener('click', function () { 9540 const select = this.closest('.review__select') 9541 const selectTop = this.closest('.review__select-top') 9542 const selectSearch = selectTop.querySelector('.review__select-search') 9543 selectSearch.value = '' 9544 selectSort(selectSearch) 9545 closeSelect(selectTop) 9546 if (select.classList.contains('review__select_teacher') || select.classList.contains('review__select_tutor')) { 9547 resetSearchCheckedInput(selectSearch) 9548 resetSubjectCheckedInput(true) 9549 } else { 9550 resetSubjectCheckedInput(false) 9551 } 9552 const selectTopText = selectTop?.querySelector('.review__select-top-text') 9553 if (selectTopText) { 9554 selectTopText.classList.remove('active') 9555 selectTopText.innerHTML = selectTopText.getAttribute('data-default-text') 9556 } 9557 }) 9558 }) 9559 9560 9561 selectSearchArray.forEach((selectSearch) => { 9562 const select = selectSearch.closest('.review__select') 9563 selectSearch.addEventListener('input', () => selectSort(selectSearch)) 9564 selectSearch.addEventListener('input', () => resetSearchCheckedInput(selectSearch)) 9565 if (select.classList.contains('review__select_teacher') || select.classList.contains('review__select_tutor')) { 9566 selectSearch.addEventListener('input', () => resetSubjectCheckedInput(true)) 9567 selectSearch.addEventListener('input', () => subjectsFilter(selectSearch)) 9568 } 9569 const reviewSearchMob = select.querySelector('.review__search-mob') 9570 if (reviewSearchMob) { 9571 reviewSearchMob.addEventListener('input', () => selectSort(reviewSearchMob)) 9572 } 9573 }) 9574 9575 function resetSearchCheckedInput (selectSearch) { 9576 const checkedInput = selectSearch?.closest('.review__select')?.querySelector('.review__select-input:checked') 9577 if (checkedInput) checkedInput.checked = false 9578 } 9579 9580 function resetSubjectCheckedInput (disabled) { 9581 const select = document.querySelector('.review__select_subject') 9582 clearSelectText(select) 9583 if (disabled) { 9584 boxSubject.classList.add('review__box_disabled') 9585 const search = select.querySelector('.review__select-search') 9586 selectSort(search) 9587 } 9588 } 9589 9590 function clearSelectText (select) { 9591 const checkedInput = select.querySelector('.review__select-input:checked') 9592 if (checkedInput) checkedInput.checked = false 9593 const text = select.querySelector('.review__select-top-text') 9594 if (text) text.innerHTML = 'Ðе вÑбÑано' 9595 const search = select.querySelector('.review__select-search') 9596 if (search) search.value = '' 9597 const searchMob = select.querySelector('.review__search-mob') 9598 if (searchMob) searchMob.value = '' 9599 } 9600 9601 function subjectsFilter (selectSearch) { 9602 const checkedInput = selectSearch.closest('.review__select')?.querySelector('.review__select-input:checked') 9603 if (checkedInput) { 9604 const dataSubjects = checkedInput.getAttribute('data-subjects') 9605 if (!dataSubjects) return 9606 const dataSubjectsParsed = JSON.parse(dataSubjects) 9607 hideAllSubjects() 9608 for (let i = 0; i < dataSubjectsParsed.length; i++) { 9609 const subject = document.querySelector(`[data-subject="${dataSubjectsParsed[i]}"]`) 9610 if (subject) subject.closest('.review__select-item').classList.remove('review__select-item_hide') 9611 } 9612 } else { 9613 showAllSubjects() 9614 } 9615 } 9616 9617 function hideAllSubjects () { 9618 for (let i = 0; i < subjectItems.length; i++) { 9619 subjectItems[i].classList.add('review__select-item_hide') 9620 } 9621 } 9622 9623 function showAllSubjects () { 9624 for (let i = 0; i < subjectItems.length; i++) { 9625 subjectItems[i].classList.remove('review__select-item_hide') 9626 } 9627 } 9628 9629 9630 function selectSort (search) { 9631 const select = search.closest('.review__select') 9632 const searchLabels = select.querySelectorAll('.review__select-item') 9633 const reviewSearchMob = select.querySelector('.review__search-mob') 9634 if (search.classList.contains('review__select-search')) { 9635 reviewSearchMob.value = search.value 9636 } else { 9637 search.value = reviewSearchMob.value 9638 } 9639 const searchString = search.value.toLowerCase() 9640 const searchSelect = search.closest('.review__select') 9641 if (searchString) { 9642 searchSelect.classList.add('review__select_not-empty') 9643 } else { 9644 searchSelect.classList.remove('review__select_not-empty') 9645 } 9646 for (let i = 0; i < searchLabels.length; i++) { 9647 const text = searchLabels[i].querySelector('.review__select-input').getAttribute('data-text').toLowerCase() 9648 if (text.startsWith(searchString) || text === searchString) { 9649 searchLabels[i].style.display = 'block' 9650 } else { 9651 searchLabels[i].style.display = 'none' 9652 } 9653 } 9654 } 9655
9656 copy.addEventListener('click', copyReview) 9657 9658 function copyReview () { 9659 steps[2].classList.add('done') 9660 navigator.clipboard.writeText(textarea.value) 9661 copy.textContent = 'СкопиÑовано' 9662 copy.classList.add('done') 9663 setTimeout(() => { 9664 copy.textContent = 'СкопиÑоваÑÑ Ð¾ÑзÑв' 9665 copy.classList.remove('done') 9666 }, 2000) 9667 } 9668 9669 for (let i = 0; i < inputRateDesktop.length; i++) { 9670 inputRateDesktop[i].addEventListener('change', setRateInputValue) 9671 } 9672 9673 function setRateInputValue () { 9674 inputRate.value = review.querySelector('.review__rate-desktop-input:checked').value 9675 rateDesktop.classList.remove('review-error') 9676 } 9677 9678 buttonNext.addEventListener('click', nextSlide) 9679 buttonBack.addEventListener('click', prevSlide) 9680 buttonMobBack.addEventListener('click', prevSlide) 9681 let isSubmitting = false; 9682 form.addEventListener('submit', submitForm) 9683 9684 function afterSuccessSubmit () { 9685 const oldSlide = review.querySelector('.review__slide.active') 9686 if (oldSlide) oldSlide.classList.remove('active') 9687 if (inputRate.value > 8) { 9688 slides[2].classList.add('active') 9689 review.classList.add('review_thanks-1') 9690 if (!textarea.value) { 9691 head_1.style.display = 'none' 9692 head_2.style.display = 'none' 9693 copyBox.style.display = 'none' 9694 } else { 9695 head_1.style.display = 'block' 9696 head_2.style.display = 'block' 9697 copyBox.style.display = 'flex' 9698 } 9699 9700 } else { 9701 slides[3].classList.add('active') 9702 steps[2].classList.add('done') 9703 review.classList.add('review_thanks-2') 9704 } 9705 steps[1].classList.add('done') 9706 steps[2].classList.add('active') 9707 window.scrollTo(0, 0) 9708 } 9709 9710 async function submitForm (e) { 9711 e.preventDefault() 9712 if (!validateSecondSlide()) return 9713 const email = form.querySelector('[name="email"]') 9714 if (email) { 9715 email_value = email.value; 9716 } 9717 9718 btnSubmit.disabled = true; 9719 9720 if (checkHoneypot()) return 9721 9722 try { 9723 e.stopPropagation(); 9724 console.log('isSubmitting:', isSubmitting); 9725 if (isSubmitting) return false; 9726 9727 // if (!captchaPassed) { 9728 // // console.log('ð ÐÑзов execute...'); 9729 captchaToken = null; 9730 // window.smartCaptcha.execute(window.captchaWidget); 9731 9732 // await new Promise((resolve, reject) => { 9733 // const checkToken = setInterval(() => { 9734 // if (captchaToken) { 9735 // clearInterval(checkToken); 9736 // resolve(); 9737 // } 9738 // }, 100); 9739 9740 // setTimeout(() => { 9741 // clearInterval(checkToken); 9742 // reject(new Error('ТаймаÑÑ ÐºÐ°Ð¿Ñи')); 9743 // }, 100000); 9744 // }); 9745 9746 // // console.log('â Токен полÑÑен:', captchaToken); 9747 // } else { 9748 // // console.log('â ÐапÑа Ñже пÑойдена, пÑопÑÑкаем пÑовеÑкÑ'); 9749 // } 9750 9751 9752 // if (captchaToken) { 9753 9754 9755 // console.log(globalForm); 9756 isSubmitting = true; 9757 // console.log('ÐÑпÑавка ÑоÑмÑ:', review); 9758 9759 const dataRequest = form.getAttribute('data-request'); 9760 const formData = new FormData(form); 9761 const formObject = {}; 9762 formData.forEach((value, key) => { 9763 formObject[key] = value; 9764 }); 9765 formObject['smart-token'] = captchaToken; 9766 9767 //formObject.captcha_token = captchaToken; 9768 9769 $.request('MainFunctions::' + dataRequest, { 9770 data: formObject, 9771 success: function(response) { 9772 // console.log('ÐÑвеÑ:', response); 9773 let hasErrors = false; 9774 9775 for (let key in response) { 9776 if (key.startsWith('.')) { 9777 const className = key.substring(1); 9778 const element = document.querySelector('.' + className); 9779 9780 if (element) { 9781 element.innerHTML = response[key]; 9782 hasErrors = true; 9783 btnSubmit.disabled = false; 9784 } 9785 } 9786 } 9787 9788 if (hasErrors) { 9789 isSubmitting = false;
9790 return; 9791 } else { 9792 afterSuccessSubmit() 9793 } 9794 }, 9795 error: function(error) { 9796 // console.error('â ÐÑибка оÑпÑавки:', error); 9797 isSubmitting = false; 9798 } 9799 }); 9800 9801 return false; 9802 // }else{ 9803 // return false; 9804 // } 9805 9806 } catch (error) { 9807 // console.error('â ÐÑибка:', error); 9808 // alert('ÐÑибка пÑовеÑки капÑи'); 9809 return false; 9810 } 9811 9812 function checkHoneypot() { 9813 const honeypots = form.querySelector('.modal-exter__input') 9814 return honeypots && honeypots?.value 9815 } 9816 } 9817 9818 function validateFirstSlide () { 9819 let valid = true 9820 const roleInputActive = slides[0].querySelector('.review__role-input:checked') 9821 if (!roleInputActive) { 9822 valid = false 9823 role.classList.add('review-error') 9824 } 9825 if (!nameInput.value) { 9826 nameInput.classList.add('review-error') 9827 valid = false 9828 } 9829 if (!surnameInput.value) { 9830 surnameInput.classList.add('review-error') 9831 valid = false 9832 } 9833 if (!validateEmail(emailInput)) { 9834 valid = false 9835 } 9836 const selectClassValue = slides[0].querySelector('.review__select-input:checked') 9837 if (!selectClassValue) { 9838 valid = false 9839 selectClass.classList.add('review-error') 9840 } 9841 return valid 9842 } 9843 9844 function validateSecondSlide () { 9845 let valid = true 9846 if (!inputRate.value) { 9847 valid = false 9848 rateDesktop.classList.add('review-error') 9849 } 9850 for (let i = 0; i < selectsOnSecondSlide.length; i++) { 9851 const input = selectsOnSecondSlide[i].querySelector('.review__select-input:checked') 9852 if (!input) { 9853 valid = false 9854 selectsOnSecondSlide[i].classList.add('review-error') 9855 } 9856 } 9857 return valid 9858 } 9859 9860 function nextSlide () { 9861 if (!validateFirstSlide()) return 9862 steps[1].classList.add('active') 9863 steps[0].classList.add('done') 9864 const oldSlide = review.querySelector('.review__slide.active') 9865 if (oldSlide) oldSlide.classList.remove('active') 9866 slides[1].classList.add('active') 9867 window.scrollTo(0, 0) 9868 } 9869 9870 function prevSlide () { 9871 steps[1].classList.remove('active') 9872 steps[0].classList.remove('done') 9873 const oldSlide = review.querySelector('.review__slide.active') 9874 if (oldSlide) oldSlide.classList.remove('active') 9875 slides[0].classList.add('active') 9876 window.scrollTo(0, 0) 9877 } 9878 9879 for (let i = 0; i < selectTops.length; i += 1) { 9880 selectTops[i].addEventListener('click', () => openSelect(selectTops[i])) 9881 const inputs = selectTops[i].parentElement.querySelectorAll('.review__select-input') 9882 inputs.forEach(input => { 9883 input.addEventListener('change', () => setSelectValue(selectTops[i])) 9884 }) 9885 const selectClose = selectTops[i].parentElement.querySelector('.review__select-close') 9886 selectClose.addEventListener('click', () => closeSelect(selectTops[i])) 9887 } 9888 9889 window.addEventListener('click', function (e) { 9890 if (e.target.closest('.review__select')) return 9891 const activeSelect = review.querySelector('.review__select.active') 9892 if (activeSelect) activeSelect.classList.remove('active') 9893 const activeSelectTop = review.querySelector('.review__select-top.active') 9894 if (activeSelectTop) activeSelectTop.classList.remove('active') 9895 body.classList.remove('no-scroll-mob') 9896 }) 9897 9898 function openSelect(that) { 9899 if (!that.classList.contains('active')) { 9900 const activeSelect = review.querySelector('.review__select.active') 9901 if (activeSelect) activeSelect.classList.remove('active') 9902 const activeSelectTop = review.querySelector('.review__select-top.active') 9903 if (activeSelectTop) activeSelectTop.classList.remove('active') 9904 } 9905 9906 if (that.parentElement.classList.contains('review__select_tutor') || that.parentElement.classList.contains('review__select_teacher')) { 9907 that.classList.add('active') 9908 that.parentElement.classList.add('active') 9909 } else { 9910 that.classList.toggle('active') 9911 that.parentElement.classList.toggle('active') 9912 } 9913 body.classList.add('no-scroll-mob') 9914 } 9915 9916 function closeSelect(selectTop) { 9917 selectTop.classList.remove('active') 9918 selectTop.parentElement.classList.remove('active') 9919 body.classList.remove('no-scroll-mob') 9920 } 9921 9922 function setSelectValue (selectTop) { 9923 closeSelect(selectTop) 9924 const selectText = selectTop.querySelector('.review__select-top-text') 9925 selectText.classList.add('active') 9926 const text = selectTop.parentElement.querySelector('input:checked').getAttribute('data-text') 9927 if (selectText) selectText.innerHTML = text 9928 const selectSearch = selectTop.querySelector('.review__select-search') 9929 if (selectSearch) { 9930 selectSearch.value = text 9931 const reviewSearchMob = selectTop.closest('.review__select').querySelector('.review__search-mob') 9932 if (reviewSearchMob) reviewSearchMob.value = text 9933 selectSort(selectSearch) 9934 subjectsFilter(selectSearch) 9935 boxSubject.classList.remove('review__box_disabled') 9936 } 9937 if (selectTop.parentElement.classList.contains('review__select_teacher')) { 9938 const name = review.querySelector('.review__sidebar-teacher-name') 9939 if (name) name.innerHTML = text 9940 const image = review.querySelector('.review__sidebar-teacher-image') 9941 const imageSrc = selectTop.parentElement.querySelector('input:checked').getAttribute('data-image') 9942 if (image && imageSrc) image.src = imageSrc 9943 const sidebarTeacher = review.querySelector('.review__sidebar-teacher') 9944 if (sidebarTeacher) { 9945 const sidebar = sidebarTeacher.parentElement.querySelector('.review__sidebar') 9946 if (sidebar) { 9947 sidebar.classList.add('hide') 9948 sidebarTeacher.classList.add('active') 9949 } 9950 } 9951 } 9952 } 9953} 9954 9955 9956const reviewsTile = document.querySelector('.reviews-tile') 9957 9958if (reviewsTile) reviewsTileInit() 9959 9960function reviewsTileInit () { 9961 const config = { attributes: false, childList: true, characterData: true, subtree: false } 9962 const body = document.querySelector('body') 9963 const sidebar = reviewsTile.querySelector('.reviews-tile__sidebar') 9964 const openFilterBtn = reviewsTile.querySelector('.reviews-tile__filter') 9965 const closeFilterBtn = reviewsTile.querySelector('.reviews-tile__close') 9966 const inputs = reviewsTile.querySelectorAll('.reviews-tile__input') 9967 const filterNote = reviewsTile.querySelector('.reviews-tile__filter-note') 9968 const scrollTopBtn = document.querySelector('.reviews-tile__scroll-top') 9969 const reviewsTileCards = document.querySelector('.reviews-tile__cards') 9970 9971 openFilterBtn.addEventListener('click', openFilters) 9972 closeFilterBtn.addEventListener('click', closeFilters) 9973 9974 function openFilters () { 9975 sidebar.classList.add('active') 9976 body.classList.add('no-scroll') 9977 } 9978 9979 function closeFilters () { 9980 sidebar.classList.remove('active') 9981 body.classList.remove('no-scroll') 9982 } 9983 9984 function textsInit (node) { 9985 let texts 9986 if (node) { 9987 texts = node.querySelectorAll('.reviews-tile__text') 9988 } else { 9989 texts = document.querySelectorAll('.reviews-tile__text') 9990 } 9991 9992 9993 for (let i = 0; i < texts.length; i++) { 9994 const toggle = texts[i].parentElement.querySelector('.reviews-tile__toggle') 9995 if ((texts[i].clientHeight - 230) > 40 && window.innerWidth >= 1440 || (texts[i].clientHeight - 190) > 40 && window.innerWidth >= 744 && window.innerWidth < 1440 || (texts[i].clientHeight - 350) > 40 && window.innerWidth < 744) { 9996 texts[i].classList.add('hide') 9997 toggle.addEventListener('click', () => toggleText(texts[i])) 9998 } else { 9999 toggle.style.display = 'none' 10000 } 10001 } 10002 10003 function toggleText (text) { 10004 const toggle = text.parentElement.querySelector('.reviews-tile__toggle') 10005 if (text.classList.contains('hide')) { 10006 text.classList.remove('hide') 10007 toggle.innerHTML = 'СкÑÑÑÑ' 10008 } else { 10009 text.classList.add('hide') 10010 toggle.innerHTML = 'ÐоказаÑÑ Ð¿Ð¾Ð»Ð½Ð¾ÑÑÑÑ' 10011 } 10012 } 10013 } 10014 10015 for (let i = 0; i < inputs.length; i++) { 10016 inputs[i].addEventListener('change', sort) 10017 inputs[i].addEventListener('change', (e) => sort(e)) 10018 } 10019 10020 async function makeFiltration (attr_type = '', attr_utm = '',p_paginate = 1) { 10021 if (typeof attr_type !== 'undefined' && attr_type !== false && 10022 typeof attr_utm !== 'undefined' && attr_utm !== false) { 10023 if (typeof p_paginate == 'undefined' || p_paginate == false || p_paginate == null){ 10024 p_paginate = 1; 10025 }
10026 console.log(attr_type); 10027 console.log(attr_utm); 10028 console.log(p_paginate); 10029 $.request('ModelUrl::onPaginateR', { 10030 data: { 10031 'pagePaginate': p_paginate, 10032 'utm_t': attr_utm, 10033 'type': attr_type, 10034 } 10035 }); 10036 } 10037 } 10038 10039 function sort (e, isMoreBtn) { 10040 closeFilters() 10041 if (!isMoreBtn) { 10042 window.scrollTo({ top: window.scrollY + reviewsTile.getBoundingClientRect().top - 180, behavior: 'smooth' }) 10043 filterNote.innerHTML = e.currentTarget.value 10044 } 10045 let utm_f = reviewsTile.getAttribute('data-utm'); 10046 let attr_type = e.currentTarget.getAttribute('data-value'); 10047 let p_paginate = e.currentTarget.getAttribute('data-v'); 10048 if(p_paginate > 1){ 10049 $('.review___more_pagi').html("<div class='tile-loader'></div>"); 10050 }else{ 10051 $('.review___catalog_pagi').html("<div class='tile-loader'></div>"); 10052 $('.review___more_pagi').html(""); 10053 } 10054 makeFiltration (attr_type, utm_f, p_paginate); 10055 10056 } 10057 10058 function moreBtnInit () { 10059 const moreBtn = reviewsTile.querySelector('.reviews-tile__more') 10060 if (moreBtn) { 10061 const newBtn = replaceBtn(moreBtn) 10062 newBtn.addEventListener('click', (e) => sort(e, true)) 10063 } 10064 } 10065 10066 function replaceBtn (oldElement) { 10067 const newElement = oldElement.cloneNode(true) 10068 oldElement.parentNode.replaceChild(newElement, oldElement) 10069 return newElement 10070 } 10071 10072 10073 videoInit() 10074 textsInit() 10075 moreBtnInit() 10076 10077 const observer = new MutationObserver(function observerCallback(mutations) { 10078 mutations.forEach( 10079 (mutation) => { 10080 if (mutation.addedNodes.length) { 10081 mutation.addedNodes.forEach((node) => { 10082 if (node?.classList?.contains('reviews-tile__card')) { 10083 videoInit(node) 10084 textsInit(node) 10085 fancyboxAjaxCardsReInit(node) 10086 initCommonAnalytics(node) 10087 10088 } 10089 }) 10090 } 10091 }) 10092 moreBtnInit() 10093 }) 10094 10095 observer.observe(reviewsTileCards, config) 10096 10097 function videoInit (node) { 10098 let videoBoxes 10099 if (node) { 10100 videoBoxes = node.querySelectorAll('.reviews-tile__video-box') 10101 } else { 10102 videoBoxes = reviewsTile.querySelectorAll('.reviews-tile__video-box') 10103 } 10104 10105 10106 for (let i = 0; i < videoBoxes.length; i++) { 10107 videoBoxes[i].addEventListener('click', playVideo) 10108 } 10109 10110 function playVideo () { 10111 const oldActive = reviewsTile.querySelector('.reviews-tile__video-box.active') 10112 if (oldActive) { 10113 const video = oldActive.parentElement.querySelector('video') 10114 oldActive.classList.remove('active') 10115 video.pause() 10116 } 10117 this.classList.add('active') 10118 const video = this.parentElement.querySelector('video') 10119 if (video) { 10120 video.play() 10121 } 10122 } 10123 } 10124 10125 if (scrollTopBtn) { 10126 scrollTopBtn.addEventListener('click', () => window.scrollTo({ top: 0, behavior: 'smooth' })) 10127 window.addEventListener('scroll', toggleAllCoursesTop, { passive: true }) 10128 10129 function toggleAllCoursesTop () { 10130 if (window.scrollY > 0) { 10131 scrollTopBtn.classList.add('active') 10132 } else { 10133 scrollTopBtn.classList.remove('active') 10134 } 10135 } 10136 } 10137} 10138 10139const reviewsSlider = document.querySelector('.reviews__slider') 10140 10141if (reviewsSlider) reviewsSliderInit() 10142 10143function reviewsSliderInit () { 10144 const body = document.querySelector('body') 10145 10146 const videos = reviewsSlider.querySelectorAll('.reviews__video') 10147 10148 for (let i = 0; i < videos.length; i++) { 10149 initVideo(videos[i]) 10150 } 10151 10152 window.addEventListener('resize', resizeHandler) 10153 10154 function resizeHandler () { 10155 if (window.innerWidth >= 1359) { 10156 for (let i = 0; i < videos.length; i++) { 10157 videos[i].pause() 10158 } 10159 } 10160 } 10161 10162 function initVideo (video) { 10163 const box = video.closest('.reviews__video-box') 10164 box.addEventListener('click', videoHandler) 10165 10166 const videoSrc = box.getAttribute('data-src') 10167 const videoHtml = 10168 '<video class="fancybox-video" controls autoplay playsinline ' + 10169 'webkit-playsinline disablePictureInPicture controlsList="nofullscreen">' + 10170 '<source src="' + videoSrc + '" type="video/mp4" />' + 10171 'ÐÐ°Ñ Ð±ÑаÑÐ·ÐµÑ Ð½Ðµ поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð²ÑÑÑоенное видео.' + 10172 '</video>'; 10173 10174 function videoHandler (e) { 10175 if (window.innerWidth >= 1359) { 10176 $.fancybox.open({ 10177 src: videoHtml, 10178 type: 'html', 10179 scrolling: 'no', 10180 touch: false, 10181 autoSize: false, 10182 smallBtn: false, 10183 toolbar: true, 10184 buttons: ['close'], 10185 }) 10186 } else { 10187 e.preventDefault() 10188 e.stopPropagation() 10189 e.stopImmediatePropagation() 10190 playVideo() 10191 } 10192 } 10193 10194 function playVideo () { 10195 const oldBox = reviewsSlider.querySelector('.reviews__video-box.active') 10196 if (oldBox) { 10197 const oldVideo = oldBox.querySelector('.reviews__video') 10198 if (oldVideo) oldVideo.pause() 10199 oldBox.classList.remove('active') 10200 } 10201 video.play() 10202 box.classList.add('active') 10203 } 10204 } 10205 10206 10207 const inners = reviewsSlider.querySelectorAll('.reviews__slide') 10208 10209 for (let i = 0; i < inners.length; i++) { 10210 initInner(inners[i]) 10211 } 10212 10213 function initInner (inner) { 10214 const btn = inner.querySelector('.reviews__toggle') 10215 10216 if (inner.clientHeight > 285 && window.innerWidth >= 1359 || inner.clientHeight > 232 && window.innerWidth < 1440) { 10217 inner.classList.add('hide') 10218 btn?.addEventListener('click', toggle) 10219 } else { 10220 btn?.remove() 10221 } 10222 10223 function toggle () { 10224 if (inner.classList.contains('hide')) { 10225 inner.classList.remove('hide') 10226 btn.innerHTML = 'СкÑÑÑÑ' 10227 inner.classList.add('show') 10228 if (window.innerWidth >= 744) createModal(inner, btn) 10229 } else { 10230 inner.classList.add('hide') 10231 btn.innerHTML = 'ЧиÑаÑÑ Ð²ÐµÑÑ Ð¾ÑзÑв' 10232 inner.classList.remove('show') 10233 } 10234 } 10235 10236 function createModal(innerOld) { 10237 const slide = innerOld.closest('.reviews__slide') 10238 const imageOld = slide.querySelector('.reviews__image') 10239 const textOld = slide.querySelector('.reviews__text') 10240 const nameOld = slide.querySelector('.reviews__name') 10241 const noteOld = slide.querySelector('.reviews__note') 10242 const starsOld = slide.querySelector('.reviews__stars') 10243 10244 const modal = document.createElement('div') 10245 modal.classList.add('review-modal') 10246 10247 const layer = document.createElement('div') 10248 layer.classList.add('review-modal__layer') 10249 10250 const inner = document.createElement('div') 10251 inner.classList.add('review-modal__inner') 10252 10253 const close = document.createElement('button') 10254 close.classList.add('review-modal__close') 10255 10256 const left = document.createElement('div') 10257 left.classList.add('review-modal__left') 10258 10259 const box = document.createElement('div') 10260 box.classList.add('review-modal__box') 10261 10262 const image = document.createElement('img') 10263 image.classList.add('review-modal__image') 10264 10265 const name = document.createElement('div') 10266 name.classList.add('review-modal__name') 10267 10268 const note = document.createElement('div') 10269 note.classList.add('review-modal__note') 10270 10271 const right = document.createElement('div') 10272 right.classList.add('review-modal__right') 10273 10274 const text = document.createElement('div') 10275 text.classList.add('review-modal__text') 10276 10277 const stars = document.createElement('div') 10278 stars.classList.add('reviews__stars') 10279 10280 image.src = imageOld.src 10281 10282 box.append(name) 10283 box.append(note) 10284 box.append(stars) 10285 name.innerHTML = nameOld.innerHTML 10286 note.innerHTML = noteOld.innerHTML 10287 stars.innerHTML = starsOld.innerHTML 10288 left.append(image) 10289 left.append(box) 10290 text.innerHTML = textOld.innerHTML 10291 right.append(text) 10292 inner.append(close) 10293 inner.append(left) 10294 inner.append(right) 10295 modal.append(layer) 10296 modal.append(inner) 10297 10298 layer.addEventListener('click', closeModal) 10299 close.addEventListener('click', closeModal) 10300 10301 const main = document.querySelector('main') 10302 main.append(modal) 10303 10304 body.classList.add('no-scroll-desktop') 10305 10306 function closeModal () { 10307 modal.remove() 10308 innerOld.classList.add('hide') 10309 btn.innerHTML = 'ЧиÑаÑÑ Ð²ÐµÑÑ Ð¾ÑзÑв' 10310 innerOld.classList.remove('show') 10311 body.classList.remove('no-scroll-desktop') 10312 } 10313 } 10314 } 10315 10316} 10317 10318 10319const reviewSo2026 = document.querySelector('.review_so-2026') 10320 10321if (reviewSo2026) reviewSo2026Init() 10322 10323function reviewSo2026Init () { 10324 const textReplace = { 10325 parent: [ 10326 { selector: '.review__caption_thanks-1', text: 'СпаÑибо, ÑÑо поделилиÑÑ Ð¾Ð¿ÑÑом!' }, 10327 { selector: '.review__caption_thanks-2', text: 'СпаÑибо за Ð²Ð°Ñ Ð¾ÑзÑв!' }, 10328 { selector: '.review__headline-thanks-1', text: 'ÐайÑе ваÑÐµÐ¼Ñ Ð¼Ð½ÐµÐ½Ð¸Ñ ÑеалÑнÑÑ ÑилÑ' }, 10329 { selector: '.review__thanks-title', text: 'ÐÐ°Ñ Ð¾ÑзÑв â оÑиенÑÐ¸Ñ Ð´Ð»Ñ Ð´ÑÑÐ³Ð¸Ñ ÑодиÑелей.' }, 10330 { selector: '.review__thanks-text_1', text: 'Ðногие ÑодиÑели ÑейÑÐ°Ñ Ð¸ÑÑÑ ÑеÑÑнÑе оÑзÑвÑ, ÑÑÐ¾Ð±Ñ ÑделаÑÑ Ð²ÑÐ±Ð¾Ñ Ð´Ð»Ñ Ñвоего Ñебенка.' }, 10331 // { selector: '.review__thanks-text_2', text: 'ÐÐ°Ñ Ð¾ÑзÑв на <a href="https://www.rbc.ru/courses/school-reviews/tocka-znanii" data-redirect>
10331Ð ÐÐ</a> ÑÑÐ°Ð½ÐµÑ Ð´Ð»Ñ Ð½Ð¸Ñ Ð²ÐµÑомÑм аÑгÑменÑом, коÑоÑÑй ÑÑÐºÐ¾Ð½Ð¾Ð¼Ð¸Ñ Ð²ÑемÑ, денÑги и неÑвÑ.' }, 10332 { selector: '.review__thanks-text_2', text: 'ÐÐ°Ñ Ð¾ÑзÑв на ÐÑзовике ÑÑÐ°Ð½ÐµÑ Ð´Ð»Ñ Ð½Ð¸Ñ Ð²ÐµÑомÑм аÑгÑменÑом, коÑоÑÑй ÑÑÐºÐ¾Ð½Ð¾Ð¼Ð¸Ñ Ð²ÑемÑ, денÑги и неÑвÑ.' }, 10333 // { selector: '.review__thanks-headline_1', text: 'ÐожалÑйÑÑа, добавÑÑе Ñвой оÑзÑв на Ð ÐÐ.' }, 10334 { selector: '.review__thanks-headline_1', text: 'ÐожалÑйÑÑа, добавÑÑе Ñвой оÑзÑв на ÐÑзовик.' }, 10335 { selector: '.review__thanks-headline_2', text: 'ÐÑо займÑÑ 2 минÑÑÑ. ÐÑÑÑÑ Ð²Ð°Ñ Ð³Ð¾Ð»Ð¾Ñ Ð¿Ð¾Ð¼Ð¾Ð¶ÐµÑ Ñ Ð²ÑбоÑом и ÑÑÐ°Ð½ÐµÑ Ð¾ÑиенÑиÑом.' }, 10336 { selector: '.review__thanks-headline_3', text: 'ÐÑÑавÑÑе оÑзÑв и помогиÑе дÑÑгим ÑодиÑелÑм!' }, 10337 { selector: '.review__thanks-2-title', text: 'ÐÑли Ð²Ñ Ñ Ð¾ÑиÑе оÑÑавиÑÑ Ð¾ÑзÑв на дÑÑÐ³Ð¸Ñ ÑÑиÑелей или ÑÑÑÑоÑов, нажмиÑе на кнопки ниже' }, 10338 ], 10339 student: [ 10340 { selector: '.review__caption_thanks-1', text: 'СпаÑибо, ÑÑо делиÑÑÑÑ Ð¾Ð¿ÑÑом!' }, 10341 { selector: '.review__caption_thanks-2', text: 'СпаÑибо за Ñвой оÑзÑв!' }, 10342 { selector: '.review__headline-thanks-1', text: 'ÐайÑе ÑÐ²Ð¾ÐµÐ¼Ñ Ð¼Ð½ÐµÐ½Ð¸Ñ ÑеалÑнÑÑ ÑилÑ' }, 10343 { selector: '.review__thanks-title', text: 'Твой оÑзÑв â оÑиенÑÐ¸Ñ Ð´Ð»Ñ Ð´ÑÑÐ³Ð¸Ñ ÑÑеников.' }, 10344 { selector: '.review__thanks-text_1', text: 'ÐовиÑкам онлайн-обÑÑÐµÐ½Ð¸Ñ Ñоже бÑÐ²Ð°ÐµÑ ÑÑÑдно: кÑо-Ñо боиÑÑÑ Ð½ÐµÐ¿Ð¾Ð½ÑÑнÑÑ Ñем, Ñложной домаÑки или оÑÑаÑÑÑÑ Ð±ÐµÐ· поддеÑжки ÑÑиÑелей.' }, 10345 { selector: '.review__thanks-text_2', text: 'Твой оÑзÑв Ð¿Ð¾Ð¼Ð¾Ð¶ÐµÑ Ð¸Ð¼ понÑÑÑ, ÑÑо ÑÑÑдноÑÑи ÑеÑÐ°ÐµÐ¼Ñ Ð¸ поддеÑжка ÑÑдом. ÐлагодаÑÑ Ñебе дÑÑгие ÑебÑÑа ÑмогÑÑ ÑделаÑÑ ÑвеÑеннÑй вÑбоÑ' }, 10346 // { selector: '.review__thanks-headline_1', text: 'ÐожалÑйÑÑа, Ð´Ð¾Ð±Ð°Ð²Ñ Ñвой оÑзÑв на Ð ÐÐ.' }, 10347 { selector: '.review__thanks-headline_1', text: 'ÐожалÑйÑÑа, Ð´Ð¾Ð±Ð°Ð²Ñ Ñвой оÑзÑв на ÐÑзовик.' }, 10348 { selector: '.review__thanks-headline_2', text: 'ÐÑо займÑÑ 2 минÑÑÑ.' }, 10349 { selector: '.review__thanks-headline_3', text: 'ÐÑÑÐ°Ð²Ñ Ð¾ÑзÑв и помоги дÑÑгим ÑколÑникам!' }, 10350 { selector: '.review__thanks-2-title', text: 'ÐÑли ÑÑ Ñ Ð¾ÑеÑÑ Ð¾ÑÑавиÑÑ Ð¾ÑзÑв на дÑÑÐ³Ð¸Ñ ÑÑиÑелей или ÑÑÑÑоÑов, нажми на кнопки ниже' }, 10351 ] 10352 } 10353 10354 const form = reviewSo2026.querySelector('.review__form') 10355 const slides = reviewSo2026.querySelectorAll('.review__slide') 10356 const steps = reviewSo2026.querySelectorAll('.review__step') 10357 const buttonsNext = reviewSo2026.querySelectorAll('.review__button') 10358 const buttonsBack = reviewSo2026.querySelectorAll('.review__back') 10359 const buttonsMobBack = reviewSo2026.querySelectorAll('.review__mob-back') 10360 const nameInput = reviewSo2026.querySelector("[name='st_name']") 10361 const surnameInput = reviewSo2026.querySelector("[name='st_surname']") 10362 const emailInput = reviewSo2026.querySelector("[name='email']") 10363 const btnSubmit = form.querySelector('.review__submit') 10364 const role = reviewSo2026.querySelector('.review__role') 10365 const roleInputs = reviewSo2026.querySelectorAll('.review__role-input') 10366 const head_1 = reviewSo2026.querySelector('.review__thanks-headline_1') 10367 const head_2 = reviewSo2026.querySelector('.review__thanks-headline_2') 10368 const textarea = reviewSo2026.querySelector('.review__textarea') 10369 const siteButton = reviewSo2026.querySelector('.review__thanks-site-button') 10370 const selectClass = reviewSo2026.querySelector(".review__select_class") 10371 const selectTops = reviewSo2026.querySelectorAll('.review__select-top') 10372 const body = document.querySelector('body') 10373 const selectClassInputs = selectClass.querySelectorAll(".review__select-input") 10374 const rateInputs = reviewSo2026.querySelectorAll(".review__rate-desktop-input") 10375 10376 let currentSlide = 0 10377 let isSubmitting = false;
10378 10379 for (let i = 0; i < selectClassInputs.length; i++) { 10380 selectClassInputs[i].addEventListener('change', function () { 10381 selectClass.classList.remove('review-error') 10382 }) 10383 } 10384 10385 rateInputs.forEach( rateInput => { 10386 rateInput.addEventListener('change', function () { 10387 this.closest('.review__rate-so')?.classList.remove('review__rate-so_error') 10388 }) 10389 }) 10390 10391 10392 nameInput.addEventListener('input', () => nameInput.classList.remove('review-error')) 10393 surnameInput.addEventListener('input', () => surnameInput.classList.remove('review-error')) 10394 emailInput.addEventListener('input', () => emailInput.classList.remove('review-error')) 10395 10396 form.addEventListener('submit', submitForm) 10397 10398 buttonsNext.forEach(buttonNext => { 10399 buttonNext.addEventListener('click', nextSlide) 10400 }) 10401 buttonsBack.forEach(buttonBack => { 10402 buttonBack.addEventListener('click', prevSlide) 10403 }) 10404 buttonsMobBack.forEach(buttonMobBack => { 10405 buttonMobBack.addEventListener('click', prevSlide) 10406 }) 10407 10408 siteButton.addEventListener('click', showLastSlideThanks) 10409 10410 for (let i = 0; i < roleInputs.length; i++) { 10411 roleInputs[i].addEventListener('change', () => { 10412 role.classList.remove('review-error') 10413 const value = reviewSo2026.querySelector('.review__role-input:checked')?.value 10414 replaceTexts(value) 10415 }) 10416 } 10417 10418 function replaceTexts(value) { 10419 if (value === 'student') { 10420 reviewSo2026.classList.add('review_student') 10421 } else { 10422 reviewSo2026.classList.remove('review_student') 10423 } 10424 textReplace[value].forEach((item) => { 10425 const node = reviewSo2026.querySelector(item.selector) 10426 node.innerHTML = item.text 10427 const dataRedirectLinks = node.querySelectorAll('[data-redirect]') 10428 for (let i = 0; i < dataRedirectLinks.length; i++) { 10429 dataRedirectLinks[i].addEventListener('click', dataRedirect) 10430 } 10431 }) 10432 } 10433 10434 function validateFirstSlide () { 10435 let valid = true 10436 const roleInputActive = slides[0].querySelector('.review__role-input:checked') 10437 if (!roleInputActive) { 10438 valid = false 10439 role.classList.add('review-error') 10440 } 10441 if (!nameInput.value) { 10442 nameInput.classList.add('review-error') 10443 valid = false 10444 } 10445 if (!surnameInput.value) { 10446 surnameInput.classList.add('review-error') 10447 valid = false 10448 } 10449 if (!validateEmail(emailInput)) { 10450 valid = false 10451 } 10452 const selectClassValue = slides[0].querySelector('.review__select-input:checked') 10453 if (!selectClassValue) { 10454 valid = false 10455 selectClass.classList.add('review-error') 10456 } 10457 return valid 10458 } 10459 10460 function validateEmail (email) { 10461 if (/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(email.value)) { 10462 email.classList.remove('review-error') 10463 return true 10464 } else { 10465 email.classList.add('review-error') 10466 return false 10467 } 10468 } 10469 10470 function nextSlide () { 10471 if (!validateFirstSlide()) return 10472 if (currentSlide > 0 && !slides[currentSlide].querySelector('input:checked')) { 10473 slides[currentSlide].querySelector('.review__rate-so')?.classList.add('review__rate-so_error') 10474 return 10475 } 10476 currentSlide += 1 10477 steps[currentSlide].classList.add('active') 10478 steps[currentSlide-1].classList.add('done') 10479 const oldSlide = reviewSo2026.querySelector('.review__slide.active') 10480 if (oldSlide) oldSlide.classList.remove('active') 10481 slides[currentSlide].classList.add('active') 10482 window.scrollTo(0, 0) 10483 } 10484 10485 function prevSlide () { 10486 currentSlide -= 1 10487 steps[currentSlide+1].classList.remove('active') 10488 steps[currentSlide].classList.remove('done') 10489 const oldSlide = reviewSo2026.querySelector('.review__slide.active') 10490 if (oldSlide) oldSlide.classList.remove('active') 10491 slides[currentSlide].classList.add('active') 10492 window.scrollTo(0, 0) 10493 } 10494 10495 async function submitForm (e) { 10496 e.preventDefault() 10497 const email = form.querySelector('[name="email"]') 10498 if (email) { 10499 email_value = email.value; 10500 } 10501 10502 btnSubmit.disabled = true; 10503 10504 if (checkHoneypot()) return 10505 10506 try { 10507 e.stopPropagation(); 10508 console.log('isSubmitting:', isSubmitting); 10509 if (isSubmitting) return false;
10510 10511 // if (!captchaPassed) { 10512 // // console.log('ð ÐÑзов execute...'); 10513 captchaToken = null; 10514 // window.smartCaptcha.execute(window.captchaWidget); 10515 10516 // await new Promise((resolve, reject) => { 10517 // const checkToken = setInterval(() => { 10518 // if (captchaToken) { 10519 // clearInterval(checkToken); 10520 // resolve(); 10521 // } 10522 // }, 100); 10523 10524 // setTimeout(() => { 10525 // clearInterval(checkToken); 10526 // reject(new Error('ТаймаÑÑ ÐºÐ°Ð¿Ñи')); 10527 // }, 100000); 10528 // }); 10529 10530 // // console.log('â Токен полÑÑен:', captchaToken); 10531 // } else { 10532 // // console.log('â ÐапÑа Ñже пÑойдена, пÑопÑÑкаем пÑовеÑкÑ'); 10533 // } 10534 10535 10536 // if (captchaToken) { 10537 10538 10539 // console.log(globalForm); 10540 isSubmitting = true; 10541 // console.log('ÐÑпÑавка ÑоÑмÑ:', review); 10542 10543 const dataRequest = form.getAttribute('data-request'); 10544 const formData = new FormData(form); 10545 const formObject = {}; 10546 formData.forEach((value, key) => { 10547 formObject[key] = value; 10548 }); 10549 formObject['smart-token'] = captchaToken; 10550 10551 //formObject.captcha_token = captchaToken; 10552 10553 $.request('MainFunctions::' + dataRequest, { 10554 data: formObject, 10555 success: function(response) { 10556 // console.log('ÐÑвеÑ:', response); 10557 let hasErrors = false; 10558 10559 for (let key in response) { 10560 if (key.startsWith('.')) { 10561 const className = key.substring(1); 10562 const element = document.querySelector('.' + className); 10563 10564 if (element) { 10565 element.innerHTML = response[key]; 10566 hasErrors = true; 10567 btnSubmit.disabled = false; 10568 } 10569 } 10570 } 10571 10572 if (hasErrors) { 10573 isSubmitting = false; 10574 return; 10575 } else { 10576 afterSuccessSubmit() 10577 } 10578 }, 10579 error: function(error) { 10580 // console.error('â ÐÑибка оÑпÑавки:', error); 10581 isSubmitting = false; 10582 } 10583 }); 10584 10585 return false; 10586 // }else{ 10587 // return false; 10588 // } 10589 10590 } catch (error) { 10591 // console.error('â ÐÑибка:', error); 10592 // alert('ÐÑибка пÑовеÑки капÑи'); 10593 return false; 10594 } 10595 10596 function checkHoneypot() { 10597 const honeypots = form.querySelector('.modal-exter__input') 10598 return honeypots && honeypots?.value 10599 } 10600 } 10601 10602 function afterSuccessSubmit () { 10603 const oldSlide = reviewSo2026.querySelector('.review__slide.active') 10604 if (oldSlide) oldSlide.classList.remove('active') 10605 if (role.querySelector('input:checked')?.value === 'parent') { 10606 slides[6].classList.add('active') 10607 reviewSo2026.classList.add('review_thanks-1') 10608 if (!textarea.value) { 10609 head_1.style.display = 'none' 10610 head_2.style.display = 'none' 10611 } else { 10612 head_1.style.display = 'block' 10613 head_2.style.display = 'block' 10614 } 10615 } else { 10616 slides[6].classList.add('active') 10617 steps[5].classList.add('done') 10618 reviewSo2026.classList.add('review_thanks-2') 10619 } 10620 steps[5].classList.add('done') 10621 steps[6].classList.add('active') 10622 window.scrollTo(0, 0) 10623 if (!isRateGood()) showLastSlideThanks() 10624 } 10625 10626 function isRateGood () { 10627 const rateChecked = reviewSo2026.querySelectorAll(".review__rate-desktop-input:checked") 10628 let result = true 10629 rateChecked.forEach(rate => { 10630 if (rate.value < 9) { 10631 result = false 10632 } 10633 }) 10634 return result 10635 } 10636 10637 10638 function showLastSlideThanks () { 10639 steps[6].classList.add('done') 10640 window.scrollTo(0, 0) 10641 const oldSlide = reviewSo2026.querySelector('.review__slide.active') 10642 if (oldSlide) oldSlide.classList.remove('active') 10643 const title = reviewSo2026.querySelector('.review__thanks-2-title') 10644 const headline_thanks_1 = reviewSo2026.querySelector('.review__headline-thanks-1') 10645 const caption_thanks_1 = reviewSo2026.querySelector('.review__caption_thanks-1') 10646 const caption_thanks_2 = reviewSo2026.querySelector('.review__caption_thanks-2') 10647 slides[7].classList.add('active') 10648 if (role.querySelector('input:checked')?.value === 'parent') { 10649 title.innerHTML = 'ÐÑли Ð²Ñ Ñ Ð¾ÑиÑе оÑÑавиÑÑ Ð¾ÑзÑв на дÑÑÐ³Ð¸Ñ ÑÑиÑелей или ÑÑÑÑоÑов, нажмиÑе на кнопки ниже' 10650 headline_thanks_1.innerHTML = '<span>Ðаждое мнение Ð´Ð°ÐµÑ Ð½Ð°Ð¼ ÑÑимÑл двигаÑÑÑÑ Ð´Ð°Ð»ÑÑе и ÑазвиваÑÑÑÑ.</span> <span>ÐÑ Ð±Ñдем пÑодолжаÑÑ ÑабоÑаÑÑ Ð½Ð°Ð´ каÑеÑÑвом наÑÐ¸Ñ ÐºÑÑÑов!</span>' 10651 } else { 10652 title.innerHTML = 'ÐÑли ÑÑ Ñ Ð¾ÑеÑÑ Ð¾ÑÑавиÑÑ Ð¾ÑзÑв на ÑÑиÑелей или ÑÑÑÑоÑов, нажми на кнопки ниже' 10653 headline_thanks_1.innerHTML = '<span>Ðаждое мнение Ð´Ð°ÐµÑ Ð½Ð°Ð¼ ÑÑимÑл двигаÑÑÑÑ Ð´Ð°Ð»ÑÑе и ÑазвиваÑÑÑÑ.</span> <span>ÐÑ Ð±Ñдем пÑодолжаÑÑ ÑабоÑаÑÑ Ð½Ð°Ð´ каÑеÑÑвом наÑÐ¸Ñ ÐºÑÑÑов!</span>' 10654 } 10655 caption_thanks_1.innerHTML = 'СпаÑибо за Ð²Ð°Ñ Ð¾ÑзÑв!' 10656 caption_thanks_2.innerHTML = 'СпаÑибо за Ñвой оÑзÑв! ' 10657 } 10658 10659 window.addEventListener('click', function (e) { 10660 if (e.target.closest('.review__select')) return 10661 const activeSelect = reviewSo2026.querySelector('.review__select.active') 10662 if (activeSelect) activeSelect.classList.remove('active') 10663 const activeSelectTop = reviewSo2026.querySelector('.review__select-top.active') 10664 if (activeSelectTop) activeSelectTop.classList.remove('active') 10665 body.classList.remove('no-scroll-mob') 10666 }) 10667 10668 for (let i = 0; i < selectTops.length; i += 1) { 10669 selectTops[i].addEventListener('click', () => openSelect(selectTops[i])) 10670 const inputs = selectTops[i].parentElement.querySelectorAll('.review__select-input')
10671 inputs.forEach(input => { 10672 input.addEventListener('change', () => setSelectValue(selectTops[i])) 10673 }) 10674 const selectClose = selectTops[i].parentElement.querySelector('.review__select-close') 10675 selectClose.addEventListener('click', () => closeSelect(selectTops[i])) 10676 } 10677 10678 function openSelect(that) { 10679 if (!that.classList.contains('active')) { 10680 const activeSelect = reviewSo2026.querySelector('.review__select.active') 10681 if (activeSelect) activeSelect.classList.remove('active') 10682 const activeSelectTop = reviewSo2026.querySelector('.review__select-top.active') 10683 if (activeSelectTop) activeSelectTop.classList.remove('active') 10684 } 10685 10686 if (that.parentElement.classList.contains('review__select_tutor') || that.parentElement.classList.contains('review__select_teacher')) { 10687 that.classList.add('active') 10688 that.parentElement.classList.add('active') 10689 } else { 10690 that.classList.toggle('active') 10691 that.parentElement.classList.toggle('active') 10692 } 10693 body.classList.add('no-scroll-mob') 10694 } 10695 10696 function closeSelect(selectTop) { 10697 selectTop.classList.remove('active') 10698 selectTop.parentElement.classList.remove('active') 10699 body.classList.remove('no-scroll-mob') 10700 } 10701 10702 function setSelectValue (selectTop) { 10703 closeSelect(selectTop) 10704 const selectText = selectTop.querySelector('.review__select-top-text') 10705 selectText.classList.add('active') 10706 const text = selectTop.parentElement.querySelector('input:checked').getAttribute('data-text') 10707 if (selectText) selectText.innerHTML = text 10708 } 10709} 10710 10711 10712if (document.querySelector('[data-role="scroll-to-anchor"]')) initScrollToAnchor() 10713 10714function initScrollToAnchor () { 10715 const anchorElements = document.querySelectorAll('[data-role="scroll-to-anchor"]') 10716 10717 for (let i = 0, len = anchorElements.length; i < len; i++) _loopAddEventScrollToAnchor(anchorElements[i]) 10718 10719 function _loopAddEventScrollToAnchor (node) { 10720 node.addEventListener('click', clickOnTheScrollElement) 10721 } 10722} 10723 10724function clickOnTheScrollElement (event) { 10725 event.preventDefault() 10726 let elementId 10727 if (this.hash) elementId = this.hash.substr(1) 10728 else elementId = this.getAttribute('scroll-to-anchor-id')?.substr(1) 10729 const element = document.getElementById(elementId) 10730 const offset = this.getAttribute('scroll-offset') 10731 if (element) animateScrollToAnchor(element, offset) 10732 const duration = this.getAttribute('scroll-duration') 10733 if (element) animateScrollToAnchor(element, offset, duration) 10734} 10735 10736function animateScrollToAnchor (theElement, offset, duration) { 10737 if (!offset) { 10738 const banner = document.querySelector('.discount') 10739 const bannerHeight = banner ? banner.clientHeight : 0 10740 if (window.innerWidth < 744) { 10741 offset = 84 + bannerHeight 10742 } else if (window.innerWidth < 1200) { 10743 offset = 102 + bannerHeight 10744 } else { 10745 offset = 120 + bannerHeight 10746 } 10747 } 10748 const positionNow = window.pageYOffset 10749 const positionElement = theElement.getBoundingClientRect().top + scrollY - offset 10750 if (duration === 'instant') { 10751 window.scrollTo({left: 0, top: positionElement, behavior: 'instant'}) 10752 } else { 10753 duration = 200 10754 const step = positionElement - positionNow 10755 const start = performance.now() 10756 10757 requestAnimationFrame(function animate (time) { 10758 const timePassed = time - start 10759 10760 if (timePassed > duration) { 10761 window.scrollTo(0, positionElement) 10762 } else { 10763 window.scrollTo(0, positionNow + step * (timePassed / duration)) 10764 requestAnimationFrame(animate) 10765 } 10766 }) 10767 } 10768} 10769 10770const selectFilter = document.querySelectorAll('.select-filter') 10771const stickyHeader = document.querySelector('.sticky-header') 10772const body = document.querySelector('body') 10773 10774for (let i = 0; i < selectFilter.length; i++) { 10775 selectFilterInit(selectFilter[i]) 10776} 10777 10778function selectFilterInit (select) { 10779 document.addEventListener('click', function (e) { 10780 if (e.target.classList.contains('select-filter__close') || e.target.closest('.select-filter__item') || !e.target.closest('.select-filter')) { 10781 filterTop.classList.remove('active') 10782 select.classList.remove('active') 10783 showHeader() 10784 } 10785 }) 10786 10787 const text = select.querySelector(".select-filter__top-text") 10788 const filterTop = select.querySelector(".select-filter__top") 10789 filterTop.addEventListener("click", (e)=> openFilter(filterTop, e)) 10790 10791 const inputs = select.querySelectorAll(".select-filter__input") 10792 for (let i = 0; i < inputs.length; i++) { 10793 inputs[i].addEventListener('change', function () { 10794 if (inputs[i].hasAttribute('data-summer')) { 10795 body.classList.add('summer-filter-active')
10796 text.innerHTML = inputs[i].parentElement.querySelector('.select-filter__view').innerHTML 10797 } else { 10798 body.classList.remove('summer-filter-active') 10799 text.innerHTML = inputs[i].getAttribute('data-text') 10800 } 10801 }) 10802 } 10803 10804 function openFilter (opener, e) { 10805 e.stopPropagation() 10806 if (!opener.classList.contains('active')) { 10807 const oldActive = document.querySelector('.select-filter__top.active') 10808 if (oldActive) oldActive.classList.remove('active') 10809 const oldActiveFilter = document.querySelector('.select-filter.active') 10810 if (oldActiveFilter) oldActiveFilter.classList.remove('active') 10811 } 10812 if (opener.classList.contains('active')) { 10813 opener.classList.remove('active') 10814 showHeader() 10815 select.classList.remove('active') 10816 } else { 10817 opener.classList.add('active') 10818 select.classList.add('active') 10819 hideHeader() 10820 const oldOpen = document.querySelector(".all-courses__filter-top.active, .ege-tile__filter-top.active, .offer-tile__filter-top.active") 10821 if (oldOpen) oldOpen.classList.remove('active') 10822 } 10823 } 10824 10825 function showHeader () { 10826 stickyHeader.classList.remove('hide') 10827 body.classList.remove('no-scroll') 10828 } 10829 10830 function hideHeader () { 10831 if (window.innerWidth < 744) { 10832 stickyHeader.classList.add('hide') 10833 body.classList.add('no-scroll') 10834 } 10835 } 10836} 10837 10838 10839const stageToggles = document.querySelectorAll('.header__stages-button') 10840 10841 if (stageToggles.length) stageTogglesInit() 10842 10843 function stageTogglesInit () { 10844 for (let i = 0; i < stageToggles.length; i++) { 10845 stageToggles[i].addEventListener('click', toggleStage) 10846 } 10847 10848 function toggleStage () { 10849 const id = this.getAttribute('data-stage-id') 10850 const blocks = document.querySelectorAll("[data-stage-number='" + id + "']") 10851 10852 for (let i = 0; i < blocks.length; i++) { 10853 blocks[i].classList.remove('stage-block-hide') 10854 } 10855 10856 const oldToggle = document.querySelector('.header__stages-button.active') 10857 let oldId = '' 10858 if (oldToggle) { 10859 oldId = oldToggle.getAttribute('data-stage-id') 10860 oldToggle.classList.remove('active') 10861 } 10862 const oldBlocks = document.querySelectorAll("[data-stage-number='" + oldId + "']") 10863 10864 const oldCourseAbout = document.querySelector(".course-about[data-stage-number='" + oldId + "']") 10865 if (oldCourseAbout) { 10866 const oldVideoWrap = oldCourseAbout.querySelector("[data-element='course-about-video-wrap']") 10867 if (oldVideoWrap) { 10868 const courseAboutVideo = oldVideoWrap.querySelector("[data-element='course-about-video']") 10869 if (courseAboutVideo) { 10870 if (!courseAboutVideo.muted) oldVideoWrap.click() 10871 } 10872 } 10873 } 10874 10875 for (let i = 0; i < oldBlocks.length; i++) { 10876 oldBlocks[i].classList.add('stage-block-hide') 10877 } 10878 10879 this.classList.add('active') 10880 } 10881 } 10882 10883const stretchBottom = document.querySelector('[data-role="stretch-bottom"]') 10884 10885if (stretchBottom) stretchBottomInit() 10886 10887function stretchBottomInit () { 10888 const close = stretchBottom.querySelector('[data-role="stretch-bottom-close"]') 10889 if (close) close.addEventListener('click', removeStretchBottom) 10890 const promo = document.querySelector('.promo') 10891 if (promo) promo.classList.add('with-stretch-bottom') 10892 10893 function removeStretchBottom (e) { 10894 e.preventDefault() 10895 stretchBottom.remove() 10896 if (promo) promo.classList.remove('with-stretch-bottom') 10897 } 10898} 10899 10900 10901const stretch = document.querySelector('[data-role="stretch"]') 10902 10903if (stretch) stretchInit() 10904 10905function stretchInit () { 10906 const stickyHeader = document.querySelector('.sticky-header') 10907 const close = stretch.querySelector('[data-role="stretch-close"]') 10908 if (close) close.addEventListener('click', removeStretch) 10909 const eye = document.querySelector('.eye') 10910 10911 function removeStretch (e) { 10912 e.preventDefault() 10913 stretch.remove() 10914 window.removeEventListener('scroll', checkScroll) 10915 stickyHeader.classList.remove('predzaps-top-hide-no-transition') 10916 stickyHeader.classList.remove('predzaps-top-hide') 10917 if (eye) eye.classList.remove('translate') 10918 } 10919 10920 window.addEventListener('scroll', checkScroll, { passive: true }) 10921 checkScroll() 10922 10923 function checkScroll () { 10924 if (window.scrollY > 100) { 10925 stickyHeader.classList.add('predzaps-top-hide') 10926 setTimeout(() => stickyHeader.classList.add('predzaps-top-hide-no-transition'), 300) 10927 if (eye) eye.classList.remove('translate') 10928 } else if (window.scrollY <= 20) { 10929 stickyHeader.classList.remove('predzaps-top-hide-no-transition') 10930 setTimeout(() => stickyHeader.classList.remove('predzaps-top-hide'), 100) 10931 if (eye) eye.classList.add('translate') 10932 } 10933 } 10934} 10935 10936const tenorSidebarDesk = document.querySelector('.tenor-sidebar_desk') 10937const tenorSidebarMob = document.querySelector('.tenor-sidebar_mob') 10938 10939if (tenorSidebarDesk && tenorSidebarMob) articleSidebarDescInit() 10940 10941function articleSidebarDescInit () { 10942 const articleLinkArray = tenorSidebarDesk.querySelectorAll('.tenor-sidebar__link') 10943 const articleTitleArray = document.querySelectorAll('[data-element="tenor-sidebar-title"]') 10944 const articleLinkArrayMob = tenorSidebarMob.querySelectorAll('.tenor-sidebar__link') 10945 const name = tenorSidebarMob.querySelector('.tenor-sidebar__name') 10946 const layer = tenorSidebarMob.querySelector('.tenor-sidebar__layer') 10947 const body = document.querySelector('body') 10948 new SimpleBar(tenorSidebarDesk.querySelector('.tenor-sidebar__area')) 10949 10950 let scrollDown = true 10951 let lastScrollTop = 0 10952 10953 10954 window.addEventListener('scroll', checkScroll, { passive: true }) 10955 10956 name.addEventListener('click', toggleSidebar) 10957 layer.addEventListener('click', closeSidebar) 10958 10959 window.addEventListener('scroll', checkScrollDirection, { passive: true }) 10960 10961 for (let i = 0; i < articleLinkArrayMob.length; i++) { 10962 articleLinkArrayMob[i].addEventListener('click', toggleLinkActive) 10963 } 10964 10965 function checkScroll () { 10966 for (let i = 0; i < articleTitleArray.length; i++) { 10967 if (articleTitleArray[i].getBoundingClientRect().top < 300 || articleTitleArray[i].getBoundingClientRect().bottom - window.innerHeight < 0) { 10968 removeOldLinkActive() 10969 articleLinkArray[i].classList.add('active') 10970 articleLinkArrayMob[i].classList.add('active') 10971 } else { 10972 articleLinkArray[i].classList.remove('active') 10973 articleLinkArrayMob[i].classList.remove('active') 10974 } 10975 } 10976 } 10977 10978 function removeOldLinkActive () { 10979 const oldActive = tenorSidebarDesk.querySelector('.tenor-sidebar__link.active') 10980 if (oldActive) oldActive.classList.remove('active') 10981 const oldActiveMob = tenorSidebarMob.querySelector('.tenor-sidebar__link.active') 10982 if (oldActiveMob) oldActiveMob.classList.remove('active') 10983 10984 } 10985 10986 function checkScrollDirection () { 10987 const st = window.scrollY 10988 if (st - lastScrollTop > 7) { 10989 scrollDown = true 10990 } else if (st - lastScrollTop < -7) { 10991 scrollDown = false 10992 } 10993 lastScrollTop = st <= 0 ? 0 : st 10994 if (scrollDown && (name.getBoundingClientRect().top < 120)) { 10995 tenorSidebarMob.classList.remove('fixed') 10996 } else { 10997 tenorSidebarMob.classList.add('fixed') 10998 } 10999 } 11000 11001 function toggleSidebar () { 11002 if (name.classList.contains('active')) { 11003 closeSidebar() 11004 } else { 11005 body.classList.add('no-scroll-md') 11006 window.removeEventListener('scroll', checkScrollDirection) 11007 name.classList.add('active') 11008 name.textContent = 'ÐакÑÑÑÑ ÑодеÑжание' 11009 tenorSidebarMob.classList.add('active') 11010 } 11011 } 11012 11013 function closeSidebar () { 11014 body.classList.remove('no-scroll-md') 11015 tenorSidebarMob.classList.remove('active') 11016 name.classList.remove('active') 11017 name.textContent = name.getAttribute('data-default-text') 11018 window.addEventListener('scroll', checkScrollDirection, {passive: true}) 11019 } 11020 11021 function toggleLinkActive () { 11022 const oldActive = tenorSidebarMob.querySelector('.tenor-sidebar__link.active') 11023 if (oldActive) oldActive.classList.remove('active') 11024 this.classList.add('active') 11025 closeSidebar() 11026 } 11027} 11028 11029const tileSumrNewy = document.querySelector('.tile-sumr-newy') 11030 11031if (tileSumrNewy) tileSumrNewyInit() 11032 11033function tileSumrNewyInit () { 11034 const inputs = tileSumrNewy.querySelectorAll('.tile-sumr-newy__input')
11035 inputs.forEach(input => { 11036 input.addEventListener('change', () => { 11037 if (input.hasAttribute('data-summer')) { 11038 body.classList.add('summer-filter-active') 11039 } else { 11040 body.classList.remove('summer-filter-active') 11041 } 11042 }) 11043 }) 11044} 11045 11046const timers = document.querySelectorAll('[data-element="timer"]') 11047 11048for (let i = 0; i < timers.length; i++) { 11049 timersInit(timers[i]) 11050} 11051 11052function timersInit (timer) { 11053 const date = timer.getAttribute('date-end') 11054 const countDownDate = new Date(date).getTime() 11055 11056 const nodes = timer.querySelectorAll('[data-element="timer-number"]') 11057 11058 const interval = setInterval(updateTimer, 1000) 11059 11060 function updateTimer () { 11061 const now = new Date().getTime(); 11062 const distance = countDownDate - now; 11063 11064 const days = Math.floor(distance / (1000 * 60 * 60 * 24)) 11065 const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)) 11066 const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)) 11067 const seconds = Math.floor((distance % (1000 * 60)) / 1000) 11068 11069 if (nodes.length < 4) { 11070 nodes[0].innerHTML = hours 11071 nodes[1].innerHTML = minutes 11072 nodes[2].innerHTML = seconds 11073 } else { 11074 nodes[0].innerHTML = days 11075 nodes[1].innerHTML = hours 11076 nodes[2].innerHTML = minutes 11077 nodes[3].innerHTML = seconds 11078 } 11079 11080 if (distance < 0) { 11081 clearInterval(interval); 11082 nodes[0].innerHTML = "0" 11083 nodes[1].innerHTML = "0" 11084 nodes[2].innerHTML = "0" 11085 if (nodes[3]) nodes[3].innerHTML = "0" 11086 } 11087 } 11088} 11089 11090 11091const trialFamilyStart = document.querySelector('#trial-family-start') 11092 11093 if (trialFamilyStart) trialFamilyStartInit() 11094 11095 function trialFamilyStartInit () { 11096 const opener = trialFamilyStart.querySelector("[data-element='trial-family-start-filter-opener']") 11097 const inputs = trialFamilyStart.querySelectorAll("[data-element='trial-family-start-filter-input']") 11098 const text = trialFamilyStart.querySelector(".trial-family-start__filter-top-text") 11099 const number = trialFamilyStart.querySelector(".trial-family-start__number") 11100 const button = trialFamilyStart.querySelector(".trial-family-start__button") 11101 11102 opener.addEventListener('click', toggleSelect) 11103 11104 function toggleSelect() { 11105 if (opener.classList.contains('active')) { 11106 opener.classList.remove('active') 11107 } else { 11108 const oldOpen = trialFamilyStart.querySelector(".trial-family-start__filter-top.active") 11109 if (oldOpen) oldOpen.classList.remove('active') 11110 opener.classList.add('active') 11111 } 11112 } 11113 11114 for (let i = 0; i < inputs.length; i++) { 11115 inputs[i].addEventListener('change', setValue) 11116 } 11117 11118 function setValue () { 11119 opener.classList.remove('active') 11120 text.innerHTML = this.getAttribute('data-number') 11121 number.innerHTML = this.getAttribute('data-number') 11122 button.href = this.value+this.getAttribute('data-utm'); 11123 } 11124 } 11125 11126const trialTile = document.getElementById("trial-tile") 11127 11128if (trialTile) trialTileInit() 11129 11130function trialTileInit () { 11131 const config = { attributes: true, childList: true, characterData: true, subtree: true } 11132 const openers = trialTile.querySelectorAll("[data-element='trial-tile-filter-opener']") 11133 const grades = trialTile.querySelector("[data-ftype='class_select']") 11134 const subjects = trialTile.querySelector("[data-ftype='class_subjects']") 11135 11136 const observer = new MutationObserver(function() { 11137 const wrap = openers[1].nextElementSibling 11138 const items = wrap.querySelectorAll("[data-element='trial-tile-filter-input']") 11139 items.forEach((item) => { 11140 item.addEventListener('change', () => updateFilter(openers[1], wrap)) 11141 }) 11142 }) 11143 11144 const reset = trialTile.querySelector("[data-element='trial-tile-filter-reset']") 11145 if (reset) reset.addEventListener('click', resetFilters) 11146 11147 function resetFilters () { 11148 for (let i = 0; i < openers.length; i++) { 11149 const wrap = openers[i].nextElementSibling 11150 const items = wrap.querySelectorAll("[data-element='trial-tile-filter-input']") 11151 items.forEach((item) => { 11152 item.checked = false 11153 }) 11154 updateFilter(openers[i], wrap) 11155 } 11156 makeFiltration(); 11157 } 11158 11159 for (let i = 0; i < openers.length; i++) { 11160 openers[i].addEventListener("click", ()=> openFilter(openers[i])) 11161 const wrap = openers[i].nextElementSibling 11162 const button = wrap.querySelector("[data-element='trial-tile-filter-save']") 11163 // button.addEventListener("click", ()=> closeFilter(openers[i], wrap)) 11164 if (button) button.addEventListener("click", ()=> closeFilter(openers[i], wrap)) 11165 const items = wrap.querySelectorAll("[data-element='trial-tile-filter-input']")
11166 items.forEach((item) => { 11167 item.addEventListener('change', () => updateFilter(openers[i], wrap)) 11168 if (!button) item.addEventListener('change', () => closeFilter(openers[i], wrap)) 11169 }) 11170 if (i === 1) { 11171 window.onload = function() { 11172 observer.observe(wrap, config) 11173 } 11174 } 11175 } 11176 11177 function updateFilter (opener, wrap) { 11178 opener.innerHTML = opener.getAttribute('data-default-text') 11179 const items = wrap.querySelectorAll(["input:checked"]) 11180 if (items.length) { 11181 opener.innerHTML = 'ÐÑбÑано: ' 11182 items.forEach((item) => { 11183 const span = document.createElement("span") 11184 span.innerHTML = item.nextElementSibling.innerHTML 11185 span.classList.add('span') 11186 opener.append(span) 11187 }) 11188 } 11189 const itemsAll = trialTile.querySelectorAll(["input:checked"]) 11190 if (itemsAll.length) { 11191 if (reset) reset.style.display = 'flex' 11192 } else { 11193 if (reset) reset.style.display = 'none' 11194 } 11195 // makeFiltration(); 11196 } 11197 11198 function openFilter (opener) { 11199 if (opener.classList.contains('active')) { 11200 closeFilter(opener) 11201 } else { 11202 const oldOpen = trialTile.querySelector(".trial-tile__filter-top.active") 11203 if (oldOpen) oldOpen.classList.remove('active') 11204 opener.classList.add('active') 11205 11206 const filter = opener.parentElement 11207 const oldFilter = trialTile.querySelector(".trial-tile__filter.open") 11208 if (oldFilter) oldFilter.classList.remove('open') 11209 if (filter) filter.classList.add('open') 11210 } 11211 } 11212 11213 function closeFilter (opener) { 11214 opener.classList.remove('active') 11215 const filter = opener.parentElement 11216 if (filter) filter.classList.remove('open') 11217 makeFiltration(); 11218 } 11219 function makeFiltration () { 11220 const grades_wrap = grades.nextElementSibling 11221 const grades_items = grades_wrap.querySelectorAll(["input:checked"]) 11222 let grades_result = '' 11223 let grade_first = 0 11224 grades_items.forEach((item, i) => { 11225 if (i > 0) grades_result += '|' 11226 if (grade_first == 0) grade_first = item.value 11227 grades_result += item.value 11228 }) 11229 let subjects_result = '' 11230 try{ 11231 const subjects_wrap = subjects.nextElementSibling 11232 const subjects_items = subjects_wrap.querySelectorAll(["input:checked"]) 11233 subjects_items.forEach((item, i) => { 11234 if (i > 0) subjects_result += '|' 11235 subjects_result += item.value 11236 }) 11237 }catch(e){} 11238 // let promo_f = trialTile.getAttribute('data-promo'); 11239 //console.log(grades_result) 11240 //console.log(subjects_result) 11241 let utm_f = trialTile.getAttribute('data-utm'); 11242 $('.filtered_elements').html("<div class='tile-loader'></div>"); 11243 // if(promo_f != null && promo_f != '' && promo_f != undefined){ 11244 // $.request('AllCourseFunctions::onPaginateAllCourses', { 11245 // data: { 11246 // 'grade': grades_result, 11247 // 'subject': subjects_result, 11248 // 'promo': promo_f, 11249 // } 11250 // }) 11251 // }else{ 11252 $.request('TrialCourseFunctions::onPaginateAllCourses', { 11253 data: { 11254 'grade': grades_result, 11255 'subject': subjects_result, 11256 'utm_t': utm_f 11257 } 11258 }) 11259 if (grade_first > 0){ 11260 let url = new URL(window.location.href) 11261 url.searchParams.set('gr', grade_first); 11262 history.replaceState(null, "", url.toString()) 11263 } 11264 // } 11265 11266 } 11267} 11268 11269/* ========================================================================== 11270 popups.js â оÑкÑÑÑие/закÑÑÑие модалок, блокиÑовка ÑкÑолла, ÑокÑÑ-ÑÑап 11271 РазмеÑка ÑпÑавлÑеÑÑÑ Ð°ÑÑибÑÑами: 11272 data-popup-open="<id>" â оÑкÑÑÑÑ Ð¿Ð¾Ð¿Ð°Ð¿ Ñ ÑÑим id 11273 data-popup-close â закÑÑÑÑ ÑекÑÑий попап 11274 ========================================================================== */ 11275(function () { 11276 'use strict'; 11277 11278 var root = document.querySelector('.tf'); 11279 if (!root) return; 11280 11281 var openStack = []; 11282 var lastFocused = null; 11283 11284 var FOCUSABLE = 'a[href], button:not([disabled]), input:not([disabled]), ' + 11285 'select:not([disabled]), textarea:not([disabled]), [tabindex]:not
11285([tabindex="-1"])'; 11286 11287 function lockScroll() { 11288 var sw = window.innerWidth - document.documentElement.clientWidth; 11289 document.body.style.overflow = 'hidden'; 11290 if (sw > 0) document.body.style.paddingRight = sw + 'px'; 11291 } 11292 function unlockScroll() { 11293 document.body.style.overflow = ''; 11294 document.body.style.paddingRight = ''; 11295 } 11296 11297 function open(id) { 11298 var popup = document.getElementById(id); 11299 if (!popup) return; 11300 11301 if (!openStack.length) { 11302 lastFocused = document.activeElement; 11303 lockScroll(); 11304 } else { 11305 // ÐеÑÐµÑ Ð¾Ð´ Ð¼ÐµÐ¶Ð´Ñ Ð¿Ð¾Ð¿Ð°Ð¿Ð°Ð¼Ð¸: пÑедÑдÑÑий пÑÑÑем. 11306 openStack[openStack.length - 1].hidden = true; 11307 } 11308 11309 popup.hidden = false; 11310 openStack.push(popup); 11311 11312 if (id === 'exitOverlay') { 11313 document.removeEventListener('mouseleave', mouseLeaveHandler) 11314 } 11315 11316 var first = popup.querySelector(FOCUSABLE); 11317 if (first) first.focus(); 11318 } 11319 11320 function close() { 11321 var popup = openStack.pop(); 11322 if (!popup) return; 11323 popup.hidden = true; 11324 11325 if (popup.id === 'exitOverlay') { 11326 popup.classList.remove('popup_no-social') 11327 } 11328 11329 if (openStack.length) { 11330 openStack[openStack.length - 1].hidden = false; 11331 } else { 11332 unlockScroll(); 11333 if (lastFocused && lastFocused.focus) lastFocused.focus(); 11334 lastFocused = null; 11335 } 11336 } 11337 11338 function closeAll() { while (openStack.length) close(); } 11339 11340 // --- ÐелегиÑование кликов ------------------------------------------------- 11341 root.addEventListener('click', function (e) { 11342 var opener = e.target.closest('[data-popup-open]'); 11343 if (opener) { 11344 e.preventDefault(); 11345 open(opener.getAttribute('data-popup-open')); 11346 return; 11347 } 11348 if (e.target.closest('[data-popup-close]')) { 11349 e.preventDefault(); 11350 close(); 11351 return; 11352 } 11353 // Ðлик по подложке закÑÑÐ²Ð°ÐµÑ ÑолÑко на деÑкÑопе, где попап â модалка. 11354 var popup = e.target.closest('.popup'); 11355 if (popup && e.target === popup && window.matchMedia('(min-width: 1280px)').matches) { 11356 close(); 11357 } 11358 }); 11359 11360 // --- ÐлавиаÑÑÑа ------------------------------------------------------------ 11361 document.addEventListener('keydown', function (e) { 11362 if (!openStack.length) return; 11363 var popup = openStack[openStack.length - 1]; 11364 11365 if (e.key === 'Escape') { e.preventDefault(); close(); return; } 11366 11367 if (e.key === 'Tab') { 11368 var items = Array.prototype.filter.call( 11369 popup.querySelectorAll(FOCUSABLE), 11370 function (el) { return el.offsetParent !== null; } 11371 ); 11372 if (!items.length) return; 11373 var first = items[0], last = items[items.length - 1]; 11374 if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); } 11375 else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); } 11376 } 11377 }); 11378 11379 // --- ÐÑÐ±Ð¾Ñ Ð²Ð°ÑианÑа в попапе оплаÑÑ --------------------------------------- 11380 // ÐодÑвеÑка каÑÑоÑки. :has() еÑÑ Ð½Ðµ везде, поÑÑÐ¾Ð¼Ñ ÐºÐ»Ð°ÑÑом. 11381 root.addEventListener('change', function (e) { 11382 if (!e.target.classList.contains('radio')) return; 11383 var group = e.target.closest('.opt-group__options'); 11384 if (!group) return; 11385 Array.prototype.forEach.call(group.querySelectorAll('.option'), function (opt) { 11386 var input = opt.querySelector('.radio'); 11387 opt.classList.toggle('is-selected', !!input && input.checked); 11388 }); 11389 }); 11390 11391 const formatGroup = document.querySelector('.opt-group-format') 11392 const paymodeGroups = document.querySelectorAll('.opt-group-paymode') 11393 const optResults = document.querySelectorAll('.opt-result') 11394 11395 function updateResult (input) { 11396 optResults.forEach(result => { 11397 result.classList.toggle( 11398 'active', 11399 result.dataset.result === input.dataset.result 11400 ) 11401 }) 11402 } 11403 11404 if (formatGroup) { 11405 const formatInputs = formatGroup.querySelectorAll('input') 11406 11407 formatInputs.forEach(formatInput => { 11408 formatInput.addEventListener('change', () => { 11409 11410 const currentPayMode = document.querySelector(
11411 '.opt-group-paymode.active input:checked' 11412 ) 11413 11414 const currentPayModeValue = currentPayMode?.value 11415 11416 const newPayModeGroup = document.querySelector( 11417 `.opt-group-paymode[data-format="${formatInput.value}"]` 11418 ) 11419 11420 paymodeGroups.forEach(group => { 11421 group.classList.remove('active') 11422 }) 11423 11424 if (!newPayModeGroup) return 11425 11426 newPayModeGroup.classList.add('active') 11427 11428 const newPayModeInputs = newPayModeGroup.querySelectorAll('input') 11429 11430 let newPayModeInput = Array.from(newPayModeInputs).find( 11431 input => input.value === currentPayModeValue 11432 ) 11433 11434 if (!newPayModeInput) { 11435 newPayModeInput = newPayModeInputs[0] 11436 } 11437 11438 if (!newPayModeInput) return 11439 11440 newPayModeInput.checked = true 11441 newPayModeInput.dispatchEvent( 11442 new Event('change', { bubbles: true }) 11443 ) 11444 }) 11445 }) 11446 } 11447 11448 paymodeGroups.forEach(paymodeGroup => { 11449 paymodeGroup.querySelectorAll('input').forEach(input => { 11450 input.addEventListener('change', () => { 11451 updateResult(input) 11452 }) 11453 }) 11454 }) 11455 11456 document.addEventListener('mouseleave', mouseLeaveHandler) 11457 11458 function mouseLeaveHandler(event) { 11459 if (event.clientY < 0 && !openStack.length) { 11460 const exitOverlay = document.querySelector('#exitOverlay') 11461 if (exitOverlay) exitOverlay.classList.add('popup_no-social') 11462 open('exitOverlay') 11463 document.removeEventListener('mouseleave', mouseLeaveHandler) 11464 } 11465 } 11466 11467 11468 // ÐаÑÑÐ¶Ñ â на ÑлÑÑай, еÑли понадобиÑÑÑ Ð´ÑÑнÑÑÑ Ð¸Ð· кода пÑоекÑа. 11469 window.tfPopups = { open: open, close: close, closeAll: closeAll }; 11470})(); 11471 11472/* ========================================================================== 11473 sticky.js â показ липкой панели и обÑаÑнÑй оÑÑÑÑÑ Ð² оÑÑеÑе 11474 ========================================================================== */ 11475(function () { 11476 'use strict'; 11477 11478 // --- ÐÐ¸Ð¿ÐºÐ°Ñ Ð¿Ð°Ð½ÐµÐ»Ñ --------------------------------------------------------- 11479 // ÐоÑвлÑеÑÑÑ, когда полÑзоваÑÐµÐ»Ñ ÑÑÑл ниже пеÑвого ÑкÑана, и пÑÑÑеÑÑÑ, 11480 // когда виден Ñам блок оÑÑеÑа â Ñам Ñже еÑÑÑ ÑÐ²Ð¾Ñ ÐºÐ½Ð¾Ð¿ÐºÐ°. 11481 var sticky = document.getElementById('stickyCta'); 11482 var offer = document.querySelector('.section--offer'); 11483 11484 if (sticky) { 11485 var offerVisible = false; 11486 11487 if (offer && 'IntersectionObserver' in window) { 11488 new IntersectionObserver(function (entries) { 11489 offerVisible = entries[0].isIntersecting; 11490 update(); 11491 }, { threshold: 0.2 }).observe(offer); 11492 } 11493 11494 var update = function () { 11495 sticky.classList.toggle('is-visible', !offerVisible); 11496 }; 11497 11498 var ticking = false; 11499 window.addEventListener('scroll', function () { 11500 if (ticking) return; 11501 ticking = true; 11502 window.requestAnimationFrame(function () { update(); ticking = false; }); 11503 }, { passive: true }); 11504 11505 update(); 11506 } 11507 11508 // --- Ð¢Ð°Ð¹Ð¼ÐµÑ Ð¾ÑÑеÑа --------------------------------------------------------- 11509 // Ðедлайн беÑÑÑÑÑ Ð¸Ð· data-deadline-minutes. Ðа Ð±Ð¾Ñ Ð·Ð°Ð¼ÐµÐ½Ð¸ÑÑ Ð½Ð° вÑÐµÐ¼Ñ Ñ ÑеÑвеÑа. 11510 var timer = document.querySelector('[data-element="try-free-timer"]') 11511 if (!timer) return 11512 11513 var dateEndStr = timer.getAttribute('date-end') 11514 if (!dateEndStr) return 11515 11516 var deadline = Date.parse(dateEndStr) 11517 if (isNaN(deadline)) return 11518 11519 var slots = { 11520 hours: timer.querySelector('[data-timer="hours"]'), 11521 minutes: timer.querySelector('[data-timer="minutes"]'), 11522 seconds: timer.querySelector('[data-timer="seconds"]') 11523 }; 11524 11525 function pad(n) { return n < 10 ? '0' + n : String(n); } 11526 11527 function tick() { 11528 var left = Math.max(0, deadline - Date.now()); 11529 var total = Math.floor(left / 1000); 11530 11531 if (slots.hours) slots.hours.textContent = pad(Math.floor(total / 3600)); 11532 if (slots.minutes) slots.minutes.textContent = pad(Math.floor(total % 3600 / 60)); 11533 if (slots.seconds) slots.seconds.textContent = pad(total % 60); 11534 11535 if (left > 0) { 11536 window.setTimeout(tick, 1000); 11537 } else { 11538 const title = document.querySelector('.offer__actions-title') 11539 if (title) title.remove() 11540 timer.remove() 11541 } 11542 } 11543 tick(); 11544 11545})(); 11546 11547 11548const vacanciesEndSlider = document.querySelector('.vacancies-end__slider') 11549 11550if (vacanciesEndSlider) vacanciesEndSliderInit() 11551 11552function vacanciesEndSliderInit () { 11553 let sliderSwiper 11554 11555 function initSlider () { 11556 sliderSwiper = new Swiper(vacanciesEndSlider, { 11557 mousewheel: { forceToAxis: true }, 11558 slidesPerView: 'auto', 11559 spaceBetween: 15,
11560 a11y: false, 11561 grid: { 11562 rows: 2, 11563 fill: 'row', 11564 }, 11565 }) 11566 } 11567 11568 window.addEventListener('resize', checkSlider) 11569 11570 checkSlider() 11571 11572 function checkSlider () { 11573 if (window.innerWidth < 1360) { 11574 if (!sliderSwiper || sliderSwiper.destroyed) { 11575 initSlider() 11576 } 11577 } else { 11578 if (sliderSwiper && !sliderSwiper.destroyed) { 11579 sliderSwiper.destroy(true, true) 11580 sliderSwiper = null 11581 } 11582 } 11583 } 11584} 11585 11586const vacanciesStories = document.querySelector('.vacancies-stories') 11587 11588if (vacanciesStories) vacanciesStoriesInit() 11589 11590function vacanciesStoriesInit () { 11591 const body = document.querySelector('body') 11592 11593 const inners = vacanciesStories.querySelectorAll('.vacancies-stories__item') 11594 11595 for (let i = 0; i < inners.length; i++) { 11596 initInner(inners[i]) 11597 } 11598 11599 function initInner (inner) { 11600 const btn = inner.querySelector('.vacancies-stories__more') 11601 btn.addEventListener('click', toggle) 11602 11603 function toggle () { 11604 if (inner.classList.contains('show')) { 11605 btn.innerHTML = 'ЧиÑаÑÑ Ð¸ÑÑоÑÐ¸Ñ Ð¿Ð¾Ð»Ð½Ð¾ÑÑÑÑ' 11606 inner.classList.remove('show') 11607 } else { 11608 btn.innerHTML = 'СкÑÑÑÑ' 11609 inner.classList.add('show') 11610 if (window.innerWidth >= 744) createModal(inner, btn) 11611 } 11612 } 11613 11614 function createModal(innerOld) { 11615 const slide = innerOld.closest('.vacancies-stories__item') 11616 const imageOld = slide.querySelector('.vacancies-stories__image') 11617 const textOld = slide.querySelector('.vacancies-stories__content') 11618 const nameOld = slide.querySelector('.vacancies-stories__name') 11619 const noteOld = slide.querySelector('.vacancies-stories__role') 11620 11621 const modal = document.createElement('div') 11622 modal.classList.add('review-modal','review-modal_vacancies-stories') 11623 modal.setAttribute('data-block', 'modal_story') 11624 11625 const layer = document.createElement('div') 11626 layer.classList.add('review-modal__layer') 11627 layer.setAttribute('data-action', 'modal_close') 11628 11629 const inner = document.createElement('div') 11630 inner.classList.add('review-modal__inner') 11631 11632 const close = document.createElement('button') 11633 close.classList.add('review-modal__close') 11634 close.setAttribute('data-action', 'modal_close') 11635 11636 const left = document.createElement('div') 11637 left.classList.add('review-modal__left') 11638 11639 const box = document.createElement('div') 11640 box.classList.add('review-modal__box') 11641 11642 const image = document.createElement('img') 11643 image.classList.add('review-modal__image') 11644 11645 const name = document.createElement('div') 11646 name.classList.add('review-modal__name') 11647 11648 const note = document.createElement('div') 11649 note.classList.add('review-modal__note') 11650 11651 const right = document.createElement('div') 11652 right.classList.add('review-modal__right') 11653 11654 const text = document.createElement('div') 11655 text.classList.add('review-modal__text') 11656 11657 image.src = imageOld.src 11658 11659 box.append(name) 11660 box.append(note) 11661 name.innerHTML = nameOld.innerHTML 11662 note.innerHTML = noteOld.innerHTML 11663 left.append(image) 11664 left.append(box) 11665 text.innerHTML = textOld.innerHTML 11666 right.append(text) 11667 inner.append(close) 11668 inner.append(left) 11669 inner.append(right) 11670 modal.append(layer) 11671 modal.append(inner) 11672 11673 layer.addEventListener('click', () => setTimeout(closeModal, 100)) 11674 close.addEventListener('click', () => setTimeout(closeModal, 100)) 11675 11676 const main = document.querySelector('main') 11677 main.append(modal) 11678 11679 body.classList.add('no-scroll-desktop') 11680 11681 initCommonAnalytics(modal) 11682 11683 function closeModal () { 11684 modal.remove() 11685 innerOld.classList.remove('show') 11686 btn.innerHTML = 'ЧиÑаÑÑ Ð¸ÑÑоÑÐ¸Ñ Ð¿Ð¾Ð»Ð½Ð¾ÑÑÑÑ' 11687 body.classList.remove('no-scroll-desktop') 11688 } 11689 } 11690 } 11691 11692} 11693 11694 11695const vacanciesTile = document.querySelector('.vacancies-tile') 11696 11697if (vacanciesTile) vacanciesTileInit() 11698 11699function vacanciesTileInit () { 11700 const inputs = vacanciesTile.querySelectorAll('.vacancies-tile__input') 11701 const cards = vacanciesTile.querySelectorAll('.vacancies-tile__card') 11702 const buttonPaginate = vacanciesTile.querySelector('.vacancies-tile__more') 11703 let paginateCounter = 1 11704 let paginatePerPage = 6 11705 let currentCards = [] 11706 11707 buttonPaginate.addEventListener('click', paginate) 11708
11709 inputs.forEach(input => { 11710 input.addEventListener('change', updateTile) 11711 }) 11712 11713 updateTile(true) 11714 11715 function updateTile (noRedirect) { 11716 currentCards = [] 11717 paginateCounter = 1 11718 const currentCategory = this?.value || "0" 11719 11720 cards.forEach(card => { 11721 card.classList.add('hide') 11722 if (card.getAttribute('data-category') === currentCategory || currentCategory === "0") { 11723 currentCards.push(card) 11724 } 11725 }) 11726 11727 paginate() 11728 11729 if (!noRedirect) { 11730 vacanciesTile.scrollIntoView({ 11731 behavior: 'smooth' 11732 }) 11733 } 11734 } 11735 11736 function paginate () { 11737 currentCards.forEach((card, index) => { 11738 if (index < paginateCounter * paginatePerPage) { 11739 card.classList.remove('hide') 11740 } 11741 }) 11742 if (currentCards.length <= paginateCounter * paginatePerPage) { 11743 buttonPaginate.style.display = 'none' 11744 } else { 11745 buttonPaginate.style.display = 'inline-flex' 11746 } 11747 paginateCounter += 1 11748 } 11749} 11750 11751 11752const webinarRecordVideoBoxes = document.querySelectorAll('.webinar-record__video-box_poster') 11753 11754webinarRecordVideoBoxes.forEach(videoBox => { 11755 videoBox.addEventListener('click', () => { 11756 videoBox.classList.add('active') 11757 }, {once: true}) 11758}) 11759 11760if (webinarRecordVideoBoxes.length > 0) { 11761 window.addEventListener('blur', function() { 11762 const activeElement = document.activeElement 11763 11764 if (activeElement && activeElement.tagName === 'IFRAME') { 11765 const container = activeElement.closest('.webinar-record__video-box_poster') 11766 if (container) { 11767 container.classList.add('active') 11768 } 11769 } 11770 }) 11771} 11772
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.