Événement lorsque l'élément est ajouté à la page

cela a déjà été discuté ici: Comment faire une action quand un élément est ajouté à une page en utilisant Jquery?

le répondant a suggéré de déclencher un événement personnalisé chaque fois qu'un div était ajouté à la page. Cependant, j'écris une extension Chrome et je n'ai pas accès à la source de la page. Quelles sont mes options? Je suppose qu'en théorie je pourrais juste utiliser setTimeout pour rechercher continuellement la présence de l'élément et ajouter mon action si le l'élément est-il.

108
demandé sur Community 2011-09-15 21:01:12
la source

7 ответов

étant donné que les événements de Mutation DOM sont maintenant déprécié (Voir note au bas) avec les dernières spécifications, et que vous n'avez aucun contrôle sur les éléments insérés parce qu'ils sont ajoutés par le code de quelqu'un d'autre, votre seule option est de les vérifier en permanence.

function checkDOMChange()
{
    // check for any new element being inserted here,
    // or a particular node being modified

    // call the function again after 100 milliseconds
    setTimeout( checkDOMChange, 100 );
}

une fois cette fonction appelée, elle s'exécute toutes les xxx millisecondes. J'ai choisi 100, qui est 1/10 (un dixième) d'une seconde. Sauf si vous avez besoin d'éléments temps réel attraper, il devrait être suffisant.

Modifier

comme L'a commenté Ben Davis, la spécification de niveau 4 de DOM introduit observateurs de Mutation (également sur Mozilla docs ), qui remplacent les événements de mutation dépréciés.

73
répondu Jose Faeti 2018-04-26 13:19:21
la source

la réponse réelle est "utiliser des observateurs de mutation" (comme indiqué dans cette question: déterminer si un élément HTML a été ajouté au DOM dynamiquement ), cependant le support (spécifiquement sur IE) est limité ( http://caniuse.com/mutationobserver ).

donc la réponse réelle est " utilisez des observateurs de mutation.... finalement. Mais allez avec la réponse de Jose Faeti pour l'instant":)

22
répondu Asfand Qazi 2017-05-23 15:34:16
la source

vous pouvez également exploiter des événements D'Animation CSS3 afin d'être notifié lorsqu'un élément spécifique est ajouté au DOM: http://www.backalleycoder.com/2012/04/25/i-want-a-damnodeinserted/

14
répondu jokeyrhyme 2014-06-07 12:11:53
la source

vous pouvez utiliser livequery plugin pour jQuery. Vous pouvez fournir une expression de sélection telle que:

$("input[type=button].removeItemButton").livequery(function () {
    $("#statusBar").text('You may now remove items.');
});

chaque fois qu'un bouton d'une classe removeItemButton est ajouté, un message apparaît dans une barre d'état.

en termes d'efficacité, vous pourriez vouloir éviter cela, mais dans tous les cas, vous pourriez utiliser le plugin au lieu de créer vos propres gestionnaires d'événements.

réponse revisitée

la réponse ci-dessus était seulement destiné à détecter qu'un article a été ajouté au DOM à travers le plugin.

cependant, très probablement, une approche jQuery.on() serait plus appropriée, par exemple:

$("#myParentContainer").on('click', '.removeItemButton', function(){
          alert($(this).text() + ' has been removed');
}

si vous avez un contenu dynamique qui devrait répondre à des clics par exemple, il est préférable de lier des événements à un conteneur parent en utilisant jQuery.on .

11
répondu Zero Distraction 2012-11-14 11:15:32
la source

ETA 24 Apr 17 Je voulais simplifier un peu avec quelques async / await magie, car il rend beaucoup plus succinct:

utilisant le même promisified-observable:

const startObservable = (domNode) => {
  var targetNode = domNode;

  var observerConfig = {
    attributes: true,
    childList: true,
    characterData: true
  };

  return new Promise((resolve) => {
      var observer = new MutationObserver(function (mutations) {
         // For the sake of...observation...let's output the mutation to console to see how this all works
         mutations.forEach(function (mutation) {
             console.log(mutation.type);
         });
         resolve(mutations)
     });
     observer.observe(targetNode, observerConfig);
   })
} 

votre fonction d'appel peut être aussi simple que:

const waitForMutation = async () => {
    const button = document.querySelector('.some-button')
    if (button !== null) button.click()
    try {
      const results = await startObservable(someDomNode)
      return results
    } catch (err) { 
      console.error(err)
    }
}

si vous voulez ajouter un timeout, vous pouvez utiliser un simple Promise.race pattern comme démontré ici :

const waitForMutation = async (timeout = 5000 /*in ms*/) => {
    const button = document.querySelector('.some-button')
    if (button !== null) button.click()
    try {

      const results = await Promise.race([
          startObservable(someDomNode),
          // this will throw after the timeout, skipping 
          // the return & going to the catch block
          new Promise((resolve, reject) => setTimeout(
             reject, 
             timeout, 
             new Error('timed out waiting for mutation')
          )
       ])
      return results
    } catch (err) { 
      console.error(err)
    }
}

Original

vous pouvez faire cela sans bibliothèques, mais vous devez utiliser quelques trucs ES6, alors soyez conscient des problèmes de compatibilité (i.e., si votre auditoire est principalement des utilisateurs Amish, luddite ou, pire, IE8)

tout d'abord, nous allons utiliser le MutationObserver API pour construire un objet observateur. Nous allons envelopper cet objet dans une promesse, et resolve() quand le rappel est déclenché (h/t davidwalshblog) david walsh article de blog sur les mutations :

const startObservable = (domNode) => {
    var targetNode = domNode;

    var observerConfig = {
        attributes: true,
        childList: true,
        characterData: true
    };

    return new Promise((resolve) => {
        var observer = new MutationObserver(function (mutations) {
            // For the sake of...observation...let's output the mutation to console to see how this all works
            mutations.forEach(function (mutation) {
                console.log(mutation.type);
            });
            resolve(mutations)
        });
        observer.observe(targetNode, observerConfig);
    })
} 

alors, nous allons créer un generator function . Si vous ne les avez pas encore utilisées, alors vous êtes en train de les rater--mais un bref synopsis est: il fonctionne comme une fonction de synchronisation, et quand il trouve une expression yield <Promise> , il attend de manière non-bloquante que la promesse soit remplie ( les générateurs font plus que cela, mais c'est ce qui nous intéresse ici ).

// we'll declare our DOM node here, too
let targ = document.querySelector('#domNodeToWatch')

function* getMutation() {
    console.log("Starting")
    var mutations = yield startObservable(targ)
    console.log("done")
}

une partie délicate à propos des générateurs est qu'ils ne "reviennent" pas comme une fonction normale. Donc, nous allons utiliser une fonction d'aide pour être en mesure d'utiliser le générateur comme une fonction régulière. (encore une fois, h/t à dwb )

function runGenerator(g) {
    var it = g(), ret;

    // asynchronously iterate over generator
    (function iterate(val){
        ret = it.next( val );

        if (!ret.done) {
            // poor man's "is it a promise?" test
            if ("then" in ret.value) {
                // wait on the promise
                ret.value.then( iterate );
            }
            // immediate value: just send right back in
            else {
                // avoid synchronous recursion
                setTimeout( function(){
                    iterate( ret.value );
                }, 0 );
            }
        }
    })();
}

ensuite, à tout moment avant que la mutation attendue de DOM puisse se produire, il suffit d'exécuter runGenerator(getMutation) .

maintenant vous pouvez intégrer DOM mutations dans un synchrone de style de flux de contrôle. Comment combat.

8
répondu Brandon 2017-05-23 15:17:56
la source

il y a une bibliothèque javascript prometteuse appelée Arrive qui ressemble à un bon moyen de commencer à profiter des observateurs de mutation une fois que le support du navigateur devient banal.

https://github.com/uzairfarooq/arrive /

6
répondu Dave Kiss 2014-08-06 02:09:23
la source

Regardez ce plugin qui fait exactement que - jquery.initialiser

il fonctionne exactement comme .chaque fonction, la différence est qu'il prend sélecteur que vous avez entré et guetter de nouveaux éléments ajoutés dans le futur correspondant à ce sélecteur et de les initialiser

Initialize ressemble à ceci

$(".some-element").initialize( function(){
    $(this).css("color", "blue");
});

mais maintenant si le nouveau sélecteur .some-element apparaîtra sur la page, il sera instanty initialiser.

la façon dont le nouvel élément est ajouté n'est pas important, vous n'avez pas besoin de vous soucier des callbacks, etc.

donc si vous voulez ajouter un nouvel élément comme:

$("<div/>").addClass('some-element').appendTo("body"); //new element will have blue color!

il sera immédiatement initialisé.

Plugin est basé sur MutationObserver

3
répondu pie6k 2015-02-04 04:23:55
la source