web-dev-qa-db-fra.com

Les sélecteurs jQuery peuvent-ils être utilisés avec des observateurs de mutation DOM?

HTML5 inclut un concept de "observateurs de mutations" pour surveiller les modifications apportées au DOM du navigateur.

Votre rappel d'observateur recevra des données qui ressemblent beaucoup à des extraits d'arbre DOM. Je ne sais pas s'ils sont exactement ça ou comment ils fonctionnent vraiment.

Mais lorsque vous écrivez du code pour interagir avec un site tiers sur lequel vous n'avez aucun contrôle, par exemple avec un script Greasemonkey ou Google Chrome script utilisateur, vous devez inspecter l'arborescence des éléments passés dans pour trouver les informations qui vous concernent.

C'est beaucoup plus simple avec les sélecteurs, tout comme avec n'importe quel DOM, que de parcourir l'arborescence manuellement, en particulier pour le code multi-navigateur.

Existe-t-il un moyen d'utiliser les sélecteurs jQuery avec les données transmises aux rappels des observateurs de mutation HTML5?

36
hippietrail

Oui, vous pouvez utiliser des sélecteurs jQuery sur les données renvoyées aux rappels des observateurs de mutation.

Voir ce jsFiddle.

Supposons que vous ayez du HTML comme ceci:

<span class="myclass">
    <span class="myclass2">My <span class="boldly">vastly</span> improved</span>
    text.
</span>


Et vous définissez un observateur, comme ceci:

var targetNodes         = $(".myclass");
var MutationObserver    = window.MutationObserver || window.WebKitMutationObserver;
var myObserver          = new MutationObserver (mutationHandler);
var obsConfig           = { childList: true, characterData: true, attributes: true, subtree: true };

//--- Add a target node to the observer. Can only add one node at a time.
targetNodes.each ( function () {
    myObserver.observe (this, obsConfig);
} );

function mutationHandler (mutationRecords) {
    console.info ("mutationHandler:");

    mutationRecords.forEach ( function (mutation) {
        console.log (mutation.type);

        if (typeof mutation.removedNodes == "object") {
            var jq = $(mutation.removedNodes);
            console.log (jq);
            console.log (jq.is("span.myclass2"));
            console.log (jq.find("span") );
        }
    } );
}

Vous remarquerez que nous pouvons jQuery sur le mutation.removedNodes.


Si vous exécutez ensuite $(".myclass").html ("[censored!]"); à partir de la console , vous l'obtiendrez de Chrome et Firefox:

mutationHandler:
childList
jQuery(<TextNode textContent="\n ">, span.myclass2, <TextNode textContent="\n text.\n ">)
true
jQuery(span.boldly)

ce qui montre que vous pouvez utiliser des méthodes de sélection jQuery normales sur les ensembles de nœuds renvoyés.

51
Brock Adams

Je n'ai aucun extrait de code personnel pour celui-ci, mais j'ai trois ressources qui peuvent vous aider:

Exemple de la bibliothèque de liens n ° 3 "jquery-mutation-summary":

// Use document to listen to all events on the page (you might want to be more specific)
var $observerSummaryRoot = $(document);

// Simplest callback, just logging to the console
function callback(summaries){
    console.log(summaries);
}

// Connect mutation-summary
$observerSummaryRoot.mutationSummary("connect", callback, [{ all: true }]);

// Do something to trigger mutationSummary
$("<a />", { href: "http://joelpurra.github.com/jquery-mutation-summary"}).text("Go to the jquery-mutation-summary website").appendTo("body");

// Disconnect when done listening
$observerSummaryRoot.mutationSummary("disconnect");
7
Vita Pluvia

Je travaillais sur un problème très similaire pour un script Stack Exchange sur lequel je travaille, et j'avais besoin de pouvoir surveiller le DOM pour les changements. Les documents jQuery n'avaient rien d'utile, mais j'ai découvert que l'événement DOMNodeInserred fonctionne dans Chrome:

document.addEventListener("DOMNodeInserted", function(event){
    var element = event.target;

    if (element.tagName == 'DIV') {
        if (element.id == 'seContainerInbox') {
            //alert($('#seContainerInbox').parent().get(0).tagName);
            trimStoredItems();
            $('#seTabInbox').click();
            //   var newCount = getNewCount();
            // if there are new inbox items, store them for later
            storeNewInboxItems();
            applyNewStyleToItems();
        }
    }
});

Je ne suis pas sûr à 100% si cela fonctionne dans Firefox, car je n'ai pas encore atteint ce stade dans le processus de développement. J'espère que cela t'aides!

3
jmort253

Je sais que c'est une vieille question, mais cela peut peut-être aider les autres à rechercher des solutions alternatives. J'ai récemment découvert les observateurs de mutation et je voulais expérimenter leur utilisation avec jQuery. J'ai proposé deux approches possibles et les ai transformées en plugins. Le code est disponible ici .

La première approche (jquery.observeWithEvents.js) Utilise la fonction trigger() de jQuery pour déclencher un événement insertNode ou removeNode qui peut être lié via la fonction on() une fonction. La deuxième approche (jquery.observeWithCallbacks.js) Utilise des paramètres de rappel traditionnels. Veuillez consulter le README pour des exemples et l'utilisation.

2
Bart Jedrocha