Осенью в России пройдут выборы депутатов Государственной Думы 9-го созыва. «Коммерсант» запускает «политический лотерею», предоставляющую читателям возможность прогнозировать результаты партий, явку, активность избирателей в регионах и т. д. Ваши «рейтинги-прогнозы» будут опубликованы на страницах «Коммерсанта», а после выборов те, кто наиболее точно предскажет их исход, получат ценные (но некоммерческие) призы. п>
Зайдите в личный кабинет, сделайте хотя бы один прогноз и получите приз как лучший аналитик* п> Правила участия диапазон> Чтобы принять участие в конкурсе прогнозов, достаточно зарегистрироваться на сайте «Коммерсанта» и заполнить любой из предложенных пунктов. Прогноз можно уточнять, но не чаще одного раза в сутки. «Тотализатор» закрывается за неделю до начала голосования на выборах 18 сентября. <уш/><уш/> Выборы в нижнюю палату парламента проводятся по смешанной системе: 225 мандатов распределяются между партиями в соответствии с их долей голосов по всей стране, другая половина — между победителями в местных одномандатных округах. <б>Чтобы читатели могли глубже погрузиться в закулисье избирательной кампании и сделать максимально точный прогноз, еженедельник «Коммерсантъ» публикует экспертные аналитические материалы о партийной деятельности в рамках спецпроекта «Навстречу выборам». б> <уш/><уш/>Те, чьи прогнозы наиболее близки к официальным результатам голосования, получат сувениры-сюрпризы от участников избирательного процесса. Мы объявим победителей в общем зачете и в индивидуальных номинациях — за наиболее точный прогноз явки (вопросы №1-3), результативности партии (№4-7) и фракции, добавившей места (№8). Расчеты будут основываться на данных итогового протокола Центральной избирательной комиссии.
Ваш прогноз сохранен!
Сравните это с общими ожиданиями или прочитайте обзор эксперта.
Завтра вы сможете уточнить свой выбор. п> Повышение точности Повышайте точность прогнозов с помощью аналитики «Коммерсанта» диапазон>
Ваш прогноз
Какую итоговую явку избирателей в стране зафиксирует Центризбирком?ч2>
Прогноз читателей
№1
Где и какая будет самая высокая явка? ч2>Субъект Российской Федерации
Прогноз читателей
№2
Где и какая будет самая низкая явка? ч2>Субъект Российской Федерации
Прогноз читателей ч3>
№3
Какой процент голосов партии получат в одном округе?
диапазон> диапазон>
Прогноз читателей ч3>
№4
Выберите один регион, результаты которого вы хотите предсказать. Сколько голосов получат партии в списке? ч2>Субъект Российской Федерации Вечеринка + Добавить партию
Прогноз читателей
№5
Где победитель покажет лучший результат и какой? ч2>Субъект Российской Федерации
Прогноз читателей
№6
Где победившая сторона покажет худший результат и какой? ч2>Субъект РФ
Прогноз читателей
№7
Какая партия покажет наибольший прирост парламентских мандатов? ч2>Вечеринка
Прогноз читателей
№8
Отдайте свой голос
Прогноз можно менять раз в сутки.
Вечеринка const truncateNumber = (число, десятичные дроби = 1) =>{ f (!num && num !== 0) возвращает ноль return Math.trunc(num * Math.pow(10, десятичные дроби))/Math.pow(10, десятичные дроби); } functon ntEle2026Felds(scope = document) { const nputs =scope.querySelectorAll(‘.ele2026_feld__nput’); nputs.forEach((nput) => { f (nput.dataset.ele2026FeldInted === ‘true’) return; nput.dataset.ele2026FeldInted = ‘истина’; const label = nput.closest(‘.ele2026_feld’); const brck = nput.closest(‘.ele2026_house__brck’); f (!label || !brck) return; const getErrorElement = () => { const next = label.nextElementSblng; вернуться к следующему && next.classLst.contans(‘ele2026_feld__error’) ? next: null; }; const showError = (сообщение) =>{ пусть ошибка = getErrorElement(); е (! ошибка) { ошибка = document.createElement(‘p’); error.className = ‘ele2026_feld__error’; label.after (ошибка); } error.textContent = сообщение; brck.classLst.add(‘ele2026_house__brck—error’); }; const hdeError = () => { константная ошибка = getErrorElement(); е (ошибка) { ошибка.удалить(); } brck.classLst.remove(‘ele2026_house__brck—error’); }; constnormalzeValue = (значение) => { возвращаемое значение.replace(/s+/g, »).replace(/,/g, ‘.’); }; const sNumercLke = (значение) => { return /^-?(?:d+|d*.d+)$/.test(value); }; const formatValue = (число) =>{ const округленный = truncateNumber(число) return Strng(округлено).replace(‘.’, ‘,’); }; const valdateInput = () =>{ const rawValue = nput.value.trm(); е (!rawValue) { nput.setCustomValdty(»); хдеОшибка(); возвращаться; } constnormalzedValue =normalzeValue(rawValue); пусть сообщение = »; е (!sNumercLke(normalzedValue)) { message = ‘Можно вводить только цифры’; } else f (nput.getAttrbute(‘nputmode’) === ‘number’ && !Number.sInteger(+normalzedValue)) { message = ‘Можно вводить только целые числа’; } еще { константное число = Число (normalzedValue); е (число < 0) { message = 'Значение должно быть не менее 0'; } else f (число >nput.max) { message = `Значение не должно быть больше ${nput.max}`; } еще { nput.value = formatValue(число); } } nput.setCustomValdty(сообщение); ж (сообщение) { showError (сообщение) nput.closest(‘[data-queston-d]’).scrollIntoVew() } еще { хдеОшибка(); } }; nput.addEventLstener(‘blur’, valdateInput); nput.addEventLstener(‘nput’, () => { nput.setCustomValdty(»); хдеОшибка(); }); }); } ntEle2026Felds(); (() =>{ const INSTANCES = новый WeakMap(); класс Ele2026Выберите { конструктор (корень, индекс = 0) { е (!root || INSTANCES.has(root)) { вернуть INSTANCES.get(корень); } ths.root = корень; ths.natve = root.querySelector(«.ele2026_select__natve»); f (!ths.natve) возврат; ths.ndex = индекс; ths.placeholder = root.dataset.placeholder || «Выбирать»; ths.lstId = `ele2026-select-lst-${ndex + 1}`; ths.button = ноль; ths.label = ноль; ths.lst = ноль; ths.tems = []; ths.sOpen = ложь; ths.actveIndex = -1; ths.sDestroyed = ложь; ths.sRenderng = ложь; ths.onDocumentClck = ths.onDocumentClck.bnd(ths); ths.onNatveChange = ths.onNatveChange.bnd(ths); ths.onButtonClck = ths.onButtonClck.bnd(ths); ths.onButtonKeydown = ths.onButtonKeydown.bnd(ths); ths.onMutatons = ths.onMutatons.bnd(ths); ths.render(); ths.bnd(); ths.observe(); INSTANCES.set(корень, тыс.); } sSelectDsabled() { вернуть ths.natve.dsabled; } getFrstEnabledIndex() { return ths.tems.fndIndex((tem) => !tem.dsabled); } getLastEnabledIndex() { for (let = ths.tems.length — 1; >= 0; —) { f (!ths.tems[].dsabled) return ; } вернуть -1; } getSelectedOpton() { const ndex = ths.natve.selectedIndex; индекс возврата >= 0 ? ths.natve.optons[ndex] : null; } бнд() { document.addEventLstener(«clck», ths.onDocumentClck); ths.natve.addEventLstener(«изменение», ths.onNatveChange); } разблокировать() { document.removeEventLstener(«clck», ths.onDocumentClck); ths.natve.removeEventLstener(«изменить», ths.onNatveChange); е (эта кнопка) { ths.button.removeEventLstener( «щелк» ths.onButtonClck ); ths.button.removeEventLstener( «нажатие клавиши», ths.onButtonKeydown ); } } наблюдать() { ths.observer = новый MutatonObserver(ths.onMutatons); ths.observer.observe(ths.natve, { chldLst: правда, поддерево: правда, атрибуты: правда, attrbuteFlter: [«dsabled», «selected», «label», «value»], данные персонажа: правда, }); } dsconnectObserver() { f (!ths.observer) return; ths.observer.dsconnect(); ths.observer = ноль; } onMutatons (мутатоны) { f (ths.sDestroyed || ths.sRenderng) return; const mustRerender = mutatons.some((мутатон) =>{ f (mutaton.type === «chldLst») возвращает true; f (mutaton.type === «characterData») возвращает true; f (mutaton.type === «атрибуты») { константная цель = mutaton.target; f (цель === ths.natve) { return mutaton.attrbuteName === «dsabled»; } f (target.tagName === «ОПЦИЯ») { вернуть [ «dsabled», «выбранный», «этикетка», «ценность», ].ncludes(mutaton.attrbuteName); } } вернуть ложь; }); f (!shouldRender) return; ths.render(); } onNatveChange() { f (ths.sDestroyed) возврат; ths.syncDsabledState(); ths.syncSeletonFromNatve(); } onDocumentClck (е) { f (ths.sDestroyed) возврат; f (!ths.root.contans(e.target) && ths.sOpen) { ths.close(ложь); } } onButtonClck() { f (ths.sSelectDsabled()) return; ths.sOpen ? ths.close() : ths.open(); } onButtonKeydown (е) { f (ths.sSelectDsabled()) return; переключатель (e.key) { случай «Стрелка вниз»: е.preventDefault(); е (!ths.sOpen) ths.open(); иначе ths.move(1); перерыв; случай «СтрелкаВверх»: е.preventDefault(); е (!ths.sOpen) ths.open(); иначе ths.move(-1); перерыв; случай «Ввод»: случай » «: е.preventDefault(); е (!ths.sOpen) { ths.open(); } еще f ( ths.actveIndex >= 0 && !ths.tems[ths.actveIndex]?.dsabled ) { ths.selectIndex(ths.actveIndex); этос.закрыть(); } перерыв; кейс «Домой»: е.preventDefault(); е (!ths.sOpen) ths.open(); ths.setActve(ths.getFrstEnabledIndex()); перерыв; случай «Конец»: е.preventDefault(); е (!ths.sOpen) ths.open(); ths.setActve(ths.getLastEnabledIndex()); перерыв; кейс «Побег»: е (ths.sOpen) { е.preventDefault(); этос.закрыть(); } перерыв; корпус «Таб»: е (ths.sOpen) { ths.close(ложь); } перерыв; } } обеспечениеКнопка() { const oldButton = ths.root.querySelector( «.ele2026_select__button» ); е (oldButton) { oldButton.removeEventLstener(«clck», ths.onButtonClck); oldButton.removeEventLstener( «нажатие клавиши», ths.onButtonKeydown ); стараяКнопка.удалить(); } ths.button = document.createElement(«кнопка»); ths.button.type = «кнопка»; ths.button.className = «ele2026_select__button»; ths.button.setAttrbute(«ara-haspopup», «lstbox»); ths.button.setAttrbute(«ara-expanded», Strng(ths.sOpen)); ths.button.setAttrbute(«ara-controls», ths.lstId); ths.label = document.createElement(«span»); ths.label.className = «ele2026_select__label»; ths.button.appendChld(ths.label); ths.natve.nsertAdjacentElement(«afterend», ths.button); ths.button.addEventLstener(«clck», ths.onButtonClck); ths.button.addEventLstener(«keydown», ths.onButtonKeydown); } rebuldLst() { ths.lst?.remove(); ths.lst = document.createElement(«ul»); ths.lst.className = «ele2026_select__lst»; ths.lst.d = ths.lstId; ths.lst.setAttrbute(«роль», «lstbox»); ths.lst.tabIndex = -1; ths.tems = Array.from(ths.natve.optons).map( (natveOpton, индекс) =>{ const l = document.createElement(«l»); const dsabled = natveOpton.dsabled; const sPlaceholder = natveOpton.value === «»; l.className = «ele2026_select__opton»; l.setAttrbute(«роль», «оптон»); l.dataset.ndex = Strng(ndex); l.dataset.optonId = natveOpton.d; l.dataset.value = natveOpton.value; л.tabIndex = -1; l.textContent = natveOpton.textContent ?? «»; е (dsabled) { l.classLst.add(«s-dsabled»); l.setAttrbute(«ara-dsabled», «true»); } е (sPlaceholder) { l.classLst.add(«s-placeholder»); } l.addEventLstener(«clck», () => { f (ths.sSelectDsabled() || dsabled) return; ths.selectIndex(ndex); этос.закрыть(); }); l.addEventLstener(«mousemove», () =>{ f (!ths.sOpen || dsabled) return; ths.setActive(ndex); }); ths.lst.appendChld(л); вернуть { эль: л, натвеОптон, индекс инвалид }; } ); ths.button.nsertAdjacentElement(«afterend», ths.lst); } syncDsabledState() { const dsabled = ths.sSelectDsabled(); ths.root.classLst.toggle(«s-dsabled», dsabled); ths.button.dsabled = dsabled; ths.button.setAttrbute(«ara-dsabled», Strng(dsabled)); f (dsabled && ths.sOpen) { ths.close(ложь); } } syncSeletonFromNatve() { const selectedIndex = ths.natve.selectedIndex; const selectedOpton = ths.getSelectedOpton(); константа имеетЗначение = выбранныйИндекс >= 0 && выбраноОптон && selectedOpton.value !== «»; е (имеет значение) { ths.label.textContent = selectedOpton.textContent; ths.root.classLst.add(«s-selected»); ths.actveIndex = selectedOpton.dsabled ? ths.getFrstEnabledIndex() : выбранныйИндекс; } еще { ths.label.textContent = ths.placeholder; ths.root.classLst.remove(«s-selected»); ths.actveIndex = ths.getFrstEnabledIndex(); } ths.syncItemsState(); } syncItemsState() { ths.tems.forEach(({ el, natveOpton, dsabled }, ndex) => { е (dsabled) { el.removeAttrbute(«ara-selected»); } еще { el.setAttrbute( «ара-выбрано», Strng(natveOpton.selected) ); } el.classLst.toggle( «с-действовать», индекс === ths.actveIndex ); }); } setActive (индекс) { f (индекс < 0 || индекс >= ths.tems.length) return; f (ths.tems[ndex].dsabled) return; ths.actveIndex = индекс; ths.syncItemsState(); ths.tems[ndex].el.scrollIntoVew({block: «ближайший» }); } перемещение (дельта) { f (!ths.tems.length) return; пусть следующий = ths.actveIndex; f (следующий < 0) следующий = ths.getFrstEnabledIndex(); f (следующий < 0) возврат; пусть охранник = 0; сделать { следующий += дельта; f (следующий < 0) следующий = ths.tems.length - 1; е (следующий >= ths.tems.length) next = 0; охранник++; } пока ( ths.tems[next].dsabled && охранник = 0 && выбраноОптон && !selectedOpton.dsabled && selectedOpton.value !== «» ) { ths.actveIndex = selectedIndex; } еще { ths.actveIndex = ths.getFrstEnabledIndex(); } ths.sOpen = правда; ths.root.classLst.add(«s-open»); ths.button.setAttrbute(«ara-expanded», «true»); ths.syncItemsState(); f (ths.actveIndex >= 0) { ths.tems[ths.actveIndex].el.scrollIntoVew({ блок: «ближайший», }); } } закрыть (returnFocus = true) { ths.sOpen = ложь; ths.root.classLst.remove(«s-open»); ths.button.setAttrbute(«ara-expanded», «false»); f (returnFocus && !ths.sSelectDsabled()) { эта.кнопка.фокус(); } } рендер() { f (ths.sDestroyed) возврат; ths.sRenderng = правда; const wasOpen = ths.sOpen; ths.ensureButton(); ths.rebuldLst(); ths.syncDsabledState(); ths.syncSeletonFromNatve(); е (!wasOpen) { ths.close(ложь); } еще f (ths.sSelectDsabled()) { ths.close(ложь); } еще { ths.sOpen = правда; ths.root.classLst.add(«s-open»); ths.button.setAttrbute(«ara-expanded», «true»); ths.syncItemsState(); } ths.sRenderng = ложь; } уничтожить() { f (ths.sDestroyed) возврат; ths.sDestroyed = правда; ths.dsconnectObserver(); ths.unbnd(); ths.lst?.remove(); эта.кнопка?.remove(); ths.root.classLst.remove( «с-открыть», «s-выбрано», «s-dsabled» ); ИНСТАНЦИИ.delete(ths.root); } } functon ntEle2026Selects (область = документ) { return Array.from(scope.querySelectorAll(«[data-select]»)) .map((корень, индекс) =>новый Ele2026Select(корень, индекс)) .flter(логическое значение); } wndow.Ele2026Select = { nt: ntEle2026Выбирает, получить (корень) { return INSTANCES.get(root) || нулевой; }, уничтожить (корень) { const nstance = INSTANCES.get(root); f (nstance) nstance.destroy(); }, }; ntEle2026Выбирает(); })(); (асинхронная функция() { const SITEKEY = ‘ysc1_V3g8MjuvrVFqTJS4m1Qbde68seTWeD38k2dgofFV00d2c29c’ const ALREADY_VOTED = ‘ele2026_voted’ const GET_DATA_API = ‘/e2026/get’ const captchaReload = document.querySelector(‘.captcha-reload’) const voicesForm = document.querySelector(‘.ele2026_forecast’) const submtButton = voicesForm.querySelector(‘.ele2026_house__basement_button’) constarchveTpl = document.querySelector(‘#archve-template’) константная пустая форма = { yaCaptchaResponse: ноль, прогноз: { TurnoutGen: ноль, TurnoutHghRegId: ноль, TurnoutHghProc: ноль, TurnoutLowRegId: ноль, TurnoutLowProc: ноль, Хгествнрегид: ноль, ХгестВнПрок: ноль, Самый низкийWnRegId: ноль, Самый низкийWnProc: ноль, Макспартиинкид: ноль, Макспартиинккуан: ноль, ByPartyLstsRegId: ноль, Вечеринки: [], Regbypartylsts: [], } } пусть formData = JSON.parse(JSON.strngfy(emptyForm)) пусть captchaWdgetId = ноль пусть sCaptchaLoaded = ложь пусть sValdatonError = false пусть SAPIError = ложь пусть canSendForm = false пусть regonsLst = [] пусть partsLst = [] пусть userData = ноль пусть sArchveOpen = false пусть ArchveLst = [] пусть actveSectionId = ноль const getCooke = (имя) =>{ const match = document.cooke.match(new RegExp(‘(^| )’ + name + ‘=([^;]+)’)); вернуть совпадение ? match[2] : null; }; const setCooke = (имя, значение, секунды) =>{ пусть выражается = «»; е (секунды) { константная дата = новая дата(); date.setTme(date.getTme() + (секунды * 1000)); expres = «; expres=» + date.toUTCStrng(); } document.cooke = name + «=» + (value || «») + expres + «; path=/»; } const showCrtcalError = () =>{ let подвал = voicesForm.querySelector(‘.ele2026_house__basement’) f (!подвал) возврат подвал.nnerHTML = » пусть ошибка = document.createElement(‘p’) error.className = ‘ele2026_house__basement_error’ error.textContent = ‘Произошла неизвестная ошибка. Пожалуйста, обновите страницу или попробуйте проголосовать позже» подвал.append (ошибка) } const showSuccess = () =>{ const DoneSection = voicesForm.querySelector(‘.ele2026_forecast_done’) f (!doneSection) возврат DoneSection.classLst.remove(‘hdden’) voicesForm.querySelector(‘.ele2026_forecast__rules’)?.scrollIntoVew() } const showCommonError = (сообщение) => { let подвал = voicesForm.querySelector(‘.ele2026_house__basement’) f (!подвал) возврат подвал.querySelector(‘.ele2026_house__basement_error’)?.remove() пусть ошибка = document.createElement(‘p’) error.className = ‘ele2026_house__basement_error’ error.textContent = сообщение подвал.append (ошибка) } const showNotAuthorzed = () =>{ showCommonError(‘Войдите, чтобы проголосовать’) } const showServerValdatonError = (errorObj) =>{ Object.keys(errorObj).forEach(f => { const feld = f.replace(‘прогноз.’, ») const msg = errorObj[f][0] пусть ФельдЭл f (feld === ‘Partylstres’) { feldEl = voicesForm.querySelector(‘[data-queston-d=»4″]’) } else f (feld === ‘Partylstres’) { feldEl = voicesForm.querySelector(‘[data-queston-d=»5″]’) } еще { feldEl = voicesForm.querySelector(`[name=»${feld}»]`) } submtError (feldEl, сообщение) feldEl.scrollIntoVew() }) } const fetchData = async (url, sCrtcal = false) =>{ попробуй { константный ответ = awat fetch (url) е (ответ.редректированный) { показатьNotAuthorized() вернуть ноль } е (!response.ok) { выдать новую ошибку(`Статус ${response.status}`) } return (AWAT response.json()) || ноль } поймать (ошибка) { е (sCrtcal) { SAPIError = правда showCrtcalError() выдать новую ошибку(`Ошибка получения данных: ${error.message}`) } } } const getCatalogData = async (catalogId) => { return awat fetchData(`https://wt.kommersant.ru/ap/v1/catalog/get?catalogId=${catalogId}&start=0&lmt=1000`, true) } const getChartData = асинхронный (метод) =>{ return awat fetchData(`/e2026/${method}`) } const getRegonsLst = async() =>{ regonsLst = (awat getCatalogData(122))?.data f (!regonsLst?.length) { SAPIError = правда showCrtcalError() } еще { regonsLst = regonsLst.flter(r => r.IsShow) } } const getPartesLst = async() => { partesLst = (awat getCatalogData(1319))?.data f (!partesLst?.length) { SAPIError = правда showCrtcalError() } еще { partesLst = partesLst.flter(r => r.IsShow) } } const flllRegons = (селектор) => { regonsLst.forEach(regon =>{ f (!regon.IsShow) возврат пусть opton = document.createElement(‘opton’) opton.textContent = regon.Name opton.d = regon.Id selector.appendChld(оптон) }) } const fllPartes = (селектор) => { partesLst.forEach(party => { f (!party.IsShow) возврат пусть opton = document.createElement(‘opton’) opton.textContent = party.Name opton.d = party.Id selector.appendChld(оптон) }) } const fllNotSelectedPartes = (newGroup) => { const secton_5 = voicesForm.querySelector(‘[data-queston-d=»5″]’) const allGroups = secton_5.querySelectorAll(‘.ele2026_house__group’) const allSelectedPartes = [] //сохраняем все уже выбранные игры в вопросе №5 allGroups.forEach(группа =>{ const partyId = +group.querySelector(‘select’)?.optonId || ноль !!partyId && allSelectedPartes.push(partyId) }) allSelectedPartes.length === partsLst.length ? secton_5.querySelector(‘.ele2026_house__brck_add’).classLst.add(‘hdden’) : secton_5.querySelector(‘.ele2026_house__brck_add’).classLst.remove(‘hdden’) const fllInnerGroup = (группа) =>{ const selector = group.querySelector(‘select’) ?? группа const partyId = +selector?.optonId || ноль whle(selector.frstChld) { selector.removeChld(selector.frstChld); } //сначала добавляем заполнитель пусть opton = document.createElement(‘opton’) opton.textContent = ‘Вечеринка’ оптон.значение = «» е (!partyId) { opton.selected = правда } selector.appendChld(оптон) partesLst.forEach(party => { f (allSelectedPartes.ncludes(party.Id) && party.Id !== partyId) return пусть opton = document.createElement(‘opton’) opton.textContent = party.Name opton.d = party.Id е (party.Id === partyId) { opton.selected = правда selector.optonId = идентификатор вечеринки } selector.appendChld(оптон) }) } //заполняем выпадающие списки партий без учета ранее выбранных allGroups.forEach(fllInnerGroup) !!newGroup && fllInnerGroup(новаягруппа) } const fllSelectors = () =>{ voicesForm.querySelectorAll(‘.ele2026_select__regon’).forEach(fllRegons) voicesForm.querySelectorAll(‘.ele2026_select__party’).forEach(fllPartes) } const sToday = (someDate) => { f (!someDate) return; const getDate = новая дата(+someDate) f (!(getDate nstanceof Date) || sNaN(getDate.getTme())) return const сегодня = новая дата(); return getDate.getDate() === Today.getDate() && getDate.getMonth() === Today.getMonth() && getDate.getFullYear() === Today.getFullYear(); } const captchaLoad = () => { const eleCaptchaContaner = voicesForm.querySelector(‘.js-lk-form-restore-captcha-contaner’) captchaWdgetId = wndow.smartCaptcha.render(eleCaptchaContaner, { обратный вызов: (токен) =>{ f (typeof token === ‘strng’ && token.length >0) { formData.yaCaptchaResponse = токен отправитьДанные() } wndow.smartCaptcha.reset(captchaWdgetId); }, гл: ‘ру’, нвсбле: правда, стекки: SITEKEY, вебвью: wndow.kommersant.sWebVew, }); sCaptchaLoaded = правда; }; функция startCountdown (tmestamp) { функция formatTme(ms) { const totalSeconds = Math.max(0, Math.floor(ms/1000)); const часы = Math.floor(totalSeconds/3600); const mnutes = Math.floor((totalSeconds % 3600)/60); константные секунды = TotalSeconds% 60; вернуть [ Strng(часы).padStart(2, ‘0’), Strng(минуты).padStart(2, ‘0’), Strng(секунды).padStart(2, ‘0’) ].jon(‘:’); } функция updateButton (кнопка) { const dff = tmestamp — Date.now() f (dff { const mustContnue = updateButton(submtButton) е (!shouldContnue) { ClearInterval (tmerId) } }, 1000) } const EnableVotng = () => { voicesForm.querySelectorAll(` .ele2026_feld > вход, select.ele2026_select__natve, button.ele2026_house__basement_button `)?.forEach(el =>el.dsabled = ложь) submtButton.classLst.remove(‘s_countdown’) submtButton.dsabled = ложь submtButton.textContent = ‘Отправить голос’ voicesForm.querySelectorAll(‘.ele2026_house__basement_note’).forEach(note =>{ note.classLst.contans(‘общий’) ? note.classLst.remove(‘hdden’) : note.classLst.add(‘hdden’) }) } const dsableVotng = (sCountng = false) => { е(sCountng) { const завтра = новая дата() завтра.setDate((новая дата()).getDate() + 1) завтра.setHours(0, 0, 0, 0) startCountdown(завтра) } voicesForm.querySelectorAll(` .ele2026_feld > вход, select.ele2026_select__natve, button.ele2026_house__basement_button `)?.forEach(el => el.dsabled = true) } const loadScrpt = (url) => { вернуть новое обещание((разрешить, отклонить) =>{ е (wndow.Hghcharts) { вернуть решение (wndow.Hghcharts); } let scrpt = document.createElement(‘scrpt’); scrpt.src = URL; scrpt.async = правда; document.head.appendChld(сценарий); константа lmt = 10; пусть повторит = 0; const ntervalID = setInterval(() => { е (wndow.Hghcharts) { ClearInterval (ID интервала); разрешить (wndow.Hghcharts); } else f (++retry >= lmt) { ClearInterval (ID интервала); ignore(new Error(‘Превышен лимит времени загрузки Hghcharts’)); } }, 500); }); }; const ntHghcharts = async () =>{ попробуй { awat loadScrpt(‘https://v.kommersant.ru/ContentFlex/js/custom/lbs/hghchats/hghcharts-v12.5.0.js’); } поймать (ошибка) { showCrtcalError() console.log(ошибка) throw new Error(‘Ошибка загрузки hghcharts.js’); } } const drawChartTurnout = (rawData) => { const secton = voicesForm.querySelector(`[data-queston-d=»1″]`) f (!section || !rawData?.length) return secton.querySelector(‘.ele2026_house__meda’)?.classLst.remove(‘hdden’) const formatedData = rawData.map((tem) =>{ вернуть [ новая дата(tem.date).getTme(), +tem.val ] }) Hghcharts.chart(section.querySelector(‘.ele2026_house__meda_chart’), { немного: { текст: незащищенный }, yAxs: { немного: { включено: ложь, }, ярлыки: { формат: ‘{value}%’, }, }, инструментp: { valueSuffx: ‘%’, }, хАкс: { введите: ‘dateme’, ярлыки: { форматтер: functon() { const curDate = новая дата (ths.value) return curDate.toLocaleStrng(‘ru-RU’, { день: ‘число’, месяц: ‘длинный’ }) } } }, сюжетОптонс: { серия: { метка: { ConnectorAllowed: ложь, }, маркер: { включено: ложь, }, } }, серия: [{ название: «Общая явка», данные: форматированные данные, }], }) } const getMaxVotes = (данные) => { вернуть data.reduce((a, b) =>{ let frst = новая дата(a?.count ?? a).getTme() пусть секунда = новая дата(b?.count ?? b).getTme() вернуть Math.max(первый, второй) }) } const getMnVal = (данные) => { return data.reduce((a, b) =>{ let frst = новая дата(a?.date ?? a).getTme() let второй = новая дата(b?.date ?? b).getTme() вернуть Math.mn(первый, второй) }) } //возвращает 5 лучших объектов по количеству голосов за все время //+ объект, за который проголосовал пользователь //всего: 6 (!) объектов или меньше const getTopFve = (данные, userObjectId) => { const ObjectId = Object.keys(данные) f (objectsId?.length +o) константные голоса = идентификатор объекта .map(d => {return { d, voices: getMaxVotes(data[d]) }}) .sort((a, b) => b.votes — a.votes) .flter(a => +ad !== +userObjectId) //оп 5 по количеству голосов const topFve = voices.slce(0, 5).map(v =>+в.д) //+ пользовательский объект !!userObjectId && topFve.push(+userObjectId) вернуться в топFve } const drawChart = (rawData, sId, userData) => { const secton = voicesForm.querySelector(`[data-queston-d=»${sId}»]`) const sPartySection = sId === 8 const каталог = [4, 5, 8].ncludes(sId) ? partesLst : regonsLst f (!section || !rawData?.length) return пусть regonsData = {} rawData.forEach(данные =>{ const regonAsIndex = data.objectId.toStrng() е (!regonsData[regonAsIndex]) { regonsData[regonAsIndex] = [] } regonsData[regonAsIndex].push(данные) }) const topFveRegons = getTopFve(regonsData, userData) константная серия = [] const objectId = Object.keys(regonsData) objectId.forEach(d =>{ const objId = +d f(!topFveRegons.ncludes(objId)) return const currentObjectName = каталог.fnd(объект => object.Id === objId)?.Name const currentObjectColor= каталог.fnd(object => object.Id === objId)?.color || ноль const formatedData = regonsData[objId.toStrng()].map((tem) =>{ вернуть [ новая дата(tem.date).getTme(), +tem.val ] }) const LastValueId = formatedData.length — 1 const LastValue = […formatedData[lastValueId]] formatedData[lastValueId] = { х: последнее значение [0], y: последнее значение[1], маркер: { включено: правда, символ: «бриллиант», } } //добавляем фиктивные данные «на сегодня», чтобы графики не ломались f (!sToday(new Date(lastValue[0]).getTme())) { //удаляем маркер с последнего значения, потому что оно уже не последнее formatedData[lastValueId].marker.enabled = false константные параметры = { день недели: ‘длинный’, день: ‘число’, месяц: ‘длинный’, год: ‘число’ } //хак, чтобы «сегодня» соответствовало серверу const сегодня = новая дата(Date.now()).toISOStrng().splt(‘T’)[0] //добавляем фиктивное «на сегодня» formatedData.push({ x: новая дата(сегодня).getTme(), y: последнее значение[1], маркер: { включено: правда, символ: «бриллиант», }, имя: `Значение:${new Intl.DateTmeFormat(‘ru-RU’, optons).format(lastValue[0])}`, }) } seres.push({ имя: имя текущего объекта, цвет: текущийОбъектКолор, данные: форматированные данные, }) }) secton.querySelector(‘.ele2026_house__meda’)?.classLst.remove(‘hdden’) Hghcharts.chart(section.querySelector(‘.ele2026_house__meda_chart’), { немного: { текст: незащищенный }, yAxs: { немного: { включено: ложь, }, ярлыки: { формат: `{value}${sPartySection ? » : ‘%’}`, }, }, инструментp: { valueSuffx: `${sPartySecton ? » : ‘%’}`, }, хАкс: { введите: ‘dateme’, ярлыки: { форматтер: functon() { const curDate = новая дата (ths.value) return curDate.toLocaleStrng(‘ru-RU’, { день: ‘число’, месяц: ‘длинный’ }) } } }, сюжетОптонс: { серия: { метка: { ConnectorAllowed: ложь, }, маркер: { включено: ложь, символ: «бриллиант», }, } }, сериал, }) } const showStatstcs = async() =>{ f (!userData) возврат console.log(‘*********’) console.log(данные пользователя) console.log(‘*********’) //Вопрос №1 f (userData.TurnoutGen !== undefned) { constchartData = awat fetchData(‘/e2026/getturnoutstats’) chartData?.data?.length >0 && drawChartTurnout(chartData.data) } //Вопрос №2 f (userData.TurnoutHghRegId !== undefned && userData.TurnoutHghProc !== undefned) { constchartData = awat fetchData(‘/e2026/gettopregonforecast’) chartData?.data?.length > 0 && drawChart(chartData.data, 2, userData.TurnoutHghRegId) } //Вопрос №3 f (userData.TurnoutLowRegId !== не определено && userData.TurnoutLowProc !== не определено) { constchartData = awat fetchData(‘/e2026/getlowestturnoutregon’) chartData?.data?.length > 0 && drawChart(chartData.data, 3, userData.TurnoutLowRegId) } //Вопрос №4 f (userData.Partylstres?.length >0) { constchartData = awat fetchData(‘/e2026/getpartycountrystats’) chartData?.data?.length > 0 && drawChart(chartData.data, 4) } //Вопрос №5 f (userData.ByPartyLstsRegId !== undefned && userData.Regbypartylsts?.length > 0) { constchartData = awat fetchData(`/e2026/getspecfcregonstats/${userData.ByPartyLstsRegId}`) chartData?.data?.length > 0 && drawChart(chartData.data, 5) } //Вопрос №6 f (userData.HghestWnRegId !== undefned && userData.HghestWnProc !== undefned) { constchartData = awat fetchData(‘/e2026/getmaxwnnerresult’) chartData?.data?.длина >0 && drawChart(chartData.data, 6, userData.HghestWnRegId) } //Вопрос №7 console.log(‘—————‘) console.log(userData.LowestWnRegId) console.log(‘—————‘) f (userData.LowestWnRegId !== не определено && userData.LowestWnProc !== не определено) { constchartData = awat fetchData(‘/e2026/getmnwnnerresult’) chartData?.data?.length > 0 && drawChart(chartData.data, 7, userData.LowestWnRegId) } //Вопрос №8 f (userData.MaxPartyIncId !== undefned && userData.MaxPartyIncQuan !== undefned) { constchartData = awat fetchData(‘/e2026/getmaxpartyncrease’) chartData?.data?.length > 0 && drawChart(chartData.data, 8, userData.MaxPartyIncId) } } const actvateGroups = (newGroup) => { const hdeError = (группа) =>{ group.querySelectorAll(‘.ele2026_feld__error’)?.forEach(el =>el.remove()) group.querySelectorAll(‘.ele2026_house__brck—error’)?.forEach(el => el.classLst.remove(‘ele2026_house__brck—error’)) } const watchChanges = (группа) => { const selector = group.querySelector(‘select’) group.querySelector(‘nput’).dsabled = !selector?.value selector.addEventLstener(‘change’, (evt) =>{ const currentGroup = evt.target.closest(‘.ele2026_house__group’) const nput = currentGroup.querySelector(‘nput’) const selectedValue = evt.target?.value || » hdeError (текущая группа) е (!selectedValue) { nput.value = » } nput.dsabled = !selectedValue }) } !!новая группа ? WatchChanges(newGroup) : voicesForm.querySelectorAll(‘.ele2026_house__group’).forEach(watchChanges) } const actvateQueston4 = () => { drawPartesBox(partesLst.slce(0, 5), ‘ele2026_partes’) //зависаем рендеринг остальных игр f (partesLst.length > 5) { voicesForm.querySelector(‘.ele2026_partes__label’).classLst.remove(‘hdden’) const showAllPartesTrgger = voicesForm.querySelector(‘.ele2026_partes__trgger’) showAllPartesTrgger.addEventLstener(‘change’, e =>{ voicesForm.querySelector(‘.ele2026_partes__roll_box’).chldElementCount === 0 && drawPartesBox( partesLst .slce(5) .sort((a, b) =>a.Name.replace(‘«’, »).localeCompare(b.Name.replace(‘«’, »))), ‘ele2026_partes__roll_box’ ) f (sToday(getCooke(ALREADY_VOTED)) || sToday(new Date(userData?.ForecastDate).getTme())) { dsableVotng() } }) } } const actvateQueston5 = () => { const secton_5 = voicesForm.querySelector(‘[data-queston-d=»5″]’) const regonSelect = secton_5.querySelector(‘select[name=»ByPartyLstsRegId»]’) const hdeError = (группа) => { group.querySelectorAll(‘.ele2026_feld__error’)?.forEach(el => el.remove()) group.querySelectorAll(‘.ele2026_house__brck—error’)?.forEach(el =>el.classLst.remove(‘ele2026_house__brck—error’)) } const swtchGroupsAccess = () =>{ const regonSelectValue = regonSelect?.optonId || » secton_5.querySelectorAll(‘.ele2026_house__group’)?.forEach(group =>{ е (!regonSelectValue) { е (group.classLst.contans(‘s_removable’)) { группа.удалить() возвращение } еще { hdeError (группа) group.querySelector(‘select[name=»PartyId»]’).optonId = » group.querySelector(‘select[name=»PartyId»]’).value = » group.querySelector(‘nput[name=»VotesProc»]’).value = » } } group.querySelector(‘select[name=»PartyId»]’).dsabled = !regonSelectValue group.querySelector(‘nput[name=»VotesProc»]’).dsabled = !regonSelectValue }) secton_5.querySelector(‘button.ele2026_house__brck_add’).dsabled = !regonSelectValue } переключатель групп доступа () regonSelect.addEventLstener(‘change’, (evt) => swtchGroupsAccess()) secton_5.querySelectorAll(‘.ele2026_house__group’)?.forEach(group => { group.querySelector(‘select[name=»PartyId»]’).addEventLstener(‘change’, e =>фллнотселектедпартес()) }) //штука отвечает за добавление новой группы/входной группы в вопросе №5 (вайберкод от Лехи) const addButton = document.querySelector(‘.ele2026_house__brck_add’); const template = document.querySelector(‘#party-template’); f (!addButton || !template) return; addButton.addEventLstener(‘clck’, () => { const clone = template.content.cloneNode(true); clone.querySelectorAll(‘.ele2026_select__party’).forEach(partySelector => { flllNotSelectedPartes (partySelector) partySelector.addEventLstener(‘change’, e => flllNotSelectedPartes()) }) addButton.before(клон); const newBlock = addButton.prevousElementSblng; ntEle2026Felds(newBlock); wndow.Ele2026Select.nt(newBlock); actvateGroups(newBlock.querySelector(‘.ele2026_house__group’)) }); document.addEventLstener(‘clck’, (событие) =>{ const removeButton = event.target.closest(‘.ele2026_house__brck_remove’); f (!removeButton) возврат; const RemoveBlock = RemoveButton.closest(‘.s_removable’); f (!removableBlock) return; const selectRoot = съемныйBlock.querySelector(‘[data-select]’); е (selectRoot) { wndow.Ele2026Select.destroy(selectRoot); } съемныйБлок.удалить(); фллнотселектедпартес() }); } const drawPartesBox = (partes, оберткаSelector) =>{ const secton_4 = voicesForm.querySelector(‘[data-queston-d=»4″]’) const partesWrapper = secton_4.querySelector(`.${wrapperSelector}`) const partyBoxTemplate = document.querySelector(‘#party-box’) f (!partesWrapper || !section_4 || !partyBoxTemplate) return partes.reverse().forEach(party =>{ const partyBox = partyBoxTemplate.content.cloneNode(true) partyBox.querySelector(‘.ele2026_partes__tem’).dataset.partyId = party.Id е(party.logo) { partyBox.querySelector(‘mg’).src = party.logo partyBox.querySelector(‘mg’).alt = party.Name } partyBox.querySelector(‘h3’).textContent = party.Name partyWrapper.prepend(partyBox) }) ntEle2026Filds(section_4) } const submtError = (field, msg) =>{ пусть ошибка = document.createElement(‘p’) error.className = ‘ele2026_feld__error’ feld.appendChld (ошибка) error.textContent = сообщение feld.classLst.add(‘ele2026_house__brck—error’) formData.yaCaptchaResponse = ноль captchaReload?.trgger(‘clck’) } const RemoveAllErrors = () => { voicesForm.querySelectorAll(‘.ele2026_feld__error’).forEach(e => e.remove()) voicesForm.querySelectorAll(‘.ele2026_house__brck—error’).forEach(feld => feld.classLst.remove(‘ele2026_house__brck—error’)) } const valdatePercent = (значение, поле) =>{ f (!value) возвращает ноль пусть ответ = value.replace(/s/g, ») ответ = parseFloat(answer.replace(‘,’, ‘.’)) ответ = truncateNumber(ответ) пусть errorMsg = ноль е (!ответ && ответ !== 0) { errorMsg = ‘Можно вводить только цифры’ } е (ответ < 0) { errorMsg = 'Значение должно быть не менее 0' } е (ответ >100) { errorMsg = ‘Значение должно быть меньше 100’ } е (!!errorMsg) { сВалдатонError = правда !!фельд && submtError(field, errorMsg) } обратный ответ } const valdateNum = (значение, поле) => { f (!value) возвращает ноль пусть ответ = parseInt(value.replace(/s/g, »)) пусть errorMsg = ноль е (!ответ && ответ !== 0) { errorMsg = ‘Можно вводить только цифры’ } е (ответ < 0) { errorMsg = 'Значение должно быть не менее 0' } е (ответ >450) { errorMsg = ‘Значение должно быть меньше 450’ } е (!!errorMsg) { сВалдатонError = правда !!фельд && submtError(field, errorMsg) } обратный ответ } const valdateRegon = (значение, поле) => { f (!value) возвращает ноль пусть ответ = parseInt (значение) ответ = regonsLst.fnd(regon => { вернуть regon.Id === ответ }) ? ответ: ноль е (!ответ) { сВалдатонError = правда !!фельд && submtError(feld, «Субъект Российской Федерации не найден») } обратный ответ } const valdateParty = (значение, поле) => { f (!value) возвращает ноль пусть ответ = parseInt (значение) ответ = partesLst.fnd(party =>{ вернуть party.Id === ответ }) ? ответ: ноль е (!ответ) { сВалдатонError = правда !!фельд && submtError(feld, «Пакет не найден») } обратный ответ } const getAllFormData = () =>{ formData = JSON.parse(JSON.strngfy(emptyForm)) //Вопрос №1 const secton_1 = voicesForm.querySelector(‘[data-queston-d=»1″]’) const feld_1 = secton_1.querySelector(‘nput[name=»TurnoutGen»]’) formData.forecast.TurnoutGen = valdatePercent(feld_1?.value || », feld_1.closest(‘.ele2026_house__brck’)) canSendForm = canSendForm || (formData.forecast.TurnoutGen !== ноль) //Вопрос №2 const secton_2 = voicesForm.querySelector(‘[data-queston-d=»2″]’) const feld_2_1 = secton_2.querySelector(‘select[name=»TurnoutHghRegId»]’) formData.forecast.TurnoutHghRegId = valdateRegon(feld_2_1?.optonId || », feld_2_1.closest(‘.ele2026_house__brck’)) е (formData.forecast.TurnoutHghRegId !== ноль) { const feld_2_2 = secton_2.querySelector(‘nput[name=»TurnoutHghProc»]’) f (!feld_2_2?.value && feld_2_2?.value !== 0) { сВалдатонError = правда submtError(feld_2_2.closest(‘.ele2026_house__brck’), ‘Поле не может быть пустым’) } еще { formData.forecast.TurnoutHghProc = valdatePercent(feld_2_2.value, feld_2_2.closest(‘.ele2026_house__brck’)) } } canSendForm = canSendForm || (formData.forecast.TurnoutHghRegId !== null && formData.forecast.TurnoutHghProc !== null) //Вопрос №3 const secton_3 = voicesForm.querySelector(‘[data-queston-d=»3″]’) const feld_3_1 = secton_3.querySelector(‘select[name=»TurnoutLowRegId»]’) formData.forecast.TurnoutLowRegId = valdateRegon(feld_3_1?.optonId || », feld_3_1.closest(‘.ele2026_house__brck’)) е (formData.forecast.TurnoutLowRegId! == ноль) { const feld_3_2 = secton_3.querySelector(‘nput[name=»TurnoutLowProc»]’) f (!feld_3_2?.value && feld_3_2?.value !== 0) { сВалдатонError = правда submtError(feld_3_2.closest(‘.ele2026_house__brck’), ‘Поле не может быть пустым’) } еще { formData.forecast.TurnoutLowProc = valdatePercent(feld_3_2.value, feld_3_2.closest(‘.ele2026_house__brck’)) } } canSendForm = canSendForm || (formData.forecast.TurnoutLowRegId !== null && formData.forecast.TurnoutLowProc !== null) //Вопрос №4 const secton_4 = voicesForm.querySelector(‘[data-queston-d=»4″]’) const partes_4 = secton_4.querySelectorAll(‘.ele2026_partes__tem’) partes_4.forEach(partyBox =>{ const feld_4_2 = partyBox.querySelector(‘nput[name=»VotesProc»]’) const feld_4_2_value = valdatePercent(feld_4_2?.value || », feld_4_2.closest(‘.ele2026_house__brck’)) f (!!feld_4_2_value || feld_4_2_value === 0) { const partyData = { PartyId: valdateParty(parseInt(partyBox?.dataset?.partyId || »)), VotesProc: feld_4_2_value } !!partyData.PartyId && formData.forecast.Partylstres.push(partyData) } }) canSendForm = canSendForm || (formData.forecast.Partylstres?.length > 0) //Вопрос №5 const secton_5 = voicesForm.querySelector(‘[data-queston-d=»5″]’) const feld_5_1 = secton_5.querySelector(‘select[name=»ByPartyLstsRegId»]’) formData.forecast.ByPartyLstsRegId = valdateRegon(feld_5_1?.optonId || », feld_5_1.closest(‘.ele2026_house__brck’)) е (formData.forecast.ByPartyLstsRegId!== null) { const partes_5 = secton_5.querySelectorAll(‘.ele2026_house__group’) partes_5.forEach(partyBox =>{ const feld_5_2 = partyBox.querySelector(‘select[name=»PartyId»]’) const feld_5_2_value = valdateParty(feld_5_2?.optonId || », feld_5_2.closest(‘.ele2026_house__brck’)) const feld_5_3 = partyBox.querySelector(‘nput[name=»VotesProc»]’) const feld_5_3_value = valdatePercent(feld_5_3?.value || », feld_5_3.closest(‘.ele2026_house__brck’)) f ((!!feld_5_3_value || feld_5_3_value === 0) && !!feld_5_2_value) { const partyData = { Идентификатор вечеринки: feld_5_2_value, ГолосованиеProc: feld_5_3_value } !!partyData.PartyId && formData.forecast.Regbypartylsts.push(partyData) } }) //если вы выбрали только регион, а потом не голосовали за партии, считаем недействительным f (!formData.forecast.Regbypartylsts?.length) { сВалдатонError = правда submtError( secton_5.querySelector(‘select[name=»PartyId»]’).closest(‘.ele2026_house__brck’), «Нужно сделать прогноз хотя бы на одну игру» ) } } canSendForm = canSendForm || (formData.forecast.ByPartyLstsRegId !== null && formData.forecast.Regbypartylsts?.length >0) //Вопрос №6 const secton_6 = voicesForm.querySelector(‘[data-queston-d=»6″]’) const feld_6_1 = secton_6.querySelector(‘select[name=»HghestWnRegId»]’) formData.forecast.HghestWnRegId = valdateRegon(feld_6_1?.optonId || », feld_6_1.closest(‘.ele2026_house__brck’)) е (formData.forecast.HghestWnRegId!== null) { const feld_6_2 = secton_6.querySelector(‘nput[name=»HghestWnProc»]’) f (!feld_6_2?.value && feld_6_2?.value !== 0) { сВалдатонError = правда submtError(feld_6_2.closest(‘.ele2026_house__brck’), ‘Поле не может быть пустым’) } еще { formData.forecast.HghestWnProc = valdatePercent(feld_6_2.value, feld_6_2.closest(‘.ele2026_house__brck’)) } } canSendForm = canSendForm || (formData.forecast.HghestWnRegId !== null && formData.forecast.HghestWnProc !== null) //Вопрос №7 const secton_7 = voicesForm.querySelector(‘[data-queston-d=»7″]’) const feld_7_1 = secton_7.querySelector(‘select[name=»LowestWnRegId»]’) formData.forecast.LowestWnRegId = valdateRegon(feld_7_1?.optonId || », feld_7_1.closest(‘.ele2026_house__brck’)) е (formData.forecast.LowestWnRegId!== null) { const feld_7_2 = secton_7.querySelector(‘nput[name=»LowestWnProc»]’) f (!feld_7_2?.value && feld_7_2?.value !== 0) { сВалдатонError = правда submtError(feld_7_2.closest(‘.ele2026_house__brck’), ‘Поле не может быть пустым’) } еще { formData.forecast.LowestWnProc = valdatePercent(feld_7_2?.value || », feld_7_2.closest(‘.ele2026_house__brck’)) } } canSendForm = canSendForm || (formData.forecast.LowestWnRegId !== null && formData.forecast.LowestWnProc !== null) //Вопрос №8 const secton_8 = voicesForm.querySelector(‘[data-queston-d=»8″]’) const feld_8_1 = secton_8.querySelector(‘select[name=»MaxPartyIncId»]’) formData.forecast.MaxPartyIncId = valdateParty(feld_8_1?.optonId || », feld_8_1.closest(‘.ele2026_house__brck’)) е (formData.forecast.MaxPartyIncId !== null) { const feld_8_2 = secton_8.querySelector(‘nput[name=»MaxPartyIncQuan»]’) f (!feld_8_2?.value && feld_8_2?.value !== 0) { сВалдатонError = правда submtError(feld_8_2.closest(‘.ele2026_house__brck’), ‘Поле не может быть пустым’) } еще { formData.forecast.MaxPartyIncQuan = valdateNum(feld_8_2?.value || », feld_8_2.closest(‘.ele2026_house__brck’)) } } canSendForm = canSendForm || (formData.forecast.MaxPartyIncId !== null && formData.forecast.MaxPartyIncQuan !== null) } const rentSelector = (раздел, значение) => { secton.querySelector(‘select’).dsabled = false const currentSelector = wndow.Ele2026Select.nt(section)[0] currentSelector.natve.selectedIndex = currentSelector.tems.fnd( => +.natveOpton.d === +value)?.ndex currentSelector.natve.optonId = +значение currentSelector.onNatveChange() } const checkUser = () => { f (!!wndow.kommersant?.user?.sAuthorzed) { вернуть истину } еще { dsableVotng() voicesForm.querySelectorAll(‘.ele2026_house__basement_note’).forEach(note =>{ note.classLst.contans(‘not_authorzed’) ? note.classLst.remove(‘hdden’) : note.classLst.add(‘hdden’) }) //если пользователь пытается кликнуть в поле формы, мы отправляем его на вход voicesForm.querySelectorAll(‘.ele2026_house__brck, .ele2026_house__basement, .ele2026_forecast__header, .ele2026_partes__label’).forEach(el => { el.classLst.add(‘войти в систему для голосования’) //закрываем отключенные элементы занавесом, чтобы можно было перехватить события const fakeInput = document.createElement(‘dv’) fakeInput.className = ‘catch-logn’ fakeInput.addEventLstener(‘clck’, (e) =>{ е.preventDefault() е.stopPropagaton() wndow.kommersant.user.logout() wndow.kommersant.user.logn({ from: ‘vote2026’ }) wndow.kommersant.sendEvent(‘пользователь’, ‘вход’, ‘из-dsabled-form’) }) el.appendChld(fakeInput) }) //если пользователь вошел в систему, инициируем форму wndow.addEventLstener(‘kommersant:authorzed’, () => { console.log(‘Пользователь авторизован. Форма Int’) включитьVotng() //снимаем все шторки для входа в систему voicesForm.querySelectorAll(‘.catch-logn’).forEach(el => el.remove()) voicesForm.querySelectorAll(‘.logn-to-vote’).forEach(el =>el.classLst.remove(‘войти для голосования’)) активироватьПользователь() //на всякий случай пролистываем в начало формы voicesForm.querySelector(‘.ele2026_forecast__rules’)?.scrollIntoVew() }) } } const actvateUser = async() =>{ //прежде чем идти дальше, проверим, авторизован ли пользователь. Возможно, вам больше ничего не придется делать е (!checkUser()) возвращение //загружаем на страницу Hghcharts ожидайте ntHghcharts() //перетаскиваем данные последнего голосования пользователя из API, показываем статистику awat fllWthUserData() //если пользователь уже проголосовал сегодня, заблокируйте форму f (sToday(getCooke(ALREADY_VOTED)) || sToday(new Date(userData.ForecastDate).getTme())) { console.log(‘Уже проголосовали’) dsableVotng (правда) возвращение } //получим капчу для отправки формы е (wndow.smartCaptcha) { капчаЗагрузка() } еще { wndow.smartCaptchaOnload = () => !!wndow.smartCaptcha && капчаЗагрузка() } //событие отправки формы submtButton.addEventLstener(‘clck’, submtForm) //если пользователь вдруг решит выйти, заблокируем форму wndow.addEventLstener(‘kommersant:unauthorzed’, () => { console.log(‘Пользователь не авторизован. Заблокировать форму’) dsableVotng() показатьNotAuthorized() }) } const fllWthUserData = асинхронный () =>{ f (!wndow.kommersant?.user?.sAuthorzed) { возвращение } userData = awat fetchData (GET_DATA_API, true) f (!userData || !userData.ForecastDate) return //Вопрос №1 f (userData.TurnoutGen !== undefned) { const secton_1 = voicesForm.querySelector(‘[data-queston-d=»1″]’) secton_1.querySelector(‘nput[name=»TurnoutGen»]’).value = userData.TurnoutGen } //Вопрос №2 f (userData.TurnoutHghRegId !== undefned && userData.TurnoutHghProc !== undefned) { const secton_2 = voicesForm.querySelector(‘[data-queston-d=»2″]’) const feld_2 = secton_2.querySelector(‘nput[name=»TurnoutHghProc»]’) rentSelector(section_2, userData.TurnoutHghRegId) feld_2.value = userData.TurnoutHghProc feld_2.dsabled = ложь } //Вопрос №3 f (userData.TurnoutLowRegId !== не определено && userData.TurnoutLowProc !== не определено) { const secton_3 = voicesForm.querySelector(‘[data-queston-d=»3″]’) const feld_3 = secton_3.querySelector(‘nput[name=»TurnoutLowProc»]’) rentSelector(section_3, userData.TurnoutLowRegId) feld_3.value = userData.TurnoutLowProc feld_3.dsabled = ложь } //Вопрос №4 f (userData.Partylstres?.length > 0) { const secton_4 = voicesForm.querySelector(‘[data-queston-d=»4″]’) const partes_4 = secton_4.querySelectorAll(‘.ele2026_partes__tem’) userData.Partylstres.forEach(party => { partes_4.forEach(el =>{ f (+el.dataset.partyId === +party.PartyId) el.querySelector(‘nput[name=»VotesProc»]’).value = party.VotesProc }) }) } //Вопрос №5 f (userData.ByPartyLstsRegId !== undefned && userData.Regbypartylsts?.length > 0 !== undefned) { const secton_5 = voicesForm.querySelector(‘[data-queston-d=»5″]’) const addButton = document.querySelector(‘.ele2026_house__brck_add’); rentSelector(section_5, userData.ByPartyLstsRegId) const allGroups = secton_5.querySelectorAll(‘.ele2026_house__group’) addButton.dsabled = ложь const setGroupData = (группа, данные) =>{ const feld = group.querySelector(‘nput[name=»VotesProc»]’) rentSelector(группа, data.PartyId) feld.value = data.VotesProc feld.dsabled = ложь group.classLst.add(‘заполнено’) } userData.Regbypartylsts.forEach((party, ) =>{ е (!!allGroups[]) { setGroupData(allGroups[], party) } еще { addButton.clck() const newGroup = secton_5.querySelector(‘.ele2026_house__group:not(.flled)’) setGroupData (новая группа, вечеринка) } }) фллнотселектедпартес() } //Вопрос №6 f (userData.HghestWnRegId !== undefned && userData.HghestWnProc !== undefned) { const secton_6 = voicesForm.querySelector(‘[data-queston-d=»6″]’) const feld_6 = secton_6.querySelector(‘nput[name=»HghestWnProc»]’) rentSelector(section_6, userData.HghestWnRegId) feld_6.value = userData.HghestWnProc feld_6.dsabled = ложь } //Вопрос №7 f (userData.LowestWnRegId !== не определено && userData.LowestWnProc !== не определено) { const secton_7 = voicesForm.querySelector(‘[data-queston-d=»7″]’) const feld_7 = secton_7.querySelector(‘nput[name=»LowestWnProc»]’) rentSelector(section_7, userData.LowestWnRegId) feld_7.value = userData.LowestWnProc feld_7.dsabled = ложь } //Вопрос №8 f (userData.MaxPartyIncId !== undefned && userData.MaxPartyIncQuan !== undefned) { const secton_8 = voicesForm.querySelector(‘[data-queston-d=»8″]’) const feld_8 = secton_8.querySelector(‘nput[name=»MaxPartyIncQuan»]’) rentSelector(section_8, userData.MaxPartyIncId) feld_8.value = userData.MaxPartyIncQuan feld_8.dsabled = ложь } показатьStatstcs() } const sendData = асинхронный () =>{ const jsonData = JSON.strngfy(formData) console.log(‘——- ДЛЯ ОТПРАВКИ ——‘) console.log(formData) console.log(‘———————‘) const rawResponse = awat fetch(‘/e2026/add’, { метод: ‘POST’, заголовки: { ‘Content-Type’: ‘applcaton/json’ }, тело: jsonData }) константный ответ = awat rawResponse.json() f (!rawResponse.ok || !response || response.status === ‘ошибка’) { f (response.status === ‘error’ && response.message) { showCommonError(response.message) е (ответ?.errors) { showServerValdatonError(response.errors) } } еще { showCrtcalError() выдать новую ошибку(`Ошибка HTTP! Статус: ${rawResponse.status}`) } возвращение } f (ответ?.status === ‘ок’) { setCooke(ALREADY_VOTED, Date.now()) dsableVotng (правда) userData = { …formData.forecast } показатьУспех() показатьStatstcs() } еще { showCrtcalError() } обратный ответ } const submtForm = асинхронный (e) =>{ удалитьВсеОшибки() сВалдатонError = ложь получитьВсеФормДанные() е (!canSendForm) { е.preventDefault() е.stopPropagaton() showCommonError(‘Необходимо ответить хотя бы на один вопрос’) возвращение } еще { voicesForm.querySelector(‘.ele2026_house__basement .ele2026_house__basement_error’)?.remove() } е (sValdatonError) { е.preventDefault() е.stopPropagaton() voicesForm.querySelector(‘.ele2026_house__brck—error’) .closest(‘[data-queston-d]’) .scrollIntoVew({блок: «ближайший» }) возвращение } е(sCaptchaLoaded) { wndow.smartCaptcha.execute(captchaWdgetId) } еще { отправитьДанные() } } const handleArchveCLose = () => { е (sArchveOpen) { sArchveOpen = ложь; actveSectionId = ноль; const archive = document.querySelector(‘.ele2026_house__archve’); архив?.remove(); wndow.removeEventLstener(‘clck’, handleOutsdeClck); wndow.removeEventLstener(‘keydown’, handleKeydown); } } const handleKeydown = (e) => { е ( e.key === ‘Побег’ && !e.ctrlKey && !e.altKey && !e.shftKey && !e.metaKey ) { handleArchveCLose(); } }; const handleOutsdeClck = (e) =>{ const sOutsde = ( !e.target.closest(‘.ele2026_house__archve’) && !e.target.closest(‘.ele2026_house__nfo’) ); f (sOutsde && sArchveOpen) { handleArchveCLose(); } } const renderArchveInfo = (rec, secton) => { const archive = archiveTpl.content .cloneNode(истина) .querySelector(‘.ele2026_house__archve’); const text =archve.querySelector(‘.ele2026_house__archve_text’); text.nnerHTML = Rec.Info; const closeBtn =archve.querySelector(‘.ele2026_house__archve_close’); closeBtn.addEventLstener(‘clck’, handleArchveCLose, { Once: true }); secton.append(архив); } const handleArchveOpen = (e) =>{ const openBtn = e.target.closest(‘.ele2026_house__nfo’); е (!openBtn) возврат; const secton = openBtn.closest(‘.ele2026_house__floor’); const sectonId = Number(section.dataset.questonId); f (sArchveOpen && actveSectonId === sectonId) return; е (sArchveOpen) handleArchveCLose(); sArchveOpen = правда; actveSectionId = идентификатор секции; const Rec = ArchveLst.fnd((rec) => Rec.Name === sectonId); renderArchveInfo (запись, раздел); wndow.addEventLstener(‘clck’, handleOutsdeClck); wndow.addEventLstener(‘keydown’, handleKeydown); } const actvateArchveInfo = async () => { константный каталог = awat getCatalogData (1334); ArchveLst = каталог.данные; f (!archveLst?.length) return; wndow.addEventLstener(‘clck’, handleArchveOpen); } const ntForm = async () => { awat wndow.kommersant.user.ready //получаем данные из каталога региона жду getRegonsLst() //получим данные из каталога пакетов ждать getPartesLst() //если данные каталога не получены, блокируем форму и выводим ошибку f (sAPIError) возврат //заполняем все выпадающие списки на основе данных из каталогов регионов и партий флселекторс() //отключаем входы, связанные с выпадающими списками активироватьГруппы() //по вопросу №4 рисуем игры активироватьQueston4() //по вопросу №5 проверяем, что регион выбран активироватьQueston5() //заполняем форму данными пользователя в зависимости от ее статуса активироватьПользователь() //добавляем архивированную информацию к вопросам активироватьАрхвеИнфо(); } нтФорм() })();































Свежие комментарии