Div won't show unless I step through the code

So, I have a div I want to .append to when a button is clicked (basically tell the user something is working in the background). But when I run the function off the click event, the div doesn’t show but for a split second after all the processing is done.

If, however, I create a breakpoint on that function call to show the div (doesn’t have to be a function call really), then it shows immediately and remains until the background work is complete.

So, I get the feeling that the background stuff starts to fast, and locks up my UI while it’s working.

Is there something I can do to solve this?

Hard to help you without seeing your code, but aren’t you by any chance using jQuery to show this element? If yes, then that may be the source of your problem.

It is with jQuery, but i’m more than open to using straight javascript.

I didn’t put code only because it’s a big function that calls several others from a button click.

I basically collect up the possible questions you created, along with any that anyone else created that they said is ‘public’. Then I select a random set of those, then have to check that they are not repeated, then if they are, try again untnil I get a set that meet all criteria and don’t have a repeated question, then once that happens, I take the user to the next screen.

So it’s during all that, where I’d like a spinner, but right now, just trying to show text.

I’m pasting, only so you can see the amount of stuff I’m doing here. Forgive the console.logging, and any horrid ways of doing something that you know how to do more elegantly (open to suggestions by the way). I’m still a relatively new developer, and am learning all the time, but have a loooooonnnng way to go.

Thanks for any help,

Template.createAGame.events({
    'click #saveCreateGame' (event) {
        event.preventDefault();
        showSpinner();

    var gameCode = "";
    // need to generate a unique game number
    var randomString = function(stringLength) {

        var possible = "ABCDE0FGHIJ1KLMNO2PQRST3UVWXY4Zabcd5efghi6jklmn7opqrs8tuvwx9yz0123456789";
        for(var i = 0; i < stringLength; i++) {
            gameCode += possible.charAt(Math.floor(Math.random() * possible.length));
        }
        console.log('Game code is: ' + gameCode);
    }
    // call the function above, and pass the length you want for the random string code
    randomString(6);

    // check that certain fields are filled out
    qCat = [];
    var gameName = $("#gameName").val();
    var gameType = $("#gameType").val();
    var numOfQs = parseInt($("#numberOfQuestions").val());
    var qType = $("#questionType").val();
    var qDifficulty = $("#questionDifficulty").val();
    var qCat = $("#questionCategories").val();

    Session.set("gameCode", gameCode);
    Session.set("gameName", gameName);
    Session.set("qCat", qCat);
    Session.set("gameType", gameType);
    Session.set("numOfQs", numOfQs);
    Session.set("qType", qType);
    Session.set("qDifficulty", qDifficulty);

    // form field validation
    if (gameType == '' || gameType == null) {
        showSnackbar("You must choose a Game Type.", "red");
        document.getElementById('gameType').style.borderColor = "red";
    } else if (gameName == '' || gameName == null) {
        showSnackbar("You need a Game Name.", "red");
        document.getElementbyId('gameName').style.borderColor = "red";
    } else {
        if (qCat == '' || qCat == null) {
            showSnackbar("You must choose at least one Question Category.", "red");
            document.getElementById('questionCategories').style.borderColor = "red";
        } else {
            console.log("call find questions function.");
            findQuestionsMatchingCriteria();
        }
    }
},
'click #cancelCreateGame' (event) {
    event.preventDefault();
    // document.getElementById("createGameForm").reset();
    var qCat = $("#questionCategories").val();
    console.log("Category is: " + qCat);
    var questions = Questions.find({ category: qCat }).fetch();
    console.log(questions);

},
});

function showSpinner() {
    $("#spinnerSpace").append("Loading Questions - Please Wait ....");
    return;
}

function writeGameToDB(gameCode, gameName, gameType, numOfQs, qType, qDifficulty, qCat) {
    var gameCode = Session.get("gameCode");
    var gameName = Session.get("gameName");
    var gameType = Session.get("gameType");
    var numOfQs = Session.get("numOfQs");
    var qType = Session.get("qType");
    var qDifficulty = Session.get("qDifficulty");
    var qCat = Session.get("qCat");
    var uniqueQuestions = Session.get("uniqueQuestions");
    var thisGameQuestion = [];

    for (i = 0; i<uniqueQuestions.length; i++) {
        questionNo = parseInt(uniqueQuestions[i]);
        var eachQuestion = Questions.find({ mySeqNo: questionNo }).fetch();
        thisGameQuestion.push(eachQuestion[0]._id);
        Session.set("thisGameQuestion", thisGameQuestion);
    }

    $("#gameCodeSpace").append("Game Code is: " + gameCode);
    Session.set("gameCode", gameCode);
    Session.set("gameName", gameName);
Meteor.call('newGame.insert', gameType, gameName, numOfQs, qType, qDifficulty, qCat, gameCode, thisGameQuestion, function(err, result) {
    if (err) {
        showSnackbar("An error occurred saving the Game.", "red");
        console.log("Save Error: " + err);
    } else {
        showSnackbar("Game Created Successfully!", "green");
        Meteor.call('addGameQuestions', thisGameQuestion, gameCode, function(err, result) {
            if (err) {
                showSnackbar("Error preparing questions for players.", "red");
            } else {
                FlowRouter.go('/gameMaster');
            }
        });
    }
});
}

function findQuestionsMatchingCriteria() {
    var qType = Session.get("qType");
    console.log("Type = " + qType)
    var qDifficulty = Session.get("qDifficulty");
    console.log("Diff = " + qDifficulty);
    var qCat = Session.get("qCat");
    console.log("Category = " + qCat);

console.log("Finding Questions to Match Criteria.")

var theSeqNo = [];
if (qType == 'mixed' && qDifficulty == 'mixed') {
    console.log("Find Questions mixed set diff and type.");
    var questions = Questions.find({ category: { $in: qCat }}).fetch();
    console.log(questions);
    for (i = 0; i < questions.length; i++) {
        theSeqNo[i] = questions[i].mySeqNo;
    }
} else if (qType == 'mixed' && qDifficulty != 'mixed') {
    console.log("Find Questions mixed set type.");
    var questions = Questions.find({ category: { $in: qCat }, difficulty: qDifficulty }).fetch();
    console.log(questions);
    for (i = 0; i < questions.length; i++) {
        theSeqNo[i] = questions[i].mySeqNo;
    }
} else if (qDifficulty == 'mixed' && qType != 'mixed') {
    console.log("Find Questions mixed set diff.");
    var questions = Questions.find({ type: qType, category: { $in: qCat }}).fetch();
    console.log(questions);
    for (i = 0; i < questions.length; i++) {
        theSeqNo[i] = questions[i].mySeqNo;
    }
} else {
    console.log("Find Questions no mixed sets.");
    var questions = Questions.find({ type: qType, category: { $in: qCat }, difficulty: qDifficulty }).fetch();
    console.log(questions);
    for (i = 0; i < questions.length; i++) {
        theSeqNo[i] = questions[i].mySeqNo;
    }
}

console.log("Questions are: " + theSeqNo);
Session.set("theSeqNo", theSeqNo);
if (theSeqNo != []) {
    console.log('would call the next function.');
    lineUpQuestions();
} else {
    console.log("seq no did not get any values.");

    // TODO: Add a message that no questions were open.
}

}

function lineUpQuestions() {
    // first get the highest question number in the system at the time.
    var theSeqNo = Session.get("theSeqNo");
    var numOfQs = parseInt(Session.get("numOfQs"));
    var count = theSeqNo.length;
    console.log("Number of questions available is: " + count);
    var uniqueQuestions = [];
    for (i=0; i < numOfQs; i++) {
        randPick = Math.floor(Math.random() * count);
        if (uniqueQuestions.indexOf(theSeqNo[randPick]) == -1) {
            uniqueQuestions.push(theSeqNo[randPick]);
            console.log("Unique Question set is " + uniqueQuestions);
            Session.set("uniqueQuestions", uniqueQuestions);
            var questionSet = 'good';
        } else {
            console.log("Unique Question set not found: Trying Again.");
            var questionSet = 'bad';
            break;
        }
    }

if (questionSet == 'good') {
    writeGameToDB();
} else if (questionSet == 'bad') {
    findQuestionsMatchingCriteria();
}
}

I think it may have to do with Meteor rendering your template(s) and when you append your spinner it will be destroyed along with other content of your template when internal state changes. Have you tried to append the spinner to a DOM element not part of any individual template, like BODY?

I haven’t, but I can. I was concerned the element would not show because of the routing with FlowRouter. Worth a try though. I thought about trying a subscription ready {{#if }} in the DOM, but figured by the time the user gets to the button click, the template subscriptions should be done, and I don’t want to take them tot he next ‘page’ until this step is successfully completed.

Just an update, it’s definitely that Im locking up the UI with what I’m doing in JS. I’m going to re-think my approach and see if I can’t make it more elegant somehow, and alleviate some of these issues. I can get the spinner if I put it on it’s own template, then route to that template and start the background code from there, but I overflow the stack a lot of times, so I definitely need to rethink my approach.