lunes, 21 de noviembre de 2011

Saber si un elemento tiene un evento jQuery asignado

Hace poco he tenido la necesidad de saber si un elemento del DOM tenía adjuntado un  evento concreto de jQuery.

Lo cierto es que hay ya un plugin que sirve a este propósito (hablando de jQuery, no podía ser de otra forma, tiene que haber un plugin para todo…)

El plugin es jquery.hasEventListener https://github.com/sebastien-p/jquery.hasEventListener

Aunque no es costumbre en mí, esta vez no quería utilizar un plugin, sino que quería una función sencilla sin mayor sobrecarga.

Siendo así y a partir de la información obtenida en la siguiente discusión en stackoverflow,  http://stackoverflow.com/questions/1515069/jquery-check-if-event-exists-on-element, me he animado a hacer mi propia función, ligera y suficiente para mis requerimientos.

Según parece, jQuery guarda por cada elemento DOM, los eventos asignados como un dato llamado “events” en su propiedad data. De este modo, simplemente hay que iterar sobre este dato para averiguar si un elemento DOM tiene un evento en concreto asignado.

Además, la guía de buen estilo de creación de plugins para jQuery, recomienda adjuntar los eventos con un nombre identificador para nuestro plugin. Es decir, mejor panicoenlaxbox.click que simplemente click, así después podremos retirar sólo nuestros eventos sin tener conflictos con eventos de terceros.

Para la situación en que utilicemos eventos con espacios de nombres, la función igualmente permite especificar esto y funcionará correctamente.

El código de la función es el siguiente:

function hasEventListener(element, eventName, namespace) {

            var returnValue = false;

            var events = $(element).data("events");

            if (events) {

                $.each(events, function (index, value) {

                    if (index == eventName) {

                        if (namespace) {

                            $.each(value, function (index, value) {

                                if (value.namespace == namespace) {

                                    returnValue = true;

                                    return false;

                                }

                            });

                        }

                        else {

                            returnValue = true;

                            return false;

                        }

                    }

                });

            }

            return returnValue;

        }


Con esta función ahora podemos escribir lo siguiente:

$(document).click(function (e) {

alert("Sergio");

});

alert(hasEventListener($(document), "click")); // true

 

o esto otro:

$(document).bind("click.Sergio", function (e) {

alert("Sergio");

});           

alert(hasEventListener($(document), "click", "Sergio")); // true


Un saludo!

4 comentarios:

  1. Excelente dato, estoy trabajando en una aplicación donde manipulo bastantes elementos con eventos y tu información me viene excelente, una pregunta, sabes de algún metodo para administrar "automaticamente" los eventos en elementos del dom?, me refiero a que si por ejemplo, se elimina del dom X elementos y estos tienen asociado un evento este sea eliminado al igual que el elemento?, pregunto esto porque a mi JQuery mantiene los eventos aun si el elemento fue eliminado del dom, por lo tanto, si vuelvo a crear el mismo elemento, este tiene el evento del elemento borrado, por lo tanto si vuelvo a asignar el evento este se repite, por ejemplo, en un elemento "a" se le asigna el evento "click", se borra y se vuelve a crear en algún momento, si ahora se le da click al elemento será como si se da dos veces click...

    Lamento un comentario tan largo...

    ResponderEliminar
  2. El método .remove() de jQuery remueve los eventos y datos asociados al elemento y su documentación lo dice claramente:

    "In addition to the elements themselves, all bound events and jQuery data associated with the elements are removed. To remove the elements without removing data and events, use .detach() instead."

    ResponderEliminar
  3. Una pregunta,uno puede saber cuando el evento continua vivo, por ejemplo

    tengo un menu (ul) con un item li class="padre" , dentro de ese li tengo otro ul con dos li hijos, el codigo es el siguiente

    li class="padre
    ul
    li hijo 1 /li
    li hijo 1 /li
    /ul
    /li
    script
    $(document).ready(function (){
    $(".padre").hover(muestra,oculta)
    function muestra()
    {
    $(this).children("ul").slideDown("slow").delay(2000)
    }
    function oculta()
    {
    $(this).children("ul").slideUp("slow")
    }

    /script


    paso por encima el mouse y se despliega la ul, pero cuando me paro encima de la ul, se ejecuta oculta() apesar del delay, y no se suponia que la ul esta dentro del li.padre ?

    lo que yo quiero es hacer una especie de ciclo mediante el cual no pase ala funcion siguiente del hover->oculta si me paro encima de la ul hija.

    espero me puedas ayudar, si ecesitas el codigo fuente para comprender mejor te lo doy.

    ResponderEliminar
  4. Buena esa, me sirvio la info para resolver el mismo problema, aunque al aplicarla no me dio resultado, despues de investigar me encontre que en las versiones >= 1.8 fue eliminado $(element).data("events").

    http://rahosudce.blogspot.mx/2013/11/re-saber-si-un-elemento-tiene-un-evento.html

    Saludos!

    ResponderEliminar