2010-07-30 17 views
9

Me pregunto si es posible hacer el siguiente código más conciso:Múltiples selectores o funciones múltiples: ¿ganancias de eficiencia?

$('#americasTrigger').hover(
    function() { 
      $('#americasImg').fadeIn() 
     }, 
    function(){ 
      $('#americasImg').fadeOut() 
    } 
); 

$('#europeTrigger').hover(
    function() { 
     $('#europeImg').fadeIn(); 
    }, 
    function(){ 
     $('#europeImg').fadeOut(); 
    } 
);  

$('#middleEastTrigger').hover(
    function() { 
     $('#middleEastImg').fadeIn(); 
    }, 
    function(){ 
     $('#middleEastImg').fadeOut(); 
    } 
);  

//More etc 

El nombre del país se mantiene igual para cada uno, con el 'disparador' o 'Img' agregado al final. Hay mucha repetición aquí que me indica que no voy a hacerlo de la mejor manera.

tuve pensamientos en torno a:

  • Crearting un escenario, o
  • De alguna manera conseguir el selector se utiliza para una selección, por lo que es una cadena, dividiendo su nombre para capturar el país en el uso y la aplicación de eso a la función anulada de fadeIn/Out con 'Img' en el extremo.

¿Es posible o estoy siendo demasiado elegante?

Edit 1: Muchas gracias por todas las respuestas, las disculpas por no publicar el html, lo he puesto a continuación. En resumen, estoy usando mapas de imágenes sobre una imagen bg (de tierra) a medida que el control deslizante se activa para desvanecer o desvanecer mis imágenes en vuelo con posicionamiento absoluto.

<div class="mapTub"> 

    <img src="images/transparentPixel.png" class="mapCover" usemap="#worldMap" width="524px" height="273px"/> 

    <map name="worldMap" id="worldMap"> 
    <area id="americasTrigger" shape="poly" coords="1,2,3" href="#americas" /> 
    <area id="europeTrigger" shape="poly" coords="4,5,6" href="#europe" /> 
    <area id="middleEastTrigger" shape="poly" coords="7,8,9" href="#middleEast" /> 
    </map> 

<img src="images/International_americas_dark.png" class="americas" id="americasImg" /> 
<img src="images/International_europe_dark.png" class="europe" id="europeImg" /> 
<img src="images/International_middleEast_dark.png" class="middleEast" id="middleEastImg" /> 

</div> 

respuesta de Reigel parece que el camino a seguir aquí, los malos probarlo informe posterior, más comentarios de bienvenida! :)

+1

códigos html por favor ... – Reigel

+0

Sí, un ejemplo de lo que parece HTML sería útil. – belugabob

Respuesta

2

Me, sin conocimiento del HTML, sugiero esto ...

$('#americasTrigger, #europeTrigger, #middleEastTrigger').hover(
    function() { 
     var id = this.id; 
     $('#'+id.replace('Trigger', 'Img')).fadeIn(); 
     //$('#'+id.slice('0',id.indexOf('Trigger'))+'Img').fadeIn(); 
    }, 
    function(){ 
     var id = this.id; 
     $('#'+id.replace('Trigger', 'Img')).fadeOut(); 
     //$('#'+id.slice('0',id.indexOf('Trigger'))+'Img').fadeOut(); 
    } 
); 

También puede utilizar .replace() según lo sugerido por Anurag en el comentario más abajo ...


id ='europeTrigger'; 
alert(id.slice('0',id.indexOf('Trigger'))); // alerts 'europe' 
// '#'+id.slice('0',id.indexOf('Trigger'))+'Img' is '#europeImg' 

demo

+0

puede reemplazar eso con 'id.replace ('Trigger', 'Img')' – Anurag

+0

@Anurag ¡jaja! espera, actualizando ... – Reigel

+0

Niza una Reigel, esto funcionó una delicia, gracias! – demolish

2

Dado que parece que solo está accediendo a unique ids, su mejor opción es utilizar un lookup table IMO.

var lookmeup = [ [$('#americasTrigger'), $('#americasImg')], 
        [$('#europeTrigger'), $('#europeImg')], 
        [$('#middleEastTrigger'), $('#middleEastImg')] 
       ]; 

$.each(lookmeup, function(index, element){ 
    element[0].hover(function(){ 
     element[1].fadeIn(); 
    }, function(){ 
     element[1].fadeOut(); 
    }); 
}); 

DRY! ¡todo listo!

Otra forma de hacerlo de una manera más eficiente sería usar event delegation.

Si todos sus hover elementos tienen la misma TAG, este enfoque podría ser útil:

$(document.body).delegate('div', 'mouseenter', function(e){ 
    $('#' + e.target.id.replace(/Trigger/, 'Img')).fadeIn(); 
}); 

$(document.body).delegate('div', 'mouseleave', function(e){ 
    $('#' + e.target.id.replace(/Trigger/, 'Img')).fadeOut(); 
}); 

Suponiendo que todas sus "hoverable" elementos eran DIV s. Aún debe darles a esos elementos un classname para que solo esos elementos específicos estén dirigidos.

Tiene mucho sentido confinar el root element para delegate().Aquí uso document.body que sería .live() do. Lo bueno de .delegate() es que si los elementos de desplazamiento flotante comparten un nodo principal, puede aplicar delegate() en ese nodo. De esta forma, se reduce el número de controladores de eventos vinculados al

(2 en lugar de 6).

+0

Hola, Andy, esto también se ve bien, acabo de publicar el código html en la operación original, ¿tienes alguna idea sobre tu método deligate frente al método de corte/reemplazo de Reigal en términos de rendimiento? – demolish

0

lol, parece que esto puede ser del mismo tamaño o más largo que su código, pero definitivamente más seco.

Gracias a @Andy por señalar la penalización de rendimiento con la versión anterior con $(..).each.

var regions = ['americas', 'europe', 'middleEast']; 

$.each(regions, function(region) { 
    var trigger = id(region, 'Trigger'); 
    var image = id(region, 'Image'); 

    $(trigger).hover(
     effect(image, 'fadeIn'), 
     effect(image, 'fadeOut'), 
    ); 
}); 

function effect(selector, method) { 
    return function() { 
     $(selector)[method](); 
    }; 
} 

function id(prefix, suffix) { 
    return '#' + prefix + suffix; 
} 

Si puede cambiar el código HTML, me codificar todo el conocimiento en la propia página, y sólo tiene que utilizar jQuery para eventos de configuración de la libración.

<div class='trigger' data-image='#americasImg'> 
    .. 
</div> 
<div class='trigger' data-image='#europeImg'> 
    .. 
</div> 

Javascript

function imageId(elem) { 
    return $(elem).attr('data-image'); 
} 

// Using the fade function from before 
$('.trigger').hover(
    effect(imageId(this), 'fadeIn'), 
    effect(imageId(this), 'fadeOut') 
); 
+0

Usaría '$ .each()', no se necesita un constructor de jQuery adicional. ¿El guión bajo como primer parámetro es un truco o error muy especial? :) – jAndy

+0

@jAndy - gracias por la sugerencia. Nunca me di cuenta de la penalización de rendimiento. (Simplemente no me gustó el aspecto de '$ .each' pero supongo que es un mal necesario :).El guión bajo fue solo una señal para indicar que el parámetro es inútil. – Anurag

0

O, para hacer las cosas mucho más simples, agregar una clase marcador, denominado 'fadingImage', por ejemplo, a cada una de las imágenes y luego usar este código ...

$('.fadingImage').hover( 
    function() { 
     $(this).fadeIn() 
    }, 
    function(){ 
     $(this).fadeOut() 
    } 
); 

Esto funciona porque todas las imágenes, independientemente de su id, se manejan de la misma manera, todo lo que necesita hacer es identificar qué imágenes de su página deben tener los manipuladores de anulación conectados, y thi s se hace con la clase de marcador. Incluso podría prescindir por completo de los identificadores, si no se utilizan para nada más.

Actualización: Sin que yo he despertado (Gracias Jandy & Reigel!), Voy a enmendar mi post para lidiar con el hecho de que siendo el elemento cernía no es el que está siendo desvaneció.

Sin tener que marcar ninguna muestra, voy a tener que hacer algunas suposiciones, pero el póster original puede querer proporcionar el marcado real, para poner las cosas en contexto.

<div> 
    <span class="fadingTrigger">first text to hover over<span> 
    <img class="fadingImage" src="..." alt="first image to be faded"/> 
<div> 
<div> 
    <span class="fadingTrigger">second text to hover over<span> 
    <img class="fadingImage" src="..." alt="second image to be faded"/> 
<div> 

$('.fadingTrigger').hover( 
    function() { 
     $(this).parent().find(".fadingImage").fadeIn() 
    }, 
    function(){ 
     $(this).parent().find(".fadingImage").fadeOut() 
    } 
); 

Dependiendo de la estructura de marcado, el método de búsqueda de la fadingImage que está asociado con el fadingTrigger puede tener que variar, pero por tener una estructura bien definida, debe ser fiable.

La razón por la que preferiría este método antes que usar una matriz de identificadores para buscar los elementos es que cualquier adición al marcado requeriría cambios en el javascript; esto sería especialmente problemático si el marcado se generó dinámicamente. El javascript también podría generarse dinámicamente, para incluir la matriz apropiada de valores, pero violaría el principal DRY.

+0

+1 más simplificado =) –

+0

Esto no funciona, ya que el OP utiliza diferentes elementos/identificadores para desplazarse. – jAndy

+0

Sí, pero no hay necesidad de que lo haga, incluso admite, él mismo, que su código es muy repetitivo. – belugabob

Cuestiones relacionadas