2010-08-10 4 views
4

jQuery débutant ici.Comment consolider mon code jQuery répétitif en une seule fonction?

Voici ce sur quoi je travaille. J'ai une carte de zone avec 10 hotspots dessus. Passez la souris sur chacun des hotspots et déplacez l'arrière-plan du div (id = dialpad) pour afficher d'autres données (dans un sprite).

Le code que j'ai actuellement fonctionne, mais j'ai une fonction séparée pour chaque ID de point d'accès.

Ex:

$('#dial1') 
    // On mouse over, move the background on hover 
    .mouseover(function() { 
    $('#dialpad').css('backgroundPosition', '0 -120px'); 
    }) 
    // On mouse out, move the background back 
    .mouseout(function() { 
    $('#dialpad').css('backgroundPosition', '0 0'); 
    }) 
    $('#dial2') 
    // On mouse over, move the background on hover 
    .mouseover(function() { 
    $('#dialpad').css('backgroundPosition', '0 -240px'); 
    }) 
    // On mouse out, move the background back 
    .mouseout(function() { 
    $('#dialpad').css('backgroundPosition', '0 0'); 
    }); 
    ... 

Ce que je veux faire est de consolider ce code dans une fonction unique où je passe simplement le chiffre décalage vertical de chaque ID de zone.

Quelqu'un peut-il vous aider?

Répondre

5
$('#dial1,#dial2').hover(
    function() { changePosition('0 ' + (parseInt(this.id.match(/\d+$/)[0])) * -120 + 'px'); }, 
    function() { changePosition('0 0'); } 
); 

function changePosition(position) { 
    $('#dialpad').css('backgroundPosition', position); 
} 

Mise à jour:

Par ailleurs, si les « points chauds » se produisent sur la page dans le même ordre que les numéros d'index, vous pouvez alors prendre une approche légèrement plus efficace et donnez-leur tous une classe et utilisez la propriété index de .each() pour déterminer le bon numéro d'index.

$('.hotspots').each(function(idx) { 
    $(this).hover(
     function() { changePosition('0 ' + ((idx + 1) * -120) + 'px'); }, 
     function() { changePosition('0 0'); } 
    ); 
}); 

function changePosition(position) { 
    $('#dialpad').css('backgroundPosition', position); 
} 

En fait, vous avez vraiment besoin de ne pas la fonction changePosition() si vous ne voulez pas. Le code est assez court pour qu'un peu de répétition ne soit pas un gros problème.

$('.hotspots').each(function(idx) { 
    $(this).hover(
     function() { $('#dialpad').css('backgroundPosition', '0 ' + ((idx + 1) * -120) + 'px')}, 
     function() { $('#dialpad').css('backgroundPosition', '0 0'); } 
    ); 
});​ 
+0

Neat ... mais ne laissez-vous 'passer le décalage vertical'. – sje397

+0

@ sje397 - Bien sûr que oui. Le résultat de 'parseInt()' est multiplié par '-120'. J'ai juste oublié d'ajouter le 'px' à la chaîne. Mise à jour ... – user113716

+1

$(). Hover() est un raccourci pour mouseenter/mouseleave, pas mouseover/mouseout. D'une part j'apprécie la brièveté de cette solution ... mais l'appariement d'expressions régulières pour déterminer le décalage? Sentiments mixtes ... – jmar777

0
function setupDial(selector, offset) { 
    function resetPos() { 
    $('#dialpad').css('backgroundPosition', '0 0'); 
    } 
    function setPos(int p) { 
    return function() { 
     $('#dialpad').css('backgroundPosition', '0 ' + p + 'px'); 
    } 
    } 

    $(selector) 
    // On mouse over, move the background on hover 
    .mouseover(setPos(offset)) 
    // On mouse out, move the background back 
    .mouseout(resetPos); 
} 

setupDial('#dial1', -120); 
setupDial('#dial2', -240); 
1

est de façon Cleanest faire un plugin rapide:

(function($){ 
    $.fn.mysprite = function(options){ 
    //merge the provided options with defaults 
    var o = $.extend($.fn.mysprite.defaults, options||{}); 

    // this is the main body, here we iterate over the set 
    // returned by the selector applying the new functionality 

    this.each(function(){ 
     switch(typeof o.target){ 
     case 'object': 
     case 'string': 
      var target = $(o.target); 
      break; 
     case null: 
      var target = $(this); 
      break; 
     default: 
      // no target specified! 
      return this; 
     } 

     //simplify your previous code with the hover method 

     $(this).hover(
     function(){ 
      target.css('backgroundPosition', o.offsetIn); 
     }, 
     function(){ 
      target.css('backgroundPosition', o.offsetOut); 
     }); 
    }); 

    return this; 
    }; 

    // setsup class defaults 
    $.fn.mysprite.defaults = { 
    offsetIn: '0 0', 
    offsetOut: '0 0', 
    target: null 
    }; 
})(jQuery); 

//invoke with 

$('#dialpad1').mysprite({offsetIn: '0 100', offsetOut: '0 0', target: '#dialpad'}); 
+1

Beau travail, un peu exagéré, mais sympa. Vous pourriez vouloir corriger la faute de frappe dans votre première ligne cependant. –

+0

Eh bien, je suppose que le 'switch' était un peu étranger ... Merci pour la tête sur la faute de frappe - corrigé. – prodigitalson

1

Voici une variation en utilisant des fermetures/générateurs de fonctions pour les callbacks:

function setOffset(offset) { 
    return (function() { $('#dialpad').css('backgroundPosition', offset); }); 
}  
$('#dial1,#dial2').each(function(i) { 
    $(this).hover(setOffset('0 -' + (120 * (i+1)) + 'px'), setOffset('0 0')); 
}); 
+0

+1 - J'aime l'approche de la fonction de retour, mais souvenez-vous que vous devrez faire 'i + 1' dans' .each() 'car c'est une indexation à base zéro. : o) – user113716

+0

Doh! Bon appel - mis à jour. – jmar777

Questions connexes