2011-04-09 8 views
6

Estoy vinculando un evento de un solo clic a un contenedor grande usando jquery (delegación de eventos).JavaScript Event Delegation code organization

Tengo muchos elementos diferentes dentro de ese contenedor en los que se puede hacer clic.

El problema que me preocupa es que si tengo 20 elementos que se pueden hacer clic, necesito hacer un bloque if else x 20 en el contenedor en el controlador de clic. ¿Hay alguna manera de hacer esto más limpio? Por ejemplo:

attachClickEvent:function(){ 
    $(".container").click($.proxy(this.handleOnClick,this)); 
}, 
handleOnClick:function(event){ 
    var $target = $(event.target); 
    if($target.closest(".widget1").length >0){ 
     //handle widget 1 interaction 
    }else if($target.closest(".widget2").length >0){ 
     //handle widget 2 interaction 
    }else if($target.closest(".widget3").length >0){ 
     //handle widget 3 interaction 
    }else if($target.closest(".widget4").length >0){ 
     //handle widget 4 interaction 
    }else if($target.closest(".widget5").length >0){ 
     //handle widget 5 interaction 
    } 
} 

etc.

Respuesta

2

primera cosa que viene a la mente es el uso de un bucle:

var handlers = { 
    "widget1": function(event, candidate){}, 
    "widget2": function(event, candidate){} 
} 

$.each(handlers, function(cssClass,handler){ 
    var sel = '.'+cssClass; 
    var candidate = target.closest(sel); 
    if(candidate.length > 0) { 
    handler(event, candidate); 
    break; 
    } 
}); 
+0

Esto es lo que estaba pensando también, gracias. – Abadaba

+0

Su uso del objetivo implica que está ejecutando este bucle dentro del controlador de clic. Esto no es bueno porque tendrá que ejecutar $ (target) .closest() potencialmente más de 20 veces para encontrar la propiedad correspondiente. También está utilizando la palabra clave 'class', que se eliminará en webkit. – typeof

+0

@typeof: se está ejecutando dentro del controlador de clics ... él está delegando en el elemento primario que contiene un conjunto de 20 elementos que tienen cada uno acciones específicas del controlador. Por lo tanto, necesita pasar por todos los selectores hasta que obtenga una coincidencia e invocar la función del controlador asociado. 'target.closest (sel)' es su prueba ... allí debe invocarse en cada iteración hasta que coincida, luego cuando se rompe el partido. Cambié el nombre de la variable ... aunque este deseo era código de trabajo ... solo un ejemplo aproximado – prodigitalson

0

HTML

<div class="container"> 
<div id="cont1"></div> 
<div id="cont2"></div> 
<div id="cont3"></div> 
<div id="cont4"></div> 
<div id="cont5"></div> 
<div id="cont6"></div> 
. 
. 
. 

</div> 

jQuery

$(".container").find("div").click(function(){ 
id = $(this).attr("id"); 
if(id=="cont1"){ 
... 
} 
else if(id=="cont2"){ 
.. 
} 
.. 
else{ 
.. 
} 
}); 
+0

Ya no se trata de una delegación de eventos, está vinculando un evento a cada div. Además, todavía estás haciendo un número de divisiones if/else x. – Abadaba

0

Ésta es quizás algo que busca. Hay muchas formas diferentes de hacer esto.

<div id="widgetcontainer"> 
    <div id="widget1">A</div> 
    <div id="widget2">B</div> 
    <div id="widget3">C</div> 
    <div id="widget4">D</div> 
    <div id="widget5">E</div> 
</div> 

Aquí está la JS

function someAction() { 
    alert("Hey"); 
} 


$(function() { 
    var wc = $("#widgetcontainer div"); 
    for (var i = 0; i < wc.length; i++) { 
     $(wc[i]).click(function() { 
      someAction(); 
     }); 
    } 
}); 
+0

Esto todavía no es una delegación de eventos. La delegación de eventos vincula un único evento al padre y escucha los eventos que surgen de los clics en los nodos secundarios. Aquí está vinculando un evento de clic a cada div. – Abadaba

0

Cómo sobre el uso delegate?

$(".container"). 
    delegate(".widget1", "click", widget_1_handler). 
    delegate(".widget2", "click", widget_2_handler) 
; 
2

crear el objeto con funciones

Un poco tarde al juego con esto, pero usted debe considerar la organización de su código como este.

Si tiene 20 acciones únicas para sus widgets, irá a todo ese código. Intenta reutilizar el código común creando funciones. Hacer una estructura como esta:

var actions = { 
    'widget1' : function(event) { 
     // handle widget 1 interaction 
    }, 
    'widget2' : function(event) { 
     // handle widget 2 interaction 
    }, 
    'widget3' : function(event) { 
     // handle widget 3 interaction 
    }, 
    call : function(event) { 
     var prefix = "widget", 
      widget = $(event.target).closest('[class^="'+prefix+'"]'), 
      classN; 
     if(widget.length) { 
      classN = widget.attr('class').replace(new RegExp('.*('+prefix+'\\d*).*$'), '$1'); 
      if(classN in this) { 
       this[classN](event); 
      } 
     } 
    } 
}; 

ejecución simplificado

Entonces, desde su controlador de clic, sólo tiene que llamar a la función como esta:

handleOnClick : function(event) { 
    actions.call(event) 
} 
1

jQuery ofrece esta funcionalidad fuera de la caja :

$('.container').on('click', '.widget1', function() { 
    // handle widget 1 interaction 
}); 

$('.container').on('click', '.widget2', function() { 
    // handle widget 2 interaction 
}); 

Recientemente escribí una: biblioteca para extraer eso si no está usando jQuery. Se llama cocodrilo. Puede ver ejemplos y/o documentación en: http://craig.is/riding/gators

se puede hacer algo como

Gator(container_element).on('click', '.widget1', function() { 
    // handle widget 1 interaction 
}); 

Gator(container_element).on('click', '.widget2', function() { 
    // handle widget 2 interaction 
}); 

Tanto jQuery y Gator solamente se unen a un solo evento de clic al elemento contenedor y manejar el envío de los eventos internos.