0

Alright, here's a puzzler. I've got a jQuery function to display a PHP generated list of announcements for a website via .fadeIn/.fadeOut; the very first thing loaded on the page is jQuery 1.11.xx from a CDN. I'm running Bootstrap, fullCalendar, SmartMenus, etc., and jQuery is most definitely loading.

Except within the setInterval() to update the announcement. This is rough-code, some functionality isn't present, but to my mind it should be doing an animation.

var announcementArray = [];
var announcementSource = "../announcements.php";
var totalAnnc;

$.getJSON(announcementSource, function(data) {
    announcementArray = data.concat();
    totalAnnc = announcementArray.length;
});

var count = 0;

var fadeAnnc = function() {

    $('#announcementArea').text(announcementArray[count].announceText);
    $('#announcementArea').fadeIn('slow',function() {
        $('#announcementArea').css('display','block');
    }).delay(2000).fadeOut('slow',function() {
        count = (count + 1) % totalAnnc;
    });
};

setInterval(function() {
    fadeAnnc();
}, 3000);   

Instead, when I run the page, I get a "function not defined" error for any jQuery function that's called within the setInterval(). If I call using document.getElementById('announcementArea').innerHTML = etc., it works, but doing the fade in/out via DOM manipulation seems to be more work than is needed when jQuery is available and working everywhere else on the page.

I've tried a few scope adjustments and have been working on what should be simple code for the last 5 hours. So, where's my glaring error? ;)

7
  • If I'm not mistaken, the fadeOut() function is inside the fadeIn() one. Is that supposed to be like that? Commented Apr 13, 2015 at 20:29
  • @yak613 it is not - the power of bad identation, haha. Commented Apr 13, 2015 at 20:32
  • Are you accidentally assigning another value to $ inside the setInterval call? Commented Apr 13, 2015 at 20:33
  • also can you provide a fiddle? Commented Apr 13, 2015 at 20:35
  • @yak613: No, they're chained with a delay in between. It is the power of bad indentation. ;) Commented Apr 13, 2015 at 20:38

3 Answers 3

2

Not sure what kind of scope issue you are having (looks like it's the result of unposted code, as everything in your question looks OK), but if you want a fairly foolproof way of passing along the jQuery object, you could always pass it as a parameter:

var fadeAnnc = function($) {

    $('#announcementArea').text(announcementArray[count].announceText);
    $('#announcementArea').fadeIn('slow',function() {
        $('#announcementArea').css('display','block');
        }).delay(2000).fadeOut('slow',function() {
        count = (count + 1) % totalAnnc;
    });
};

setInterval(function() {
    fadeAnnc($);
}, 3000);   

Based on your updated answer, here's another possible solution:

(function($){

    var announcementArray = [];
    var announcementSource = "../announcements.php";
    var announcementSpace = "#announcementArea";


    $.getJSON(announcementSource, function(data) {
        announcementArray = data.concat();
        if (announcementArray.length === 0) {
            $('#anncRow').css('display','none');
        }
    });

    var count = 0;
    var masterCount = 0;
    var totalAnnc =  announcementArray.length;
    var timer;

    var fadeAnnc = function() {
        if (announcementArray.length > 0) {
            $(announcementSpace).html(announcementArray[count].announceText);
            $(announcementSpace).fadeIn(750, function() {
                $(announcementSpace).css('display','block');
            }).delay(4500).fadeOut(750, function() {
                $(announcementSpace).css('display','hidden');
            });
        }
        count += 1;
        if ((count % announcementArray.length) == 0) {count = 0}
    };

    setInterval(fadeAnnc, 6000);    

}(jQuery));

$ is defined as a function parameter and thus overrides the globally scoped $ within the function body, protecting it's definition for your code. This is actually exactly what jQuery recommends when creating an extension.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! I'll add that to my jQuery notes for development.
0

My previous answer - scratch that:

The issue was more interesting - somewhere between the SmartMenu plugin and the LibraryThing book display widget there is a jQuery conflict created. This explains why - depending on the load order - different parts would break, but always the setInterval(), which always loaded after SmartMenu and LibraryThing.

So, my somewhat messy solution is to release the $ at the beginning of the script and reclaim it at the end so on other pages jQuery has access to it, like so:

jq = jQuery.noConflict();

var announcementArray = [];
var announcementSource = "../announcements.php";
var announcementSpace = "#announcementArea";


jq.getJSON(announcementSource, function(data) {
    announcementArray = data.concat();
    if (announcementArray.length === 0) {
        jq('#anncRow').css('display','none');
    }
});

var count = 0;
var masterCount = 0;
var totalAnnc =  announcementArray.length;
var timer;

var fadeAnnc = function() {
    if (announcementArray.length > 0) {
        jq(announcementSpace).html(announcementArray[count].announceText);
        jq(announcementSpace).fadeIn(750, function() {
            jq(announcementSpace).css('display','block');
        }).delay(4500).fadeOut(750, function() {
            jq(announcementSpace).css('display','hidden');
        });
    }
    count += 1;
    if ((count % announcementArray.length) == 0) {count = 0}
};

setInterval(fadeAnnc, 6000);    

$ = jQuery.noConflict();

Comments

0

Use closures (which is considered good practice anyways):

(function($) {

    var your_function = function() {
        $(...);
    };

    setTimeout(function() {
        your_function();
    });

}(jQuery));

Using closures creates a sort of 'sandbox' for your code, so you don't have to worry about overwriting any variables declared in a parent scope (such as the dollar-sign $ used by jQuery).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.