elementos - lista de eventos javascript




Ligação de evento em elementos criados dinamicamente? (16)

Eu tenho um pouco de código onde eu estou em loop através de todas as caixas de seleção em uma página e ligando um evento .hover para eles para fazer um pouco de mexer com a sua largura no mouse on/off .

Isso acontece na página pronto e funciona muito bem.

O problema que tenho é que qualquer caixa de seleção que eu adicione via Ajax ou DOM após o loop inicial não terá o evento ligado.

Eu encontrei este plugin ( jQuery Live Query Plugin ), mas antes de adicionar outro 5k às minhas páginas com um plugin, eu quero ver se alguém sabe uma maneira de fazer isso, seja com jQuery diretamente ou por outra opção.


Ligação de evento em elementos criados dinamicamente

Elemento único:

$(document.body).on('click','.element', function(e) {  });

Elemento filho:

 $(document.body).on('click','.element *', function(e) {  });

Observe o adicionado * . Um evento será acionado para todos os filhos desse elemento.

Eu notei que:

$(document.body).on('click','.#element_id > element', function(e) {  });

Não está mais funcionando, mas estava funcionando antes. Eu tenho usado o jQuery do Google CDN , mas não sei se eles mudaram.


Esta é uma solução JavaScript pura , sem quaisquer bibliotecas ou plugins:

document.addEventListener('click', function (e) {
    if (hasClass(e.target, 'bu')) {
        // .bu clicked
        // Do your thing
    } else if (hasClass(e.target, 'test')) {
        // .test clicked
        // Do your other thing
    }
}, false);

onde hasClass é

function hasClass(elem, className) {
    return elem.className.split(' ').indexOf(className) > -1;
}

Demonstração ao vivo

O crédito vai para Dave e Sime Vidas

Usando o JS mais moderno, o hasClass pode ser implementado como:

function hasClass(elem, className) {
    return elem.classList.contains(className);
}

Eu prefiro que os ouvintes de eventos sejam implantados de maneira modular ao invés de criar scripts para um ouvinte de eventos no nível do document . Então, eu gosto abaixo. Observe que você não pode se inscrever demais em um elemento com o mesmo ouvinte de eventos, portanto, não se preocupe em anexar um ouvinte mais de uma vez - apenas um deles fica preso.

var iterations = 4;
var button;
var body = document.querySelector("body");

for (var i = 0; i < iterations; i++) {
    button = document.createElement("button");
    button.classList.add("my-button");
    button.appendChild(document.createTextNode(i));
    button.addEventListener("click", myButtonWasClicked);
    body.appendChild(button);
}

function myButtonWasClicked(e) {
    console.log(e.target); //access to this specific button
}


Eu prefiro usar o seletor e aplicá-lo no documento.

Isso se liga ao documento e será aplicável aos elementos que serão renderizados após o carregamento da página.

Por exemplo:

$(document).on("click", $(selector), function() {
    // Your code here
});

Isso é feito pela delegação de eventos. O evento será vinculado ao elemento da classe wrapper, mas será delegado ao elemento da classe do seletor. É assim que funciona.

$('.wrapper-class').on("click", '.selector-class', function() {
    // Your code here
});

Nota:

O elemento wrapper-class pode ser qualquer coisa ex. documento, corpo ou seu invólucro. Invólucro já deve existir.


Outra solução é adicionar o ouvinte ao criar o elemento. Em vez de colocar o ouvinte no corpo, você coloca o ouvinte no elemento no momento em que o cria:

var myElement = $('<button/>', {
    text: 'Go to Google!'
});

myElement.bind( 'click', goToGoogle);
myElement.append('body');


function goToGoogle(event){
    window.location.replace("http://www.google.com");
}

Tente assim -

$(document).on( 'click', '.click-activity', function () { ... });

Tente usar .live() vez de .bind() ; o .live() ligará o .hover à sua caixa de seleção depois que a solicitação do Ajax for executada.


Use o método .on() do jQuery on() para anexar manipuladores de eventos ao elemento live.

Também a partir da versão 1.9 o método .live() é removido.


Veja por que elementos criados dinamicamente não respondem a cliques:

var body = $("body");
var btns = $("button");
var btnB = $("<button>B</button>");
// `<button>B</button>` is not yet in the document.
// Thus, `$("button")` gives `[<button>A</button>]`.
// Only `<button>A</button>` gets a click listener.
btns.on("click", function () {
  console.log(this);
});
// Too late for `<button>B</button>`...
body.append(btnB);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>

Como solução alternativa, você precisa ouvir todos os cliques e verificar o elemento de origem:

var body = $("body");
var btnB = $("<button>B</button>");
var btnC = $("<button>C</button>");
// Listen to all clicks and
// check if the source element
// is a `<button></button>`.
body.on("click", function (ev) {
  if ($(ev.target).is("button")) {
    console.log(ev.target);
  }
});
// Now you can add any number
// of `<button></button>`.
body.append(btnB);
body.append(btnC);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>

Isso é chamado de "Delegação de Eventos". Boas notícias, é um recurso embutido no jQuery :-)

var i = 11;
var body = $("body");
body.on("click", "button", function () {
  var letter = (i++).toString(36).toUpperCase();
  body.append($("<button>" + letter + "</button>"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>


Você pode adicionar eventos a objetos quando os cria. Se você estiver adicionando os mesmos eventos a vários objetos em momentos diferentes, criar uma função nomeada pode ser o caminho a percorrer.

var mouseOverHandler = function() {
    // Do stuff
};
var mouseOutHandler = function () {
    // Do stuff
};

$(function() {
    // On the document load, apply to existing elements
    $('select').hover(mouseOverHandler, mouseOutHandler);
});

// This next part would be in the callback from your Ajax call
$("<select></select>")
    .append( /* Your <option>s */ )
    .hover(mouseOverHandler, mouseOutHandler)
    .appendTo( /* Wherever you need the select box */ )
;

Você pode anexar evento ao elemento quando criado dinamicamente usando jQuery(html, attributes) .

A partir do jQuery 1.8 , qualquer método de instância jQuery (um método de jQuery.fn ) pode ser usado como uma propriedade do objeto passado para o segundo parâmetro:

function handleDynamicElementEvent(event) {
  console.log(event.type, this.value)
}
// create and attach event to dynamic element
jQuery("<select>", {
    html: $.map(Array(3), function(_, index) {
      return new Option(index, index)
    }),
    on: {
      change: handleDynamicElementEvent
    }
  })
  .appendTo("body");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>


Você pode usar o método live () para vincular elementos (até mesmo recém-criados) a eventos e manipuladores, como o evento onclick.

Aqui está um código de exemplo que escrevi, onde você pode ver como o método live () associa os elementos escolhidos, até mesmo os recém-criados, aos eventos:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Untitled Document</title>
    </head>

    <body>
        <script src="http://code.jquery.com/jquery-latest.js"></script>
        <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.16/jquery-ui.min.js"></script>

        <input type="button" id="theButton" value="Click" />
        <script type="text/javascript">
            $(document).ready(function()
                {
                    $('.FOO').live("click", function (){alert("It Works!")});
                    var $dialog = $('<div></div>').html('<div id="container"><input type ="button" id="CUSTOM" value="click"/>This dialog will show every time!</div>').dialog({
                                                                                                         autoOpen: false,
                                                                                                         tite: 'Basic Dialog'
                                                                                                     });
                    $('#theButton').click(function()
                    {
                        $dialog.dialog('open');
                        return('false');
                    });
                    $('#CUSTOM').click(function(){
                        //$('#container').append('<input type="button" value="clickmee" class="FOO" /></br>');
                        var button = document.createElement("input");
                        button.setAttribute('class','FOO');
                        button.setAttribute('type','button');
                        button.setAttribute('value','CLICKMEE');
                        $('#container').append(button);
                    });
                    /* $('#FOO').click(function(){
                                                     alert("It Works!");
                                                 }); */
            });
        </script>
    </body>
</html>

você poderia usar

$('.buttons').on('click', 'button', function(){
    // your magic goes here
});

ou

$('.buttons').delegate('button', 'click', function() {
    // your magic goes here
});

Esses dois métodos são equivalentes, mas têm uma ordem diferente de parâmetros.

veja: jQuery Delegate Event


Solução mais flexível para criar elementos e vincular eventos ( source )

// creating a dynamic element (container div)
var $div = $("<div>", {id: 'myid1', class: 'myclass'});

//creating a dynamic button
 var $btn = $("<button>", { type: 'button', text: 'Click me', class: 'btn' });

// binding the event
 $btn.click(function () { //for mouseover--> $btn.on('mouseover', function () {
    console.log('clicked');
 });

// append dynamic button to the dynamic container
$div.append($btn);

// add the dynamically created element(s) to a static element
$("#box").append($div);

Nota: Isso criará uma instância do manipulador de eventos para cada elemento (pode afetar o desempenho quando usado em loops)


<html>
    <head>
        <title>HTML Document</title>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
    </head>

    <body>
        <div id="hover-id">
            Hello World
        </div>

        <script>
            jQuery(document).ready(function($){
                $(document).on('mouseover', '#hover-id', function(){
                    $(this).css('color','yellowgreen');
                });

                $(document).on('mouseout', '#hover-id', function(){
                    $(this).css('color','black');
                });
            });
        </script>
    </body>
</html>






unobtrusive-javascript