Не определяется функция слушателя событий
Показываю модальку:
<div id="callback" class="modal_b"> <div class="body"> <div class="ttl">Заказать консультацию</div> <div class="dsc">Напишите нам и мы поможем вам разобраться в вопросах.</div> <div class="form v_form"> <div class="field"> <input type="text" name="name" class="form-control" placeholder="Ваше имя" data-rules="required"> </div> <div class="field"> <input type="phone" name="phone" class="form-control" placeholder="Телефон" data-rules="required"> </div> <div class="field"> <textarea name="dsc" rows="5" class="form-control" placeholder="Сообщение"></textarea> </div> <div class="action"> <spa class="btn btn-action go">Отправить</spa> </div> </div> </div> </div> По кукам: function getCookie(name) { let matches = document.cookie.match(new RegExp( "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)" )); return matches ? decodeURIComponent(matches[1]) : undefined; } let mcookie = getCookie("mcookie"); if (mcookie != "no") { setTimeout(function() { showModal("obratnyij-zvonok/"); document.getElementsByClassName("fancybox-close").addEventListener("click", function() { modalwin.style.display="none"; // записываем cookie на 1 день, с которой мы не показываем окно let date = new Date; date.setDate(date.getDate() + 1); document.cookie = "mcookie=no; path=/; expires=" + date.toUTCString(); }); }, 1000); } Но почему-то ругается: Uncaught TypeError: document.getElementsByClassName(...).addEventListe ner is not a function |
Скорее всего у вас скрипт отрабатывает еще до того, как на странице появится ваше модальное окно.
+ метод `getElementsByClassName` возвращает `HTMLCollection`, а не `HTMLElement`, у которой нет метода `addEventListener`. Попробуйте так: function getCookie(name) { let matches = document.cookie.match(new RegExp( "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)" )); return matches ? decodeURIComponent(matches[1]) : undefined; } document.addEventListener('DOMContentLoaded', function() { let mcookie = getCookie("mcookie"); if (mcookie != "no") { setTimeout(function() { showModal("obratnyij-zvonok/"); document.querySelector("fancybox-close").addEventListener("click", function() { if ('modalwin' in window) { modalwin.style.display = "none"; } // записываем cookie на 1 день, с которой мы не показываем окно let date = new Date; date.setDate(date.getDate() + 1); document.cookie = "mcookie=no; path=/; expires=" + date.toUTCString(); }); }, 1000); } }); |
Nexus, сделал как вы написали, теперь получаю ошибку:
caught TypeError: Cannot read properties of null (reading 'addEventListener') |
Timurkin,
точка нужна document.querySelector("тутfancybox-close") |
Цитата:
document.querySelector(".fancybox-close").addEventListener("click", function() { |
Цитата:
s - множественное число. Дай элементы Функция дает список (псевдомассив) элементов, даже если он один. Надо обращаться к одному элементу document.getElementsByClassName("fancybox-close")[0].addEventListener("click", function() { |
рони,
voraa, точку добавил. Теперь: caught TypeError: Cannot read properties of null (reading 'addEventListener') |
В вашем html коде вообще нет элемента с классом fancybox-close. Я не знаю, что именно вы ищите, почему он должен быть и где.
В вашем коде его нет. Поэтому результат поиска этого элемента null. |
Цитата:
Самого модального окна на странице изначально нет. Но оно как раз вызывается в коде выше: showModal("obratnyij-zvonok/"); |
Ну значит надо в отладчике проверять, появляется ли там эта кнопка.
Поставить точку останова после showModal и посмотреть появилась ли она. Если нет - думать почему, если появилась, то с каким точно классом. Что такое "obratnyij-zvonok/" и точно ли там должен быть /? |
showModal скорее всего проявляет окно не сразу, а с какой-нить анимацией, а потому если сразу пытаться получить кнопку - её ещё нет. Надо смотреть что там в showModal происходит: может оно принимает коллбэк, может возвращает промис, может вообще возвращает контрольный объект со всем нужным...
Способы отловить "что-то когда-то" есть, но это хрень. |
Цитата:
|
Ну функция showModal проста и ужасна
function showModal(target) { var opt = { type: 'ajax', scrolling: 'visible', wrapCSS: 'get-modal' }; if (typeof target === 'object') { opt = $.extend(opt, target); } else { opt.href = target; } $.fancybox(opt); } Она ничего не возвращает, поэтому мы не узнаем, когда открылась модальное окно, что бы обратиться к его кнопке закрытия. Тут три варианта действий. - Глубже изучить библиотеку fancybox в надежде, что у нее есть какие то события. Может есть событие открытия окна и тогда к кнопке обращаться только внутри этого события. - Сделать после вызова showModal цикл с таймером и каждые, скажем, 100 мс проверять появилась эта кнопка или нет. Когда появится выполнить необходимые действия. Недостаток - если что то пошло не так, и fancybox не смог считать ресурс мы попадаем в бесконечный цикл. Но можно ограничить цикл, например, 8 секундами, и если через 8 сек кнопка не появилась, сказать, что произошла ошибка и сервер не отвечает. - Перед вызовом showModal повесить на body MutationObserver и пусть он ждет, когда среди его дочерних элементов появится кнопка с заданным классом. Как появится - выполнить с ней необходимые действия. Еще. При клике на эту кнопку задается modalwin.style.display="none"; Не уверен, что это правильно. У fancybox скорее всего есть свой обработчик этой кнопки, который полностью убирает окно. Если он сработает первым, то окно уже не будет существовать. И это может вызвать ошибку. |
Если есть возможность переписать showModal, то сделайте его так
function showModal(target, callback) { var opt = { type: 'ajax', scrolling: 'visible', wrapCSS: 'get-modal' }; if (typeof target === 'object') { opt = $.extend(opt, target); } else { opt.href = target; } if (callback) { opt.opts = {}; opt.opts.onComplete = callback; } $.fancybox(opt); } А ваш код вызова document.addEventListener('DOMContentLoaded', function() { let mcookie = getCookie("mcookie"); if (mcookie != "no") { setTimeout(function() { showModal("obratnyij-zvonok/", () => { document.querySelector(".fancybox-close") .addEventListener("click", function() { if ('modalwin' in window) { // Не уверен, что это нужно modalwin.style.display = "none"; } // записываем cookie на 1 день, с которой мы не показываем окно let date = new Date; date.setDate(date.getDate() + 1); document.cookie = "mcookie=no; path=/; expires=" + date.toUTCString(); }) }); }, 1000); } }); |
Решил проблему, добавив таймер в 1 секунду после вызова showModal:
function getCookie(name) { let matches = document.cookie.match(new RegExp( "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)" )); return matches ? decodeURIComponent(matches[1]) : undefined; } document.addEventListener('DOMContentLoaded', function() { let mcookie = getCookie("mcookie"); if (mcookie != "no") { setTimeout(function() { showModal("obratnyij-zvonok/"); setTimeout(() => { document.querySelector(".fancybox-close").addEventListener("click", async function() { if ('modalwin' in window) { modalwin.style.display = "none"; } // записываем cookie на 1 день, с которой мы не показываем окно let date = new Date; date.setDate(date.getDate() + 1); document.cookie = "mcookie=no; path=/; expires=" + date.toUTCString(); }); }, 1000); }, 15000); } }); Всем спасибо за помощь и подсказки! |
Так себе решение.
А если на сервере запор, а в сети пробки, и за секунду ответ не пришел? Опять ошибка будет. Так попробуйте function getCookie(name) { let matches = document.cookie.match(new RegExp( "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)" )); return matches ? decodeURIComponent(matches[1]) : undefined; } function closeListener (tbeg) { const closeButton = document.querySelector(".fancybox-close") if (closeButton) { closeButton.addEventListener("click", function() { if ('modalwin' in window) { modalwin.style.display = "none"; } // записываем cookie на 1 день, с которой мы не показываем окно let date = new Date; date.setDate(date.getDate() + 1); document.cookie = "mcookie=no; path=/; expires=" + date.toUTCString(); }); } else { if (Date.now() - tbeg > 8000) { console.error('Сервер не отвечает') return; } setTimeout (closeListener, 100, tbeg); } } document.addEventListener('DOMContentLoaded', function() { let mcookie = getCookie("mcookie"); if (mcookie != "no") { setTimeout(function() { showModal("obratnyij-zvonok/"); closeListener(Date.now()) }, 15000); } }); |
voraa, работает, спасибо!
|
Часовой пояс GMT +3, время: 00:43. |