現在、クリックされたクラスの属性を取得するJavaScriptを書こうとしています。これを正しい方法で行うには、イベントリスナーを使うべきだとわかっています。 私のコードは以下の通りです。
var classname = document.getElementsByClassName("classname");
var myFunction = function() {
var attribute = this.getAttribute("data-myattribute");
alert(attribute);
};
classname.addEventListener('click', myFunction(), false);
クラスをクリックするたびにアラートボックスが表示され、属性を教えてくれるものと期待していましたが、残念ながらうまくいきません。誰か助けてくれませんか?
(注 - _jQuery`で簡単にできるのですが、使いたくありません)
これで動くはずです。getElementsByClassName
は、条件にマッチした要素の array 配列のようなオブジェクト(編集部参照)を返します。
var classname = document.getElementsByClassName("classname");
var myFunction = function() {
var attribute = this.getAttribute("data-myattribute");
alert(attribute);
};
for (var i = 0; i < classname.length; i++) {
classname[i].addEventListener('click', myFunction, false);
}
jQueryはループ部分を代行してくれますが、これはプレーンなJavaScriptで行う必要があります。
もしES6をサポートしているのであれば、最後の行を以下のように置き換えることができます。
Array.from(classname).forEach(function(element) {
element.addEventListener('click', myFunction);
});
注意:古いブラウザ(IE6、IE7、IE8など)は、getElementsByClassName
をサポートしていないので、undefined
を返します。
EDIT : 修正
getElementsByClassName`は配列を返しませんが、ほとんどのブラウザではHTMLCollectionを、いくつかのブラウザではNodeListを返します(Mozilla ref)。これらの型はどちらも配列に似ていますが (つまり、長さのプロパティを持ち、インデックスを使ってオブジェクトにアクセスできます)、厳密には配列ではありませんし、配列から継承されたものでもありません。(つまり、配列に対して実行可能な他のメソッドは、これらの型に対しては実行できません。)
この点を指摘してくれたユーザーの@Nemoさんに感謝します。
これは、ターゲットクラスの子供がイベントをトリガーできるように編集されました。詳細は回答の下部を参照してください。
アイテムが頻繁に追加・削除されるクラスにイベントリスナーを追加する代替案です。これは jQuery'の on
関数にヒントを得たもので、イベントが listen する子要素のセレクタを渡すことができます。
var base = document.querySelector('#base'); // the container for the variable content
var selector = '.card'; // any css selector for children
base.addEventListener('click', function(event) {
// find the closest parent of the event target that
// matches the selector
var closest = event.target.closest(selector);
if (closest && base.contains(closest)) {
// handle class event
}
});
Fiddle:
これは base
要素の子供のクリックを listen し、クリックのターゲットがセレクタにマッチする親を持っていれば、クラスイベントが処理されます。個々の要素にクリックリスナーを追加することなく、好きなように要素を追加したり削除したりすることができます。このリスナーが追加された後に追加された要素であっても、jQueryの機能と同じように(フードの中では多少似ていると思いますが)、すべてのクリックをキャッチします。
これはイベントの伝搬に依存しているので、どこか他の場所でイベントのstopPropagation
を行うと、これは機能しないかもしれません。また、closest
関数には、IEとの互換性の問題があるようです(何が問題なのでしょうか?
このタイプのアクションリスニングを繰り返し行う必要がある場合は、以下のように関数にすることができます。
function addChildEventListener(base, eventName, selector, handler) {
base.addEventListener(eventName, function(event) {
var closest = event.target.closest(selector);
if (closest && base.contains(closest)) {
// passes the event to the handler and sets `this`
// in the handler as the closest parent matching the
// selector from the target element of the event
handler.call(closest, event);
}
});
}
=========================================
EDIT: この記事では当初、イベントターゲットの DOM 要素に対して matches
関数を使用していましたが、これではイベントのターゲットがダイレクトクラスのみに制限されてしまいます。代わりに closest
関数を使用するように更新しました。これにより、目的のクラスの子に対するイベントもトリガーできるようになりました。オリジナルの matches
コードは、オリジナルの fiddle で見ることができます。
https://jsfiddle.net/u6oje7af/23/
下記のコードをご利用いただけます。
document.body.addEventListener('click', function (evt) {
if (evt.target.className === 'databox') {
alert(this)
}
}, false);