動的に作成された要素のイベントバインディング?
ページ上のすべての選択ボックスをループし、.hover
イベントをそれらにバインドして、幅をオンにして少し調整するコードが少しありますmouse on/off
。
これはページの準備ができたときに発生し、問題なく機能します。
私が抱えている問題は、最初のループの後にAjaxまたはDOMを介して追加した選択ボックスには、イベントがバインドされないことです。
このプラグイン(jQuery Live Query Plugin)を見つけましたが、プラグインを使用してページにさらに5kを追加する前に、jQueryを直接または別のオプションでこれを行う方法を誰かが知っているかどうかを確認したいと思います。
回答
jQuery 1.7以降jQuery.fn.on、セレクターパラメーターを入力して使用する必要があります。
$(staticAncestors).on(eventName, dynamicChild, function() {});
説明:
これはイベント委任と呼ばれ、次のように機能します。イベントは、staticAncestors
処理する必要のある要素の静的な親()にアタッチされます。このjQueryハンドラーは、この要素または子孫要素の1つでイベントがトリガーされるたびにトリガーされます。次に、ハンドラーは、イベントをトリガーした要素がセレクター(dynamicChild
)と一致するかどうかを確認します。一致する場合は、カスタムハンドラー関数が実行されます。
これ以前は、推奨されるアプローチは次を使用することでした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());
});
まだ作成されていない子孫要素のイベントを処理する機能に加えて、委任されたイベントのもう1つの利点は、多くの要素を監視する必要がある場合にオーバーヘッドがはるかに低くなる可能性があることです。に1,000行あるデータテーブルでtbody
、最初のコード例はハンドラーを1,000要素にアタッチします。
委任イベントアプローチ(2番目のコード例)は、イベントハンドラーを1つの要素、にのみアタッチし、イベントはtbody
1つのレベル(クリックさ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;
}
Live demo
クレジットはDaveとSimeVidasに送られます
最新の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 */ )
;
イベントバインディング呼び出しを関数にラップして、それを2回呼び出すことができます。1回はドキュメントの準備ができたとき、もう1回は新しいDOM要素を追加するイベントの後でです。これを行う場合は、既存の要素に同じイベントを2回バインドしないようにする必要があるため、既存のイベントのバインドを解除するか、(より適切に)新しく作成されたDOM要素にのみバインドする必要があります。コードは次のようになります。
function addCallbacks(eles){
eles.hover(function(){alert("gotcha!")});
}
$(document).ready(function(){ addCallbacks($(".myEles"))
});
// ... add elements ...
addCallbacks($(".myNewElements"))
;の.live()
代わりに使用してみてください.bind()
。.live()
結合する.hover
Ajaxリクエストを実行した後、あなたのチェックボックスに。
動的に作成された要素のイベントバインディング
単一要素:
$(document.body).on('click','.element', function(e) { });
子要素:
$(document.body).on('click','.element *', function(e) { });
追加され*
たに注意してください。その要素のすべての子に対してイベントがトリガーされます。
私はそれに気づきました:
$(document.body).on('click','.#element_id > element', function(e) { });
それはもう機能していませんが、以前は機能していました。Google CDNのjQueryを使用していますが、変更されたかどうかはわかりません。
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).on("click", 'selector', 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");
}
このようにしてみてください-
$(document).on( 'click', '.click-activity', function () { ... });
これは、イベントの委任によって行われます。イベントはラッパークラス要素にバインドされますが、セレクタークラス要素に委任されます。これがその仕組みです。
$('.wrapper-class').on("click", '.selector-class', function() {
// Your code here
});
そしてHTML
<div class="wrapper-class">
<button class="selector-class">
Click Me!
</button>
</div>
#注:ラッパークラス要素は、たとえば何でもかまいません。ドキュメント、本文、またはラッパー。ラッパーはすでに存在しているはずです。ただし、selector
必ずしもページの読み込み時に表示する必要はありません。後で来る可能性があり、イベントはselector
必ずバインドされます。
要素が配置されている「MAIN」クラスに注意してください。たとえば、
<div class="container">
<ul class="select">
<li> First</li>
<li>Second</li>
</ul>
</div>
上記のシナリオでは、jQueryが監視するMAINオブジェクトは「コンテナ」です。
そして、あなたは基本的にのようなコンテナの下に要素名を持つことになりますul
、li
とselect
:
$(document).ready(function(e) { $('.container').on( 'click',".select", function(e) {
alert("CLICKED");
});
});
you could use
$('.buttons').on('click', 'button', function(){
// your magic goes here
});
or
$('.buttons').delegate('button', 'click', function() {
// your magic goes here
});
these two methods are equivalent but have a different order of parameters.
see: jQuery Delegate Event
You can attach event to element when dynamically created using jQuery(html, attributes).
As of jQuery 1.8, any jQuery instance method (a method of
jQuery.fn
) can be used as a property of the object passed to the second parameter:
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>
Here is why dynamically created elements do not respond to clicks :
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>
As a workaround, you have to listen to all clicks and check the source element :
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>
This is called "Event Delegation". Good news, it's a builtin feature in 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>
Any parent that exists at the time the event is bound and if your page was dynamically creating elements with the class name button you would bind the event to a parent which already exists
$(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>
Bind the event to a parent which already exists:
$(document).on("click", "selector", function() {
// Your code here
});
Use the .on()
method of jQuery http://api.jquery.com/on/ to attach event handlers to live element.
Also as of version 1.9 .live()
method is removed.
Another flexible solution to create elements and bind events (source)
// 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);
Note: This will create an event handler instance for each element (may affect performance when used in loops)
I prefer to have event listeners deployed in a modular function fashion rather than scripting a document
level event listener. So, I do like below. Note, you can't oversubscribe an element with the same event listener so don't worry about attaching a listener more than once - only one sticks.
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
}
<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>
I was looking a solution to get $.bind
and $.unbind
working without problems in dynamically added elements.
As on() makes the trick to attach events, in order to create a fake unbind on those I came to:
const sendAction = function(e){ ... }
// bind the click
$('body').on('click', 'button.send', sendAction ); // unbind the click $('body').on('click', 'button.send', function(){} );