Question

Je veux exécuter une fonction lorsque certains div ou d'entrée sont ajoutés à la page html.Est-ce possible?

Par exemple, une saisie de texte est ajouté, puis la fonction doit être appelée.

Était-ce utile?

La solution

2015 mise à jour, de nouvelles MutationObserver est pris en charge par les navigateurs modernes:

Chrome 18+, Firefox 14+, c'est à dire 11+, Safari 6+

Si vous avez besoin d'un soutien plus âgés, vous pouvez essayer de revenir à d'autres approches comme celles mentionnées dans ce 5 (!) ans réponse ci-dessous.Il y a des dragons.Enjoy :)


Quelqu'un d'autre est en train de changer le document?Parce que si vous avez le plein contrôle sur les modifications que vous avez juste besoin de créer votre propre domChanged API - avec une fonction ou d'événements personnalisés - et détente/appel partout où vous modifier les choses.

L' DOM de Niveau 2 a La Mutation des types d'événements, mais les anciennes version d'IE ne le supporte pas.Notez que la mutation événements sont obsolète dans le DOM3 Événements spec et avoir un les performances.

Vous pouvez essayer d'imiter la mutation de l'événement avec onpropertychange dans IE (et de revenir à la force brute approche si non est disponible).

Pour un plein domChange un intervalle peut être une sur-tuer.Imaginez que vous avez besoin pour stocker l'état actuel de l'ensemble du document, et d'examiner chaque élément de chaque propriété d'être le même.

Peut-être que si vous êtes seulement intéressés par les éléments et leur ordre (comme vous l'avez mentionné dans votre question), un getElementsByTagName("*") peut travailler.Cela déclenche automatiquement si vous ajoutez un élément, supprimer un élément, remplacer des éléments ou modifier la structure du document.

J'ai écrit une preuve de concept:

(function (window) {
    var last = +new Date();
    var delay = 100; // default delay

    // Manage event queue
    var stack = [];

    function callback() {
        var now = +new Date();
        if (now - last > delay) {
            for (var i = 0; i < stack.length; i++) {
                stack[i]();
            }
            last = now;
        }
    }

    // Public interface
    var onDomChange = function (fn, newdelay) {
        if (newdelay) delay = newdelay;
        stack.push(fn);
    };

    // Naive approach for compatibility
    function naive() {

        var last = document.getElementsByTagName('*');
        var lastlen = last.length;
        var timer = setTimeout(function check() {

            // get current state of the document
            var current = document.getElementsByTagName('*');
            var len = current.length;

            // if the length is different
            // it's fairly obvious
            if (len != lastlen) {
                // just make sure the loop finishes early
                last = [];
            }

            // go check every element in order
            for (var i = 0; i < len; i++) {
                if (current[i] !== last[i]) {
                    callback();
                    last = current;
                    lastlen = len;
                    break;
                }
            }

            // over, and over, and over again
            setTimeout(check, delay);

        }, delay);
    }

    //
    //  Check for mutation events support
    //

    var support = {};

    var el = document.documentElement;
    var remain = 3;

    // callback for the tests
    function decide() {
        if (support.DOMNodeInserted) {
            window.addEventListener("DOMContentLoaded", function () {
                if (support.DOMSubtreeModified) { // for FF 3+, Chrome
                    el.addEventListener('DOMSubtreeModified', callback, false);
                } else { // for FF 2, Safari, Opera 9.6+
                    el.addEventListener('DOMNodeInserted', callback, false);
                    el.addEventListener('DOMNodeRemoved', callback, false);
                }
            }, false);
        } else if (document.onpropertychange) { // for IE 5.5+
            document.onpropertychange = callback;
        } else { // fallback
            naive();
        }
    }

    // checks a particular event
    function test(event) {
        el.addEventListener(event, function fn() {
            support[event] = true;
            el.removeEventListener(event, fn, false);
            if (--remain === 0) decide();
        }, false);
    }

    // attach test events
    if (window.addEventListener) {
        test('DOMSubtreeModified');
        test('DOMNodeInserted');
        test('DOMNodeRemoved');
    } else {
        decide();
    }

    // do the dummy test
    var dummy = document.createElement("div");
    el.appendChild(dummy);
    el.removeChild(dummy);

    // expose
    window.onDomChange = onDomChange;
})(window);

Utilisation:

onDomChange(function(){ 
    alert("The Times They Are a-Changin'");
});

Cela fonctionne sur IE 5.5+, FF 2+, Chrome, Safari 3+ et Opera 9.6+

Autres conseils

C'est l'approche ultime jusqu'à présent, avec le plus petit code:

IE9 +, ff, webkit:

Utilisation de mutationObserver et retomber à la dépréciation Événements de mutation si nécessaire:

(exemple ci-dessous si seulement pour DOM change concernant les nœuds ajoutés ou supprimés)

var observeDOM = (function(){
  var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

  return function( obj, callback ){
    if( !obj || obj.nodeType !== 1 ) return; // validation

    if( MutationObserver ){
      // define a new observer
      var obs = new MutationObserver(function(mutations, observer){
          callback(mutations);
      })
      // have the observer observe foo for changes in children
      obs.observe( obj, { childList:true, subtree:true });
    }
    
    else if( window.addEventListener ){
      obj.addEventListener('DOMNodeInserted', callback, false);
      obj.addEventListener('DOMNodeRemoved', callback, false);
    }
  }
})();

//------------< DEMO BELOW >----------------
// add item
var itemHTML = "<li><button>list item (click to delete)</button></li>",
    listElm = document.querySelector('ol');

document.querySelector('body > button').onclick = function(e){
  listElm.insertAdjacentHTML("beforeend", itemHTML);
}

// delete item
listElm.onclick = function(e){
  if( e.target.nodeName == "BUTTON" )
    e.target.parentNode.parentNode.removeChild(e.target.parentNode);
}
    
// Observe a specific DOM element:
observeDOM( listElm, function(m){ 
   var addedNodes = [], removedNodes = [];

   m.forEach(record => record.addedNodes.length & addedNodes.push(...record.addedNodes))
   
   m.forEach(record => record.removedNodes.length & removedNodes.push(...record.removedNodes))

  console.clear();
  console.log('Added:', addedNodes, 'Removed:', removedNodes);
});


// Insert 3 DOM nodes at once after 3 seconds
setTimeout(function(){
   listElm.removeChild(listElm.lastElementChild);
   listElm.insertAdjacentHTML("beforeend", Array(4).join(itemHTML));
}, 3000);
<button>Add Item</button>
<ol>
  <li><button>list item (click to delete)</button></li>
  <li><button>list item (click to delete)</button></li>
  <li><button>list item (click to delete)</button></li>
  <li><button>list item (click to delete)</button></li>
  <li><em>&hellip;More will be added after 3 seconds&hellip;</em></li>
</ol>

J'ai récemment écrit un plugin qui fait exactement ce que - jquery.initialiser

Vous l'utilisez de la même manière que .each la fonction

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

La différence de .each est - il en faut du sélecteur, dans ce cas .some-element et d'attendre de nouveaux éléments avec le sélecteur dans le futur, si un tel élément sera ajouté, il sera initialisé trop.

Dans notre cas, la fonction d'initialisation juste changer l'élément de couleur bleu.Donc, si nous allons ajouter un nouvel élément (peu importe si avec ajax ou même F12 inspecteur ou quoi que ce soit) comme:

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

Plugin init instantanément.Aussi plugin permet de s'assurer qu'un élément est initialisé qu'une seule fois.Donc, si vous ajoutez l'élément, puis .detach() de corps, puis l'ajouter à nouveau, il ne sera pas initialisé à nouveau.

$("<div/>").addClass('some-element').appendTo("body").detach()
    .appendTo(".some-container");
//initialized only once

Le Plugin est basé sur MutationObserver - il va travailler sur IE9 et 10 avec dépendances détaillées sur le page readme.

ou vous pouvez simplement créer votre propre événement , qui courent partout

 $("body").on("domChanged", function () {
                //dom is changed 
            });


 $(".button").click(function () {

          //do some change
          $("button").append("<span>i am the new change</span>");

          //fire event
          $("body").trigger("domChanged");

        });

exemple complet http://jsfiddle.net/hbmaam/mq7nx/

L'exemple suivant a été adapté de Mozilla Hacks ' blog post et utilise MutationObserver .

// Select the node that will be observed for mutations
var targetNode = document.getElementById('some-id');

// Options for the observer (which mutations to observe)
var config = { attributes: true, childList: true };

// Callback function to execute when mutations are observed
var callback = function(mutationsList) {
    for(var mutation of mutationsList) {
        if (mutation.type == 'childList') {
            console.log('A child node has been added or removed.');
        }
        else if (mutation.type == 'attributes') {
            console.log('The ' + mutation.attributeName + ' attribute was modified.');
        }
    }
};

// Create an observer instance linked to the callback function
var observer = new MutationObserver(callback);

// Start observing the target node for configured mutations
observer.observe(targetNode, config);

// Later, you can stop observing
observer.disconnect();

Support de navigateur: Chrome 18+, Firefox 14+, soit 11+, Safari 6 +

Utilisez le Interface mutationObserver comme indiqué dans Gabriele Romanato's blog

Chrome 18+, Firefox 14+, soit 11+, Safari 6 +

// The node to be monitored
var target = $( "#content" )[0];

// Create an observer instance
var observer = new MutationObserver(function( mutations ) {
  mutations.forEach(function( mutation ) {
    var newNodes = mutation.addedNodes; // DOM NodeList
    if( newNodes !== null ) { // If there are new nodes added
        var $nodes = $( newNodes ); // jQuery set
        $nodes.each(function() {
            var $node = $( this );
            if( $node.hasClass( "message" ) ) {
                // do something
            }
        });
    }
  });    
});

// Configuration of the observer:
var config = { 
    attributes: true, 
    childList: true, 
    characterData: true 
};

// Pass in the target node, as well as the observer options
observer.observe(target, config);

// Later, you can stop observing
observer.disconnect();

Que diriez-vous de prolonger une jQuery pour cela?

   (function () {
        var ev = new $.Event('remove'),
            orig = $.fn.remove;
        var evap = new $.Event('append'),
           origap = $.fn.append;
        $.fn.remove = function () {
            $(this).trigger(ev);
            return orig.apply(this, arguments);
        }
        $.fn.append = function () {
            $(this).trigger(evap);
            return origap.apply(this, arguments);
        }
    })();
    $(document).on('append', function (e) { /*write your logic here*/ });
    $(document).on('remove', function (e) { /*write your logic here*/ ) });

JQuery 1.9+ a construit un support pour cela (j'ai entendu non testé).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top