Rileva le modifiche al contenuto degli elementi con jQuery


113

change() funziona e rileva le modifiche sugli elementi del modulo, ma esiste un modo per rilevare quando il contenuto di un elemento DOM è stato modificato?

Questo non funziona, a meno che non #contentsia un elemento del modulo

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

Voglio che questo si attivi quando si fa qualcosa come:

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

Inoltre html()o la append()funzione non ha una richiamata.

Eventuali suggerimenti?


vecchia domanda lo so, ma controlla la mia risposta per una soluzione elegante stackoverflow.com/a/23826615/744975
Andrew Atkinson

Risposte:


26

Questi sono eventi di mutazione .

Non ho utilizzato le API degli eventi di mutazione in jQuery, ma una rapida ricerca mi ha portato a questo progetto su GitHub. Non sono a conoscenza della maturità del progetto.


17
Questo plugin per gli eventi di mutazione non funziona, perché aggancia semplicemente gli eventi ai metodi di mutazione di jQuery. Vengono attivati ​​quando jQuery stesso tenta di modificare gli elementi, ma non quando gli elementi vengono modificati dall'esterno di jQuery. Non guardano le modifiche sul documento.
Sebastián Grignoli

10
Cercare su Google e pubblicare un collegamento a una libreria che non hai mai provato non è molto utile. (Commentando perché mi è stato chiesto di fare il downvoting.)
Smetti di calunniare Monica Cellio


L'alternativa agli eventi di mutazione sembra essere MutationObservers .
Woodrow Shigeru

69

So che questo post risale a un anno fa, ma vorrei fornire un approccio di soluzione diverso a coloro che hanno un problema simile:

  1. L'evento di modifica jQuery viene utilizzato solo sui campi di input dell'utente perché se qualcos'altro viene manipolato (ad esempio, un div), tale manipolazione proviene dal codice. Quindi, trova dove si verifica la manipolazione, quindi aggiungi tutto ciò di cui hai bisogno lì.

  2. Ma se questo non è possibile per qualsiasi motivo (stai usando un plugin complicato o non riesci a trovare alcuna possibilità di "callback"), l'approccio jQuery che suggerirei è:

    un. Per una semplice manipolazione DOM, usa jQuery chaining and traversing,$("#content").html('something').end().find(whatever)....

    b. Se desideri fare qualcos'altro, utilizza jQuery bindcon eventi personalizzati etriggerHandler

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

Ecco un collegamento al gestore del trigger jQuery: http://api.jquery.com/triggerHandler/


1
pensiero finale. anche se dovrebbe essere abbastanza completo sopra: potresti aggiornare il valore di un campo di input nascosto con quello dell'html #content e quindi associare l'evento di modifica al campo di input nascosto :) molte opzioni
Kyle

7
+1 "Trova il punto in cui si verifica la manipolazione, quindi aggiungi tutto ciò di cui hai bisogno lì". Risolto il problema in 2 secondi senza hack / plug-in :)
Hartley Brody

L'unico cambiamento che suggerisco qui è che bindsi aspetta che il tuo gestore restituisca un file bool.
Serj Sagan

15

Il browser non attiverà l'evento onchange per gli <div>elementi.

Penso che il ragionamento alla base di questo sia che questi elementi non cambieranno se non modificati da javascript. Se devi già modificare l'elemento da solo (piuttosto che l'utente lo fa), puoi semplicemente chiamare il codice di accompagnamento appropriato nello stesso momento in cui modifichi l'elemento, in questo modo:

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

Puoi anche attivare manualmente un evento come questo:

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

Se nessuna di queste soluzioni funziona per la tua situazione, potresti fornire maggiori informazioni su ciò che stai cercando di ottenere specificamente?


11
Questo presuppone che tu abbia scritto tutto il javascript, il che potrebbe non essere il caso.
Myster

GRAZIE!!!! Questo mi ha solo aiutato a risolvere un problema che stavo fissando per 6 ore.
Jordan Parmer

Esattamente quello di cui avevo bisogno.
smac89

15

che dire di http://jsbin.com/esepal/2

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

Questo evento è stato deprecato a favore dell'API Mutation Observer


1
non è una cattiva idea, anche se mi chiedo quanto supporto abbia. developer.mozilla.org/en/DOM/DOM_event_reference/…
Elzo Valugi

Come si monitorano i cambiamenti di un elemento specifico? Attualmente il documento controlla l'intera pagina.
Patoshi パ ト シ




3

Non è strettamente una risposta jQuery, ma utile da menzionare per il debug.

In Firebug puoi fare clic con il pulsante destro del mouse su un elemento nella struttura DOM e impostare "Interrompi alla modifica degli attributi":

Fai clic con il pulsante destro del mouse su Firebug con Break on Attribute Change evidenziato

Quando un attributo viene modificato in uno script, apparirà la finestra di debug e potrai rintracciare cosa sta succedendo. C'è anche un'opzione per l'inserimento e la rimozione dell'elemento di seguito (inutilmente oscurato dal popup nello screengrab).


1
Questo è utile, ma non esattamente quello che stava chiedendo. Questo rileverà cose come quando una classe cambia o quando viene aggiunto o modificato un attributo di stile. Non controllerà quando il contenuto all'interno del nodo cambia. Ad esempio, se qualche javascript da qualche parte cambia un nodo da <span> ciao </span> a <span> World </span>, questo non lo rileverà
Joshua Soileau



1

Spesso un modo semplice ed efficace per ottenere questo risultato è tenere traccia di quando e dove si sta modificando il DOM.

Puoi farlo creando una funzione centrale che è sempre responsabile della modifica del DOM. Quindi fai qualsiasi pulizia necessaria sull'elemento modificato dall'interno di questa funzione.

In un'applicazione recente, non avevo bisogno di un'azione immediata, quindi ho usato un callback per la funzione handly load (), per aggiungere una classe a qualsiasi elemento modificato e quindi ho aggiornato tutti gli elementi modificati ogni pochi secondi con un timer setInterval.

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

Quindi puoi gestirlo come preferisci, ad es

setInterval("handlemodifiedstuff();", 3000); 
function handlemodifiedstuff()
{
    $(".dommodified").each(function(){/* Do stuff with $(this) */});
}

3
Questo presuppone che tu abbia scritto tutto il javascript, il che potrebbe non essere il caso.
Myster

1

Puoi aggiungere un'opzione di callback alla funzione html (o qualsiasi):

$.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 qui.

Fai la modifica su qualche elemento, non l'elemento è costretto a cambiare da qualcosa che devi catturare.


Oggi ho dovuto risolvere questo problema. Non ho potuto modificare il codice che in realtà ha chiamato html () perché è in una libreria di terze parti. Una versione modificata di questo era perfetta per me. Ho fatto questo: $ .fn.oldHtml = $ .fn.html (); $ .fn.html = funzione (e) {var result = this.oldHtml (e); this.trigger ('afterHtmlChange', e);} Ora posso associare tutti gli eventi che voglio al nuovo evento afterHtmlChange su qualsiasi elemento, che si attiverà ogni volta che qualcosa chiama html () fn di jQuery.
Daniel Howard

Ops, piccolo errore. Fn nel mio commento sopra dovrebbe essere: function (e) {var result = this.oldHtml (e); this.trigger ( 'afterHtmlChange', e); risultato di ritorno;}
Daniel Howard

0

Ho scritto uno snippet che controllerà la modifica di un elemento su un evento.

Quindi, se stai usando codice javascript di terze parti o qualcosa del genere e hai bisogno di sapere quando qualcosa appare o cambia quando hai cliccato, puoi farlo.

Per lo snippet di seguito, diciamo che devi sapere quando il contenuto di una tabella cambia dopo aver fatto clic su un pulsante.

$('.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);
        });

Pseudo codice:

  • Dopo aver fatto clic su un pulsante
  • l'html dell'elemento che ci si aspetta di modificare viene acquisito
  • quindi controlliamo continuamente l'html dell'elemento
  • quando troviamo che l'html è diverso, interrompiamo il controllo

0

Possiamo ottenere ciò utilizzando gli eventi di mutazione . Secondo www.w3.org, il modulo dell'evento di mutazione è progettato per consentire la notifica di eventuali modifiche alla struttura di un documento, incluse le modifiche all'attr e al testo. Per maggiori dettagli EVENTI DI MUTAZIONE

Per esempio :

$("body").on('DOMSubtreeModified', "#content", function() {
    alert('Content Modified'); // do something
});

Questo è stato deprecato per un po '. Si dovrebbe usare Mutation Observers (stesso concetto)
Carles Alcolea

-3

Non è possibile, credo cioè abbia un evento di modifica del contenuto ma non è certamente x-browser

Devo dire che non è possibile senza qualche brutto intervallo che sbuffa in sottofondo!


21
niente è impossibile!
jrharshath
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.