views:

99

answers:

4

Posting as a jquery newbie. I am sure there must be a way to condense the code below in a DRY fashion. Essentially this is just a show/hide that is applied to multiple elements on a page, all using the same template and naming conventions:

$("#homelink1").hover(
    function() { $("#poptext1").show(); },
    function() { $("#poptext1").hide(); }
);

$("#homelink2").hover(
    function() { $("#poptext2").show(); },
    function() { $("#poptext2").hide(); }
);
...

I'm stuck on how to convert this to a function with passed parameters, so that I could just pass the integer (1 or 2) and have the function evaluate the rest, e.g.

$("#homelink" + param).hover

+5  A: 

How about this:

function setHover( param ){
   $("#homelink" + param).hover(
    function() { $("#poptext" + param).show(); },
    function() { $("#poptext" + param).hide(); }
  );
}
Justin Ethier
or param as an array? eh? eh?
Dan Heberden
I think @Dan is pretty much right. The way it is, you'll be repeating yourself (BRY?) with separate calls to `setHover(1)` `setHover(2)` etc.. Assuming that the numbering is consistent, you wouldn't really even need an array. Just a number representing the total number of element pairs.
patrick dw
Or you could just use a `for` loop :)
Justin Ethier
+2  A: 

Are the #poptext elements children of their respective #homelink? If so, you could create a "homelink" class and a "poptext" class and then do something like the following:

$(".homelink .poptext").hover(
    function() { $(this).show(); },
    function() { $(this).hide(); }
});

As a side note, most functions in jQuery work just as well on collections of objects as they do on a single one. In this case, even though $(".homelink .poptext") is returning a collection of objects, each one is individually associated with a mouseover and mouseout handler by hover().

Faisal
I actually already had some similar classes in the code, so this ended up working great. The .poptext elements were siblings of .homelabel elements, so the code that worked for me is:$("div.homelabel").hover(function() { $(this).siblings(".poptext").show(); },function() { $(this).siblings(".poptext").hide(); });
JayZeeNYC
Great! Also, kind of a "duh" moment for me here, but I forgot that you wanted the hover() event associated with the homelink and not the poptexts, in which case my code doesn't work. Good on you for figuring it out in the end anyway. :)
Faisal
+2  A: 

I'd probably try something like the following:

$('.homelink').bind('hover', function(){
    $('.poptext', this).toggleClass('hide');
});

# and some CSS

.hide {
    display: none
}

Bind the hover event to a generic classname, rather than trying to figure out how to hackishly bind it to #homelink{somenumber} and #poptext{somenumber}. Keep your ids in place if you must (for styling hooks for example), but simplify things and use classes.

Jason Leveille
I agree -- it seems like a case of "coincidental coupling", where two things are expected to have a relationship just because they share a naming convention. Classes are definitely the way to go here.
Faisal
+1 I don't know the HTML structure, but am assuming that `.poptext` class is somehow structurally related to `.homelink`. If so, this makes adding new stuff extremely easy - just change the HTML, JavaScript remains intact.
Anurag
Yeah, this is definitely a more flexible solution. I ended up going with Faisal's solution because it required the least refactoring of my existing code, but I like this approach.
JayZeeNYC
+2  A: 

You could use a regexp to get the number from the homelink that was hovered, then toggle the associated poptext.

Try it out: http://jsfiddle.net/xFR3s/

$("#homelink1,#homelink2").hover( function() { 
    $("#poptext" + this.id.match(/\d+$/)[0]).toggle(); 
});​

You could make it shorter with a "starts with" selector for the homelink elements. Less efficient, but it only runs once on DOM load, so perhaps it's alright.

Try it out: http://jsfiddle.net/xFR3s/1/

$("[id^=homelink]").hover( function() { 
    $("#poptext" + this.id.match(/\d+$/)[0]).toggle(); 
});​

EDIT: If you don't want it interpreted on the fly, I guess I'd do something like this:

Try it out: http://jsfiddle.net/xFR3s/2/

$("[id^=homelink]").each(function() {
    var num = this.id.match(/\d+$/)[0];
    $(this).hover( function() { 
        $("#poptext" + num).toggle(); 
    });​
});

or this:

Try it out: http://jsfiddle.net/xFR3s/3/

$("[id^=homelink]").each( function() {
    $(this).hover( setUpHover(this.id.match(/\d+$/)[0]) );
});

function setUpHover(num) {
    return function() {
        $("#poptext" + num).toggle(); 
    };
}​
patrick dw