Keefer Keefer - 5 months ago 16
jQuery Question

Refactoring jQuery With a Selector and index

Just to get it working, I have an FAQ page with jQuery that hides all divs classed with

.faqSection
, as well as a unique id --
#faqSection1
,
#faqSection2
, etc. . I then go through with the Waypoint plugin that detects when the offset of a given div is at 80% of viewport.

Before refactoring, the code looks like this:

jQuery('.faqSection').css('opacity', 0);
jQuery('#faqSection2').waypoint(function() {
jQuery('#faqSection2').delay(800).queue('fx', function() { jQuery(this).addClass('animated fadeInDown'); });
}, { offset: '80%' });

jQuery('#faqSection3').waypoint(function() {
jQuery('#faqSection3').delay(800).queue('fx', function() { jQuery(this).addClass('animated fadeInDown'); });
}, { offset: '80%' });

jQuery('#faqSection4').waypoint(function() {
jQuery('#faqSection4').delay(800).queue('fx', function() { jQuery(this).addClass('animated fadeInDown'); });
}, { offset: '80%' });

jQuery('#faqSection5').waypoint(function() {
jQuery('#faqSection5').delay(800).queue('fx', function() { jQuery(this).addClass('animated fadeInDown'); });
}, { offset: '80%' });

jQuery('#faqSection6').waypoint(function() {
jQuery('#faqSection6').delay(800).queue('fx', function() { jQuery(this).addClass('animated fadeInDown'); });
}, { offset: '80%' });


As you can see, it's just the number on the end that changes. I wanted to refactor for that very reason, plus want to accommodate a different number of divs.

So I tried this:

jQuery('.faqSection').css('opacity', 0);
for(var index = 0;
index < $('.faqSection').length; index++) {
jQuery('#faqSection' + index).waypoint(function() {
jQuery('#faqSection' + index).delay(800).queue('fx', function() { jQuery(this).addClass('animated fadeInDown'); });
}, { offset: '80%' });
}


Is it not possible to do a selector plus index, or do I have something else incorrect in my syntax and/or thinking?

Answer

Just a guess, but I think the issue may be that you're failing to capture the index variable properly. (In other words, the code inside the function always sees the latest value of index instead of the one at the time you set it up.)

Give this a try instead (also factoring in @Neverever's point that your index probably starts and ends at the wrong number):

jQuery('.faqSection').css('opacity', 0);
for(var index = 2;
    index <= $('.faqSection').length; index++) {
    (function (index) { jQuery('#faqSection' + index).waypoint(function() {
        jQuery('#faqSection' + index).delay(800).queue('fx', function() { jQuery(this).addClass('animated fadeInDown'); });
    }, { offset: '80%' }); })(index);
}

EDIT

Even better:

jQuery('.faqSection').css('opacity', 0);

// slice(1) skips the first element
jQuery('.faqSection').slice(1).each(function () {
    jQuery(this).waypoint(function () {
        jQuery(this).delay(800).queue('fx', function () {
            jQuery(this).addClass('animated fadeInDown');
        });
    });
});

Or, assuming waypoint works this way (I think most jQuery plugins do):

jQuery('.faqSection').css('opacity', 0);

// slice(1) skips the first element
jQuery('.faqSection').slice(1).waypoint(function () {
    jQuery(this).delay(800).queue('fx', function () {
        jQuery(this).addClass('animated fadeInDown');
    });
});
Comments