Deteksi perubahan konten elemen dengan jQuery

113

change() fungsi berfungsi dan mendeteksi perubahan pada elemen formulir, tetapi adakah cara untuk mendeteksi ketika konten elemen DOM diubah?

Ini tidak bekerja, kecuali #contentelemen formulir

$("#content").change( function(){
    // do something
});

Saya ingin ini terpicu saat melakukan sesuatu seperti:

$("#content").html('something');

Juga html()atau append()fungsi tidak memiliki panggilan balik.

Ada saran?

Elzo Valugi
sumber
pertanyaan lama yang saya tahu, tetapi periksa jawaban saya untuk solusi yang elegan stackoverflow.com/a/23826615/744975
Andrew Atkinson

Jawaban:

26

Ini adalah peristiwa mutasi .

Saya belum pernah menggunakan API peristiwa mutasi di jQuery, tetapi pencarian sepintas membawa saya ke proyek ini di GitHub. Saya tidak mengetahui kematangan proyek.

jrharshath
sumber
17
Plugin peristiwa mutasi ini tidak akan berfungsi, karena hanya menghubungkan peristiwa tersebut ke metode mutasi jQuery. Mereka dipecat ketika jQuery itu sendiri mencoba mengubah elemen, tetapi tidak ketika elemen diubah dari luar jQuery. Mereka tidak melihat perubahan pada dokumen. Lihat plugin kecil ini sebagai gantinya: stackoverflow.com/questions/3233991/jquery-watch-div/…
Sebastián Grignoli
10
Googling dan memposting link ke perpustakaan yang belum pernah Anda coba tidak terlalu berguna. (Berkomentar karena saya terdorong untuk melakukan downvoting.)
Berhenti Memfitnah Monica Cellio
27
Peristiwa mutasi tidak lagi digunakan ; jangan gunakan mereka.
Brock Adams
Alternatif untuk peristiwa mutasi tampaknya MutationObservers .
WoodrowShigeru
69

Saya tahu posting ini berumur satu tahun, tetapi saya ingin memberikan pendekatan solusi yang berbeda untuk mereka yang memiliki masalah serupa:

  1. Peristiwa perubahan jQuery hanya digunakan pada bidang masukan pengguna karena jika ada hal lain yang dimanipulasi (misalnya, div), manipulasi itu datang dari kode. Jadi, temukan di mana manipulasi terjadi, lalu tambahkan apa pun yang Anda butuhkan di sana.

  2. Tetapi jika itu tidak mungkin karena alasan apa pun (Anda menggunakan plugin yang rumit atau tidak dapat menemukan kemungkinan "panggilan balik") maka pendekatan jQuery yang saya sarankan adalah:

    Sebuah. Untuk manipulasi DOM sederhana, gunakan jQuery chaining dan traversing,$("#content").html('something').end().find(whatever)....

    b. Jika Anda ingin melakukan sesuatu yang lain, gunakan jQuery binddengan acara khusus dantriggerHandler

    $("#content").html('something').triggerHandler('customAction');
    
    $('#content').unbind().bind('customAction', function(event, data) {
       //Custom-action
    });

Berikut link ke jQuery trigger handler: http://api.jquery.com/triggerHandler/

Kyle
sumber
1
pikiran terakhir. meskipun itu seharusnya cukup komprehensif di atas: Anda dapat memperbarui nilai bidang masukan tersembunyi dengan nilai dari #content html dan kemudian mengikat acara perubahan ke bidang masukan tersembunyi :) banyak opsi
Kyle
7
+1 "Temukan di mana manipulasi terjadi, lalu tambahkan apa pun yang Anda butuhkan di sana." Memperbaiki masalah saya dalam 2 detik tanpa peretasan / plugin apa pun :)
Hartley Brody
Hanya perubahan yang saya sarankan di sini bindadalah mengharapkan pawang Anda mengembalikan a bool.
Serj Sagan
15

Browser tidak akan mengaktifkan peristiwa onchange untuk <div>elemen.

Saya pikir alasan di balik ini adalah bahwa elemen-elemen ini tidak akan berubah kecuali dimodifikasi oleh javascript. Jika Anda sudah harus memodifikasi elemen sendiri (daripada pengguna yang melakukannya), Anda dapat memanggil kode yang menyertai pada saat yang sama Anda memodifikasi elemen, seperti:

 $("#content").html('something').each(function() { });

Anda juga dapat mengaktifkan peristiwa seperti ini secara manual:

 $("#content").html('something').change();

Jika tidak satu pun dari solusi ini berhasil untuk situasi Anda, dapatkah Anda memberikan informasi lebih lanjut tentang apa yang secara khusus ingin Anda capai?

TM.
sumber
11
Ini mengasumsikan Anda telah menulis semua javascript, yang mungkin bukan masalahnya.
Misteri
TERIMA KASIH!!!! Ini hanya membantu saya memecahkan masalah yang telah saya lihat selama 6 jam.
Jordan Parmer
Persis yang saya butuhkan.
smac89
15

bagaimana dengan http://jsbin.com/esepal/2

$(document).bind("DOMSubtreeModified",function(){
  console.log($('body').width() + ' x '+$('body').height());
})

Acara ini sudah tidak digunakan lagi karena mendukung API Pengamat Mutasi

FDisk
sumber
1
bukan ide yang buruk, meskipun saya bertanya-tanya seberapa besar dukungan yang dimilikinya. developer.mozilla.org/en/DOM/DOM_event_reference/…
Elzo Valugi
Bagaimana Anda memantau elemen tertentu untuk perubahan? Saat ini dokumen memantau seluruh halaman.
Patoshi パ ト シ
3

Ini bukan hanya jawaban jQuery - tetapi berguna untuk disebutkan untuk debugging.

Di Firebug Anda bisa mengklik kanan pada elemen di pohon DOM dan mengatur 'Break on Attribute Change':

Elemen klik kanan di Firebug dengan Break on Attribute Change disorot

Ketika atribut diubah dalam skrip, jendela debug akan muncul dan Anda dapat melacak apa yang terjadi. Ada juga opsi untuk penyisipan elemen dan penghapusan elemen di bawah ini (tanpa bantuan dikaburkan oleh munculan di screengrab).

John Reid
sumber
1
Ini membantu, tetapi tidak persis seperti yang dia minta. Ini akan mendeteksi hal-hal seperti ketika kelas berubah, atau ketika atribut gaya ditambahkan atau diubah. Itu tidak akan memeriksa ketika konten di dalam node berubah. Misalnya, jika beberapa javascript di suatu tempat mengubah simpul dari <span> halo </span> menjadi <span> Dunia </span>, ini tidak akan mendeteksinya
Joshua Soileau
2

Saya sedang mengembangkan perpustakaan JS kecil yang disebut mutabor ( https://github.com/eskat0n/mutabor ) yang dimaksudkan untuk menyederhanakan penggunaan Peristiwa Mutasi DOM. Lihat demo.html sebagai contoh.

Eskat0n
sumber
1

Seringkali cara yang sederhana dan efektif untuk mencapainya adalah dengan melacak kapan dan di mana Anda memodifikasi DOM.

Anda dapat melakukan ini dengan membuat satu fungsi sentral yang selalu bertanggung jawab untuk memodifikasi DOM. Anda kemudian melakukan pembersihan apa pun yang Anda butuhkan pada elemen yang dimodifikasi dari dalam fungsi ini.

Dalam aplikasi baru-baru ini, saya tidak memerlukan tindakan segera, jadi saya menggunakan callback untuk fungsi handly load (), untuk menambahkan kelas ke elemen yang dimodifikasi dan kemudian memperbarui semua elemen yang dimodifikasi setiap beberapa detik dengan timer setInterval.

$($location).load("my URL", "", $location.addClass("dommodified"));

Kemudian Anda dapat menanganinya sesuka Anda - mis

setInterval("handlemodifiedstuff();", 3000); 
function handlemodifiedstuff()
{
    $(".dommodified").each(function(){/* Do stuff with $(this) */});
}
Antony Carthy
sumber
3
Ini mengasumsikan Anda telah menulis semua javascript, yang mungkin bukan masalahnya.
Misteri
1

Anda dapat menambahkan opsi panggilan balik ke fungsi html (, atau apa pun):

$.fn.oldHtml = $.fn.html;
$.fn.html = function(html,fn){
  fn = fn || function(){};
  var result =  this.oldHtml(html);
  fn();
  return result;
};
$('body').html(11,function(){alert("haha");});

Demo di sini.

Anda melakukan perubahan pada beberapa elemen, bukan elemen tersebut dipaksa untuk diubah oleh sesuatu yang harus Anda tangkap.


sumber
Saya harus menyelesaikan masalah ini hari ini. Saya tidak bisa mengedit kode yang sebenarnya disebut html () karena ada di perpustakaan pihak ketiga. Versi modifikasi ini sempurna untuk saya. Saya melakukan ini: $ .fn.oldHtml = $ .fn.html (); $ .fn.html = fungsi (e) {var result = this.oldHtml (e); this.trigger ('afterHtmlChange', e);} Sekarang saya bisa mengikat acara apa pun yang saya inginkan ke acara afterHtmlChange yang baru dibuat pada elemen apa pun, yang akan aktif setiap kali ada yang memanggil html () fn jQuery.
Daniel Howard
Ups, sedikit kesalahan. Fn dalam komentar saya di atas harus: function (e) {var result = this.oldHtml (e); this.trigger ('afterHtmlChange', e); hasil pengembalian;}
Daniel Howard
0

Saya menulis potongan yang akan memeriksa perubahan elemen pada sebuah acara.

Jadi jika Anda menggunakan kode javascript pihak ketiga atau sesuatu dan Anda perlu tahu ketika sesuatu muncul atau berubah ketika Anda telah mengklik maka Anda bisa.

Untuk potongan di bawah ini, katakanlah Anda perlu tahu kapan konten tabel berubah setelah Anda mengklik tombol.

$('.button').live('click', function() {

            var tableHtml = $('#table > tbody').html();
            var timeout = window.setInterval(function(){

                if (tableHtml != $('#table > tbody').
                    console.log('no change');
                } else {
                    console.log('table changed!');
                    clearInterval(timeout);
                }

            }, 10);
        });

Kode Pseudo:

  • Setelah Anda mengklik sebuah tombol
  • html dari elemen yang Anda harapkan untuk diubah ditangkap
  • kami kemudian terus memeriksa html elemen tersebut
  • ketika kami menemukan html berbeda, kami menghentikan pemeriksaan
Andrew Atkinson
sumber
0

Kami dapat mencapai ini dengan menggunakan Peristiwa Mutasi . Menurut www.w3.org, Modul peristiwa mutasi dirancang untuk memungkinkan pemberitahuan tentang perubahan apa pun pada struktur dokumen, termasuk modifikasi attr dan teks. Untuk lebih detail ACARA MUTASI

Sebagai contoh :

$("body").on('DOMSubtreeModified', "#content", function() {
    alert('Content Modified'); // do something
});
Sanchit Gupta
sumber
Ini sudah tidak digunakan lagi untuk sementara waktu. Seseorang harus menggunakan Pengamat Mutasi (konsep yang sama)
Carles Alcolea
-3

Tidak mungkin, saya yakin ada acara yang diubah kontennya tetapi jelas bukan x-browser

Haruskah saya katakan tidak mungkin tanpa jeda yang buruk di latar belakang!

kotak merah
sumber
21
kemustahilan itu tak ada!
jrharshath