В настоящее время я пытаюсь изменить целевую страницу регистрации для подписчиков пользователей на моей установке в режиме дискурса.
Я пытаюсь через панель администратора в настройке Edit Html/css специально в разделе </head>
, я также попытался поместить это в </body>
По какой-то причине этот код не останавливает действие по умолчанию или перенаправляет пользователя на клик
<script>
var thingy = document.getElementsByClassName("sign-up-button")
thingy.onclick ="return false;"
thingy.onclick = function() {
window.location.href = "https://join.domain.com";
};
</script>
Когда я пытаюсь это сделать
<script>
var thingy = document.getElementsByClassName("sign-up-button");
console.log(thingy.length);
console.log(thingy)
for (var i = 0; i < thingy.length; i++) {
console.log('print this');
};
</script>
Он показывает длину thingy как 0, но затем он обрабатывает html-элемент, но никогда не выполняет итерацию, так как длина равна 0
Проблема заключается в том, что Discourse использует Ember. С Ember ничего не стоит в качестве клиентской платформы, но, похоже, это добавление элементов в DOM после запуска вашего скрипта. Когда элемент добавляется после того, как ваш скрипт пытается добавить прослушиватель событий, ваш скрипт не будет делать много (как вы обнаружили).
Я просмотрел веб-страницу Discourse, и я увидел, что кнопка часто добавляется и удаляется из DOM. Вероятно, это связано с тем, что кнопка должна отображаться только в том случае, если пользователь находится в верхней части страницы.
Одна тактика заключается в том, чтобы сделать что-то, чтобы задержать ваш скрипт - например, async defer
, requestAnimationFrame
или setTimeout
- чтобы этот элемент уже был вокруг, когда запускается ваш скрипт. Поскольку у меня нет отдельной страницы для тестирования, я не могу прокомментировать это.
Я собираюсь продемонстрировать, как присоединить обработчик событий, когда элемент добавлен в DOM. В старые времена вы использовали бы события мутации, как показано в большинстве ответов на этот вопрос. Поскольку эти события теперь устарели, вы должны использовать Mutation Observers (которые, как представляется, довольно хорошо поддерживаются).
MutationObserver.observe()
имеет два аргумента: целевой элемент и объект опций. Целевой элемент - это элемент, в котором вы слушаете события мутации. Из использования источника просмотра на странице кажется, что с самого начала не так много полезного в body
, поэтому мы уйдем с body
. Что касается объекта options, нас интересуют мутации childList
и subtree
поскольку кнопка не является прямым потомком body
.
Функция обратного вызова (только аргумент конструктора) будет срабатывать всякий раз, когда происходят события. Это тот момент, когда вы должны искать кнопку и присоединить обработчик события клика. Чтобы все было в порядке, вы можете проверить, действительно ли кнопка на самом деле, и отключить MutationObserver, если она есть. Не нужно продолжать прикреплять событие.
Для полноты я также хотел бы вызвать функцию, чтобы сразу прикрепить события, на случай, если элемент уже окажется вокруг.
Обратите внимание, что даже если элемент удаляется и добавляется в DOM при прокрутке вверх и вниз, вам нужно только прикрепить событие один раз. Это похоже на тот же элемент, поэтому слушатель событий все еще подключен.
Вы также упомянули в комментарии что-то о том, что модальность все еще появляется после того, как вы подключили слушателя. Вы можете остановить это с помощью .stopPropagation()
.
Кстати, эта пропаганда несколько связана с тем, почему вы не могли сделать простую $(window).on('click', '.sign-up-button',...)
. Это работает для большинства динамически создаваемых элементов, но в этом случае основное приложение также прослушивает события щелчка и, по-видимому, останавливает событие от пузыря.
Мой код ниже. Я использую jQuery, потому что видел, что он присутствует на страницах Discourse.
var targetNode = $('body')[0];
var attachEvent = function () {
var $button = $('.sign-up-button');
$button.on('click', function (e) {
e.stopPropagation();
// Do the redirect here
console.log('gotcha');
});
if ($button.length) {
console.log('hit');
observer.disconnect();
}
};
var callback = function() {
console.log('mutation');
attachEvent();
};
var observer = new MutationObserver(callback);
observer.observe(targetNode, { childList: true, subtree: true });
// Just in case...
attachEvent();
getElementsByClassName извлекает набор из нуля для многих объектов. Вы захотите выбрать один, перебрать их или использовать jQuery.
Это работает, если вы хотите только вернуть первую кнопку. (thingy [0].)
<script>
var thingy = document.getElementsByClassName("sign-up-button")
//thingy.onclick ="return false;"
thingy[0].onclick = function() {
window.location.href = "https://www.google.com";
//return false;
};
</script>
"Return false" не требуется, поскольку вы заменяете событие onclick.
Лучший вариант - дать кнопке идентификатор, а затем использовать getElementById для его получения.
TypeError: thingy[0] is undefined