Не определяется функция слушателя событий
Показываю модальку:
<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, время: 08:37. |