У меня есть немного кода, где я просматриваю все поля выбора на странице и привязываю к нему событие .hover
, чтобы сделать немного спрятаться с их шириной на mouse on/off
.
Это происходит на странице готово и прекрасно работает.
Проблема заключается в том, что любые поля выбора, которые я добавляю через Ajax или DOM после начального цикла, не будут иметь привязки к событию.
Я нашел этот плагин (jQuery Live Query Plugin), но прежде чем добавить еще 5 к моим страницам с плагином, я хочу посмотрите, знает ли кто-нибудь способ сделать это, либо с помощью jQuery напрямую, либо с помощью другого параметра.
Начиная с jQuery 1.7 вы должны использовать jQuery.fn.on
:
$(staticAncestors).on(eventName, dynamicChild, function() {});
До этого рекомендуется использовать live()
:
$(selector).live( eventName, function(){} );
Однако live()
устарел в 1.7 в пользу on()
и полностью удален в 1.9. Подпись live()
:
$(selector).live( eventName, function(){} );
... можно заменить на следующую: on()
подпись:
$(document).on( eventName, selector, function(){} );
Например, если ваша страница динамически создавала элементы с именем класса dosomething
вы привязывали бы событие к родительскому, который уже существует (это суть проблемы здесь, вам нужно что-то, что существует для привязки, не привязывать к динамический контент), это может быть (и самый простой вариант) - это document
. Хотя иметь в виду document
возможно, не самый эффективный вариант.
$(document).on('mouseover mouseout', '.dosomething', function(){
// what you want to happen when mouseover and mouseout
// occurs on elements that match '.dosomething'
});
Любой родитель, который существует в момент привязки события, прекрасен. Например
$('.buttons').on('click', 'button', function(){
// do something here
});
будет применяться к
<div class="buttons">
<!-- <button>s that are generated dynamically and added here -->
</div>
В документации jQuery.fn.on
.
Короче:
Обработчики событий привязаны только к выбранным в данный момент элементам; они должны существовать на странице в момент, когда ваш код делает вызов
.on()
.
Таким образом, в следующем примере #dataTable tbody tr
должен существовать до генерации кода.
$("#dataTable tbody tr").on("click", function(event){
console.log($(this).text());
});
Если на страницу вводится новый HTML-код, предпочтительнее использовать делегированные события для присоединения обработчика событий, как описано ниже.
Делегированные события имеют то преимущество, что они могут обрабатывать события из элементов-потомков, которые будут добавлены в документ позже. Например, если таблица существует, но строки добавляются динамически с использованием кода, следующее будет обрабатывать ее:
$("#dataTable tbody").on("click", "tr", function(event){
console.log($(this).text());
});
В дополнение к их способности обрабатывать события на дочерних элементах, которые еще не созданы, другим преимуществом делегированных событий является их потенциал для значительно более низких накладных расходов, когда необходимо контролировать многие элементы. В таблице данных с 1000 строк в tbody
первый пример кода прикрепляет обработчик к 1000 элементам.
Подход с делегированными событиями (второй пример кода) присоединяет обработчик события только к одному элементу tbody
, и событию нужно только пузырьки на один уровень (от нажатого tr
до tbody
).
Примечание. Делегированные события не работают для SVG.
Это чистое решение JavaScript без каких-либо библиотек или плагинов:
document.addEventListener('click', function (e) {
if (hasClass(e.target, 'bu')) {
// .bu clicked
// Do your thing
} else if (hasClass(e.target, 'test')) {
// .test clicked
// Do your other thing
}
}, false);
где hasClass
function hasClass(elem, className) {
return elem.className.split(' ').indexOf(className) > -1;
}
Кредит принадлежит Дейву и Симе Видасу
Используя более современную JS, hasClass
можно реализовать как:
function hasClass(elem, className) {
return elem.classList.contains(className);
}
Вы можете добавлять события к объектам при их создании. Если вы добавляете одни и те же события к нескольким объектам в разное время, создание именованной функции может быть способом.
var mouseOverHandler = function() {
// Do stuff
};
var mouseOutHandler = function () {
// Do stuff
};
$(function() {
// On the document load, apply to existing elements
$('select').hover(mouseOverHandler, mouseOutHandler);
});
// This next part would be in the callback from your Ajax call
$("<select></select>")
.append( /* Your <option>s */ )
.hover(mouseOverHandler, mouseOutHandler)
.appendTo( /* Wherever you need the select box */ )
;
Вы можете просто связать вызов привязки события к функции, а затем вызвать его дважды: один раз на документе готов и один раз после вашего события, которое добавляет новые элементы DOM. Если вы это сделаете, вы захотите избежать связывания одного и того же события дважды с существующими элементами, поэтому вам нужно либо отменить существующие события, либо (лучше) привязать только к вновь созданным элементам DOM. Код будет выглядеть примерно так:
function addCallbacks(eles){
eles.hover(function(){alert("gotcha!")});
}
$(document).ready(function(){
addCallbacks($(".myEles"))
});
// ... add elements ...
addCallbacks($(".myNewElements"))
Попробуйте использовать .live()
вместо .bind()
; .live()
привяжет .hover
к вашему флажку после выполнения запроса Ajax.
live()
устарел в версии 1.7 в пользу on
и удален в версии 1.9.
Вы можете использовать метод live() для привязки элементов (даже недавно созданных) к событиям и обработчикам, например к событию onclick.
Вот пример кода, который я написал, где вы можете увидеть, как метод live() связывает выбранные элементы, даже вновь созданные, с событиями:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>
<body>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.16/jquery-ui.min.js"></script>
<input type="button" id="theButton" value="Click" />
<script type="text/javascript">
$(document).ready(function()
{
$('.FOO').live("click", function (){alert("It Works!")});
var $dialog = $('<div></div>').html('<div id="container"><input type ="button" id="CUSTOM" value="click"/>This dialog will show every time!</div>').dialog({
autoOpen: false,
tite: 'Basic Dialog'
});
$('#theButton').click(function()
{
$dialog.dialog('open');
return('false');
});
$('#CUSTOM').click(function(){
//$('#container').append('<input type="button" value="clickmee" class="FOO" /></br>');
var button = document.createElement("input");
button.setAttribute('class','FOO');
button.setAttribute('type','button');
button.setAttribute('value','CLICKMEE');
$('#container').append(button);
});
/* $('#FOO').click(function(){
alert("It Works!");
}); */
});
</script>
</body>
</html>
Одиночный элемент:
$(document.body).on('click','.element', function(e) { });
Детский элемент:
$(document.body).on('click','.element *', function(e) { });
Обратите внимание на добавленный *
. Событие будет инициировано для всех дочерних элементов этого элемента.
Я заметил, что:
$(document.body).on('click','.#element_id > element', function(e) { });
Он больше не работает, но он работал раньше. Я использую jQuery из Google CDN, но я не знаю, изменили ли они его.
Я предпочитаю использовать селектор, и я применяю его в документе.
Это привязывается к документу и будет применяться к элементам, которые будут отображаться после загрузки страницы.
Например:
$(document).on("click", $(selector), function() {
// Your code here
});
selector
, когда он должен содержать либо строку, либо объект Element, который вы можете просто передать непосредственно этому аргументу on()
Другим решением является добавление слушателя при создании элемента. Вместо того чтобы поместить слушателя в тело, вы помещаете слушателя в элемент в тот момент, когда вы его создаете:
var myElement = $('<button/>', {
text: 'Go to Google!'
});
myElement.bind( 'click', goToGoogle);
myElement.append('body');
function goToGoogle(event){
window.location.replace("http://www.google.com");
}
myElement.append('body');
должен быть myElement.appendTo('body');
, С другой стороны, если нет необходимости дальнейшего использования переменной myElement
это проще и короче так: $('body').append($('<button/>', { text: 'Go to Google!' }).bind( 'click', goToGoogle));
Вы можете присоединить событие к элементу при динамическом создании с помощью jQuery(html, attributes)
.
Как и jQuery 1.8, любой метод экземпляра jQuery (метод
jQuery.fn
) может использоваться как свойство объекта, переданного в второй параметр:
function handleDynamicElementEvent(event) {
console.log(event.type, this.value)
}
// create and attach event to dynamic element
jQuery("<select>", {
html: $.map(Array(3), function(_, index) {
return new Option(index, index)
}),
on: {
change: handleDynamicElementEvent
}
})
.appendTo("body");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
Обратите внимание на класс "MAIN", который помещается, например,
<div class="container">
<ul class="select">
<li> First</li>
<li>Second</li>
</ul>
</div>
В приведенном выше сценарии объект MAIN, который будет наблюдать jQuery, является "контейнером".
Тогда у вас будут в основном имена элементов под контейнером, такие как ul
, li
и select
:
$(document).ready(function(e) {
$('.container').on( 'click',".select", function(e) {
alert("CLICKED");
});
});
вы можете использовать
$('.buttons').on('click', 'button', function(){
// your magic goes here
});
или
$('.buttons').delegate('button', 'click', function() {
// your magic goes here
});
эти два метода эквивалентны, но имеют другой порядок параметров.
delegate()
теперь устарел. Не используйте это.
Вот почему динамически созданные элементы не реагируют на клики :
var body = $("body");
var btns = $("button");
var btnB = $("<button>B</button>");
// `<button>B</button>` is not yet in the document.
// Thus, `$("button")` gives `[<button>A</button>]`.
// Only `<button>A</button>` gets a click listener.
btns.on("click", function () {
console.log(this);
});
// Too late for `<button>B</button>`...
body.append(btnB);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>
В качестве обходного пути вы должны прослушать все клики и проверить исходный элемент :
var body = $("body");
var btnB = $("<button>B</button>");
var btnC = $("<button>C</button>");
// Listen to all clicks and
// check if the source element
// is a `<button></button>`.
body.on("click", function (ev) {
if ($(ev.target).is("button")) {
console.log(ev.target);
}
});
// Now you can add any number
// of `<button></button>`.
body.append(btnB);
body.append(btnC);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>
Это называется "Event Delegation". Хорошие новости, это встроенная функция в jQuery: -)
var i = 11;
var body = $("body");
body.on("click", "button", function () {
var letter = (i++).toString(36).toUpperCase();
body.append($("<button>" + letter + "</button>"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>
Любой p arent, который существует в момент привязки события, и если ваша страница динамически создавала элементы с именем класса , вы свяжет событие с родителем, который уже существует
$(document).ready(function(){
//Particular Parent chield click
$(".buttons").on("click","button",function(){
alert("Clicked");
});
//Dynamic event bind on button class
$(document).on("click",".button",function(){
alert("Dymamic Clicked");
});
$("input").addClass("button");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="buttons">
<input type="button" value="1">
<button>2</button>
<input type="text">
<button>3</button>
<input type="button" value="5">
</div>
<button>6</button>
Попробуйте это -
$(document).on( 'click', '.click-activity', function () { ... });
Это делается делегированием мероприятия. Событие будет привязано к элементу класса-оболочки, но будет делегировано элементу класса-селектора. Вот как это работает.
$('.wrapper-class').on("click", '.selector-class', function() {
// Your code here
});
Элемент класса-обертки может быть чем угодно. документ, тело или ваша обертка. Оболочка уже должна существовать.
var myElement = $('<button/>', {
text: 'Go to Google!'
});
myElement.bind( 'click', goToGoogle);
myElement.append('body');
function goToGoogle(event){
window.location.replace("http://www.google.com");
}
Используйте метод .on()
для jQuery http://api.jquery.com/on/ для присоединения обработчиков событий к элементу live.
Также удаляется метод версии 1.9 .live()
.
Свяжите событие с родителем, который уже существует:
$(document).on("click", "selector", function() {
// Your code here
});
Я предпочитаю, чтобы прослушиватели событий были развернуты модульной функцией, а не сценарием слушателя событий уровня document
. Итак, мне нравится ниже. Обратите внимание: вы не можете переадресовать элемент с одним и тем же прослушивателем событий, поэтому не беспокойтесь о том, чтобы добавить слушателя более одного раза - только один палец.
var iterations = 4;
var button;
var body = document.querySelector("body");
for (var i = 0; i < iterations; i++) {
button = document.createElement("button");
button.classList.add("my-button");
button.appendChild(document.createTextNode(i));
button.addEventListener("click", myButtonWasClicked);
body.appendChild(button);
}
function myButtonWasClicked(e) {
console.log(e.target); //access to this specific button
}
Более гибкое решение для создания элементов и привязки событий (источник)
// creating a dynamic element (container div)
var $div = $("<div>", {id: 'myid1', class: 'myclass'});
//creating a dynamic button
var $btn = $("<button>", { type: 'button', text: 'Click me', class: 'btn' });
// binding the event
$btn.click(function () { //for mouseover--> $btn.on('mouseover', function () {
console.log('clicked');
});
// append dynamic button to the dynamic container
$div.append($btn);
// add the dynamically created element(s) to a static element
$("#box").append($div);
Примечание. Это создаст экземпляр обработчика события для каждого элемента (может повлиять на производительность при использовании в цикле)
Я искал решение, чтобы получить $.bind
и $.unbind
без проблем работать в динамически добавленных элементах.
Поскольку on() делает трюк для присоединения событий, чтобы создать фальшивый отрыв от тех, к которым я пришел:
const sendAction = function(e){ ... }
// bind the click
$('body').on('click', 'button.send', sendAction );
// unbind the click
$('body').on('click', 'button.send', function(){} );
<html>
<head>
<title>HTML Document</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
</head>
<body>
<div id="hover-id">
Hello World
</div>
<script>
jQuery(document).ready(function($){
$(document).on('mouseover', '#hover-id', function(){
$(this).css('color','yellowgreen');
});
$(document).on('mouseout', '#hover-id', function(){
$(this).css('color','black');
});
});
</script>
</body>
</html>