Run Function when the element appears in the gift

Asked

Viewed 657 times

2

How to run a function where a particular item exists in the DOM?

For example, I have a list with 4 elements, and whenever a new element appears I want to run a certain function. Example code below:

// Função a ser executada
function fazAlgoNaLI() {
  $(this).addClass('alterada');
}

// Execução quando os elementos já existem no dom
$('li').each(fazAlgoNaLI);

// Agora vamos adicionando elementos após e preciso executar a funcion quando esse elemento for adicionado
setInterval(function() {
  $('ul').append('<li>Nova linha</li>');
}, 1000);
.alterada {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li>Linha 1</li>
  <li>Linha 2</li>
  <li>Linha 3</li>
</ul>

OBS1: One premise is that I have no way of controlling the moment that this element is changed as there are several third party Javascripts that are all minified. Then I need an event that runs Function when the DOM is changed.


OBS2: I managed with a setInterval running for example every 100 milliseconds, check and execute the function, but wanted a more performative solution that was not running a function all the time in the application.

  • 2
  • The problem with Mutationobserver is that the browser implementation is not yet reliable...

  • 1

    To date? This specification is already a good few years old. The compatibility table you have on MDN seems ok.

  • @bfavaretto I was going to comment, only Safari 6 and 7 that require the prefix. Other browsers considered modern (in "day") work perfectly :)

1 answer

2


I suggest you use one of these 3 ways to check:

Setting a property in the element

First of all I recommend you read this:

So if the structure is in fact simple the way it did, and the elements are always Lis then a setTimeout that would check those who already own the property or not:

// Função a ser executada
function fazAlgoNaLI() {
    if (this.alterado) return; //Ignora se já tiver a propriedade

    this.alterado = true;
    
    $(this).addClass('alterada');
}

// Agora vamos adicionando elementos após e preciso executar a funcion quando esse elemento for adicionado
setInterval(function() {
  $('.foo').append('<li>Nova linha</li>');
}, 1000);

/* verifica alterações*/
var quantidade = 0;
(function mutacao() {
    var lis = $('.foo > li');

    //verifica se a quantidade aumentou
    if (quantidade !== lis.length) {
        lis.each(fazAlgoNaLI);
        quantidade = lis.length; //Atualiza a ultima quantidade
    }
    
    setTimeout(mutacao, 100);
})();
.alterada {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<ul class="foo">
  <li>Linha 1</li>
  <li>Linha 2</li>
  <li>Linha 3</li>
</ul>

Using the selector :not(...)

Or you can take only those who don’t have the class class="alterada", for this use the selector :not(...), do so:

// Função a ser executada
function fazAlgoNaLI() {
    $(this).addClass('alterada');
}

// Agora vamos adicionando elementos após e preciso executar a funcion quando esse elemento for adicionado
setInterval(function() {
  $('.foo').append('<li>Nova linha</li>');
}, 1000);

(function mutacao() {
    var lis = $('.foo > li:not(.alterada)'); //Pega somente elementos que não tiverem a classe alterada

    lis.each(fazAlgoNaLI);
    
    setTimeout(mutacao, 100);
})();
.alterada {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<ul class="foo">
  <li>Linha 1</li>
  <li>Linha 2</li>
  <li>Linha 3</li>
</ul>

Using Mutationobserver

You can use the MutationObserver which checks with combined with addedNodes, only the new elements added and then you can match with .filter, jQuery, to check if it is a valid tag, or in case it was a LI added:

// Função a ser executada
function fazAlgoNaLI() {
    $(this).addClass('alterada');
}

// Agora vamos adicionando elementos após e preciso executar a funcion quando esse elemento for adicionado
setInterval(function() {
    $('.foo').append('<li>Nova linha</li>');
}, 1000);

/* verifica alterações*/
var isReady = 0;

var observer = new MutationObserver(function( mutations ) {
  mutations.forEach(function( mutation ) {
    var nn = mutation.addedNodes;

    if (nn !== null) {

        console.log("Foi adicionado " + nn.length + " novo elemento");

        $(nn).filter('li').each(fazAlgoNaLI);
    }
  });    
});

var config = { 
    childList: true
};

//Inicia o observador
observer.observe($(".foo").get(0), config);
.alterada {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<ul class="foo">
  <li>Linha 1</li>
  <li>Linha 2</li>
  <li>Linha 3</li>
</ul>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.