jQuery .click command order - javascript

This is a very simple question/problem, and I can easily work around it, but since I'm learning javascript I was very eager to know WHY exactly this particular problem is happening.
$("#go").click(function() {
$("p").append(array[x] + " ")
functionlist[array[x]]()
x++
})​
This does not work as I expect it to. I want it to write the current content of array, perform a simple animation that is associated with a certain function name, and then increment x. Everything works, except it doesn't increment x.
If I do this:
$("#go").click(function() {
$("p").append(array[x] + " ")
//functionlist[array[x]]()
x++
})​
x is incremented successfully.
So my question is, why does this happen?
Here is a link to a jsfiddle that I am using: http://jsfiddle.net/mxy6N/3/

Well, if you check your script console (F12 is most browsers), you'll see that functionlist[array[x]]() throws an error something like:
Object has no method "smooch"
This is because array[x] is equal to "smooch", and functionlist["smooch"] is undefined, so it errors out before it makes it to your x++.
Other things going on in this code:
x is declared inside of your function, therefore it will always be 0 at the time it is used.
even if it were declared outside of your function, as you increment it, it will run out of items to look at in your array. You'll need to use a modulo operator or two here.
You're not referencing an .js files that have a definition for $.fn.transition, so your transition calls will also error out.
flip and flop both have the same rotateY value, so once it "flips" it won't "flop"
Here is something that might do what you're looking to do: http://jsfiddle.net/g5mJd/3/
And the updated code:
var array = ["smooch", "jab", "flip"];
var move = "flip";
var x = 0;
var functionlist = {
flip: function() {
$("#block").transition({
perspective: '0px',
rotateY: '180deg'
}, 1000);
},
flop: function() {
$("#block").transition({
perspective: '0px',
rotateY: '0deg'
}, 100);
}
};
$("#go").click(function() {
var functionName = (x % 2 == 0) ? 'flip' : 'flop';
var fn = functionlist[functionName];
if($.isFunction(fn)) {
fn();
}
var say = array[x % array.length];
$('p').append(say + ' ');
x++;
})​;
EDIT: Updated with $.isFunction() check.

Related

jQuery run code after chunked $.each() is finished

With the below code:
$('#button').on('click', function () {
var longArray = searchArray; // assume this has 100 or more postalcodes init
var shortArrays = [], i, len;
for (i = 0, len = longArray.length; i < len; i += 100) {
shortArrays.push(longArray.slice(i, i + 100));
}
// Now we iterate over shortArrays which is an array of arrays where each array has 100 or fewer
// of the original postalcodes in it
for (i = 0, len = shortArrays.length; i < len; i++) {
// shortArrays[i] is an array of postalcodes of 100 or less
$.each(shortArrays[i], function(index, value){
setTimeout( function() {
// Each parent gets its own searchToggle class
$('.postcodes input[data-postcode*="' + value + '"]').parent().parent().addClass('searchToggle');
// Each parent also gets a data filter attribute for ordering the results
$('.postcodes input[data-postcode*="' + value + '"]').parent().parent().attr('data-filter' , index);
// We display the items in the search array
$('.postcodes input[data-postcode*="' + value + '"]').parent().parent().css('display', 'flex');
$('.postcodes .searchToggle .postcode input[data-postcode*="' + value + '"]').parent().css('display', 'flex');
}, 0 );
})
} // /for
alert('Finished message');
});
I try to show an alert message(for debugging) once the $.each() is finished. Since this each goes through an array that could be 1000s of postal codes long I broke it up in chunks of 100. This to prevent the dreaded browser is unresponsive. This is all working fine but the alert fires immediately on click.
I have tried several things already:
I tried by using a count: ABOVE THE EACH var count = 0; INSIDE THE EACH count++ if ( count == longArray.length ) { ALERT } But this also fired the alert immediately???
I tried it by using an interval but that became a mess almost instantly.
I tried a couple of other SO answers but all of them resulted in the alert to fire immediately.
When looking through the jQuery docs and previous codes that I have written it should just run the code after the each is finished but in this case it does not.
Any idea on why this is and how I can fix it.
PS: This alert could be other codes! Like sorting the results or something else.
PS2: I can change all the js/jQuery you see but I cannot change any of the HTML selectors.
PS3: Thank you for thinking about this issue and especially for commenting/answering!
I have solved it by adding another setTimeout.
So I replaced the alert (see Question) from
alert(Finished message);
To
setTimeout( function() {
// As an example I used alert in my question and here in this answer.
// This can be offcourse anything else. I use it for instance to sort the results.
alert(Finished message);
}, 0 );
This works for me, but it might not be the best way to deal with it. So I am still looking forward to what more experienced people think about the question or the answer.

Conditional statement is not recognizing variable values

I am making a simple reaction time game for a final project.
We are using javascript to power the functions in the game, most of my code is in working order, but I have an if conditional statement that's giving me trouble.
Here's the code
function fireTime() {
setTimeout(ShotsFired, time);
function ShotsFired() {
fire.style.visibility = "visible";
createdTime = Date.now();
console.log(createdTime);
EnemyTime = Math.floor((Math.random() * 1000) + 400);
setTimeout(EnemyShoot, EnemyTime)
function EnemyShoot() {
console.log(EnemyTime);
gameplay();
}
function gameplay() {
reactionTime = -(createdTime - clickedTime);
var EnemyTime;
console.log(reactionTime);
if (reactionTime < EnemyTime) {
alert("Wow you beat him! Congrats!");
fire.style.visibility = "hidden";
clickedTime = 0;
createdTime = 0;
reactionTime = 0;
scavnumber++;
BGnumber++;
DesertBG.src = "images/Desert" + BGnumber + ".png";
scav.src = "images/scav" + scavnumber + ".png";
fireTime();
} else {
EndScreen.style.visibility = "visible";
}
}
This is not the entire code, just the function that should progress the game to the next level.
For whatever reason, even though reactionTime is less than EnemyTime, the EndScreen becomes visible.
Anyone know what could cause this?
Use floating point for your enemy time maths, i.e. 400.0 , else you are getting 0/1 seconds and not using milliseconds, and it is useing Math integer. Specifically cast your enemyTime as a float number, for the moment, if you print it it's probably an integer. its a MAJOR js coding detail that you will cost you hours of bughunting in the future if you think that 101/50 = 2.05, it isn't it equals 2, so divide by 50.0 and same with all second/ms tasks.
Use EnemyTime as a global variable for all scripts, at the moment, the code things you have a different function called EnemyTime in all scripts, the latter one has no value.
Use print to see when your else conditions work, specify a print in both an print the enemyTime value.
That's how you are supposed to resolve the issue, by printing the variables that are confusing.

Recursive function to print numbers in JavaScript

I'm trying to make a recursive function to print 1 to 10 in JavaScript, my current code is:
function rec10(x)
{
if (x < 10)
{
$('#text').val(x+1);
x = x+1;
rec10(x);
}
}
The problem is, everytime I activate this function, the text box only shows "10" directly, i want the code to move from 0 to 1, to 2... until 10. Showing each one of them in the text box.
I tried to use setInterval and setTimeout but I didn't figure it out how to work with that. Thank you very much
instead of:
rec10(x);
call
setTimeout(function() { rec10(x); }, 1000);
With setInterval you can using code below:
function rec10(x) {
var interval = setInterval(function() {
if (x >= 10) clearInterval(interval);
$('#text').val(x++);
}, 1000);
}
JavaScript is single threaded, which means while your code runs, the changes you make to the DOM won't be seen on the browser until your code finish.
You need to give control to the browser for couple of seconds, it can be done with setTimeout:
function rec10(x){
if (x < 10){
$('#text').val(++x);
setTimeout(function(){
rec10(x);
},20);
}
}
Did you resort to setInterval/setTimeout only because you can't make a working recursive function?
If that's the case, how about this recursive function below without using setInterval/setTimeout:
function rec10(x) {
if (x <= 10) {
if (x <= 0) x = 1;
//append?
$('#text').val(x);
rec10(x + 1);
}
}
rec10(1);
But the problem with the code above is it will happen so fast you won't notice the printing of numbers 1 up to 9.
If you want to see the those numbers then I suggest you just append the value to your placeholder $('#text').
But if you really wanna see the numbers being printed and then being replaced by the next number, then you can refer to the answers posted by other users which uses setInterval/setTimeout.

How do I add up a number to a properties in my object?

I have an object like this:
var statistics = {
won: 0,
tie: 0,
lost: 0
};
I have a function that adds 1 to won:
var plus1 = function() {
return statistics.won++;
}
I call that function within an if/else statement like this:
plus1();
But it doesn't work. Does anyone have an idea?
It's probably that x++ returns x instead of x+1.
You are looking for
var plus1 = function() {
return ++statistics.won;
}
Looking at your code I don't really see any reason why you would return your result.
I would rewrite the function to simply be
function plus1() {
statistics.won++;
}
When it comes to having it update, I can't see any were in your code where you actually update the html. After you've run plus1(). If I run console.log(statistics) in my Console I can see that statistic.won goes up whenever I win.
As already mentioned in the comment above, if you run wins() after you've run plus1() it will all work.
This is due to to way pre/post incrementation works in JavaScript:
var one = 1;
var two = 1;
// increment `one` FIRST and THEN assign it to `three`.
var three = ++one;
// assign `two` to `four`, THEN increment it
var four = two++;
So in your code, you're assigning the value of statistics.won to the return value first and then incrementing it. You can see the difference in how they work here.
So, as I mentioned in the comments, return ++statistics.won; is the solution you need.

JavaScript variables - new var altering original value

It's been a while since I've touched JavaScript, but something has got me flummoxed, simple I just know I should know it, but it's causing me a massive headache for the past hour!
Scenario;
Mop = {
els : [],
pool : [],
generate : function(){
for (var i=0; i<Mop.els.length; i++){
Mop.pool.push(i)
}
},
oneAtime : {
p : Mop.pool,
runit : function(){
timerID = window.setTimeout(function(){
Mop.show()
});
}
},
show : function(){
var p = Mop.oneAtime.p;
var r = Math.floor(p.length * Math.random());
p.splice(r,1);
},
init : function(){
Mop.els = $(".cells");
Mop.generate();
Mop.oneAtime();
}
}
Mop.init()
A long winded way to say it's a problem with variable assigning. But I thought I'd show the context.
In short, invoking Mop.show() affects both the arrays Mop.pool, and Mop.oneAtime.p, even though the latter was assigned Mop.pool value, and Mop.pool is not touched again. Mop.pool must remain un-altered.
I can hear someone laughing at how easy this must be - but I just cannot work out why both arrays are affected by the splice() method! Scope, closure, something like that I bet, I've tried all I can think of...

Categories

Resources