Suatu saat saya sedang bekerja dengan proyek yang banyak melibatkan binding event ke banyak element dinamis. Maksud saya adalah element yang tercipta dari interaksi user seperti dari penggunaan appendChild. Seperti diketahui bahwa saat dokumen HTML dan JavaScript nya selesai terunduh dari server, peraba dari pengguna akan membind event handler hanya ke element yang ada saat itu, yaitu element yang terdapat pada saat dokumen terunduh. Jadi event handler hanya akan dibind sekali pada satu waktu. Jika tercipta elemen baru hasil manipulasi DOM dari interaksi pengguna maka jangan heran jika elemen baru dengan class sama tidak ditangani oleh event handler yang sudah Anda tulis. Untuk lebih jelasnya mari lihat kode JavaScript (dengan jQuery) berikut:

1
2
3
4
5
6
7
8
9
10
11
12
13
$(function() {
    var counter = 0;
 
    $(".taut").click(function() {
        var txt = $(this).text();
        $("#container-dinamis").append("<div class='dinamis'>Hasil dari click " + txt + "<div>");
    });
 
    $("#tambah-taut").click(function() {
        counter += 1;
        $("#container-taut").append("<a href='#' title='taut' class='taut'>Aku taut baru yang ke-" + counter + "</a>");
    });
});

Untuk melihat halaman demonya silahkan klik disini. Saat anchor dengan class taut dihasilkan dari klik #tambah-taut, anchor baru tersebut tidak akan mendapatkan event handler click. Karena event handler click pada element anchor dengan class taut hanya diberikan ke elemen saat baru terunduh. Masalahnya adalah bagaimana agar elemen baru dengan class taut tersebut mendapatkan penanganan yang sama saat terjadi event click? Mari kita lihat solusinya di bawah, yaitu dengan apa yang disebut delegasi event.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$(function() {
    var counter = 0;
 
    $("#container-taut").click(function(e) {
        var el  = $(e.target);
        var txt = el.text();
 
        if (el.hasClass('taut') {
            $("#container-dinamis").append("<div class='dinamis'>Hasil dari click " + txt + "<div>");
        }
    });
 
    $("#tambah-taut").click(function() {
        counter += 1;
        $("#container-taut").append("<a href='#' title='taut' class='taut'>Aku taut baru yang ke-" + counter + "</a>");
    });
});

Untuk melihat halaman demo solusi silahkan klik disini. Delegasi event hanyalah pemanfaatan fase event dalam JavaScript, yaitu saat fase event bubbling. Event JavaScript tereksekusi dalam dua fase, yaitu capturing dan bubbling. Saat event terjadi pada element, misal element anchor dengan class taut terklik maka fase capturing dimulai dengan click handler pada dokumen, turun ke <body>, ke <div id="container-taut"> dan akhirnya <a class="taut">. Setelah selesai eksekusi event kembali lagi ke atas (bubbling) sesuai urutan DOM sebelumnya, yaitu <div id="container-taut">, <body> dan document. Semua event handler tereksekusi sesuai urutan fase tersebut. Untuk lebih jelasnya lihat gambar berikut:

Dua fase event JavaScript, capturing dan bubbling, ada karena perbedaan antara implementasi event pada IE dan Netscape dulu (awal mulainya perang browser). IE mendefinisikan event bubbling, sedangkan netscape mendefinisikan event capturing. Lalu W3C menengahkan keduanya dengan mendefinisikan event capturing terjadi pertama kali sampai target element ditemui lalu event akan bubbling ke element parentnya. Model binding event oleh W3C ini adalah addEventListener(). Ada dua model binding event sebelumnya, yaitu model inline dan tradisional. Model inline merupakan model yang dibuat oleh Netscape, yaitu event handler didefinisikan sebagai atribut dari suatu element, misal : <a href="index.html" onclick="alert('yeah')">. Sedangkan model tradisional adalah model yang digunakan sejak netscape 3 dan IE 4 yaitu dengan meregistrasi event handler melalui DOM scripting,

document.getElementById("element").onclick = someFunction;

Event binding di jQuery merupakan W3C model, addEventListener, tanpa event capturing. Untuk melihat bagaimana event bubbling terjadi, perhatikan struktur HTML pada gambar fase event diatas, setiap element memiliki event handler onclick, lalu pada saat element anchor mendapatkan dirinya diklik, event handler untuknya akan dieksekusi, lalu bubbling ke atas mengeksekusi event handler dari element container hingga document. Demo nya dapat di lihat disini.

Dengan mengetahui sifat event seperti ini, event dapat didelegasikan ke element dalam element. Dengan meregistrasi event handler ke element container, anak element dapat ditangani melalui properti target dari objek event. Ya, dalam JavaScript event merupakan objek yang memiliki properti, seperti type, target, keyCode dan sebagainya. Pembahasan event lebih dalam akan saya bahas lain kali. Yang perlu Anda ketahui adalah penggunaan event delegation sangat berguna menghemat handler yang diberikan ke element. Bila Anda bekerja dengan dokumen yang melibatkan banyak element, event delegation memberikan performa lebih baik dibanding dengan membinding setiap element.

Referensi: