views:

58

answers:

2

My last question asked for running once without the use of booleans. I decided I needed booleans but not a lot of variables since that would be messy.

So let's say I have this:

var counter = 0;

$(function() {
    $('#typing').keyup(function() {
        switch($(this).val().toLowerCase()) {
          case 'test':
            // DO THIS EVERYTIME TEST CASE IS CALLED
            $('#test').fadeOut("fast", function() {
                $(this).html("<span class='green'>That's correct!</span>").fadeIn("fast");
            });

            // DO THIS ONCE AND ONLY ONCE
            count++;
        }
    });
});

Basically, it's part of 'percent complete' application where a user tries to type all cases I make available. So if a user types test twice... on the first run of case test it would add 1 to the counter but on the SECOND run of case test it would NOT add to counter.

I don't want to make it to add a lot of booleans for each case because that would be messy.

Get it? :)

My idea is to make an array and per each case that I add it would add alltogther. So array[0] would be case test. Then I on my first try I would set array[0] to 1.. then create a FOR-LOOP on each case array to add up for total. This is a good idea?

The only problem is I don't know how to make a per case array.

+2  A: 

A simple way would be to use an object literal as the counter variable, and once a case is hit assign the value true:

var counter = {};
...
case 'test' : counter[$(this).val()] = true;

Alternatively, check if the 'case' has already been stored in a plain old boring array:

var counter = [];
...
case 'test' :
if(!$.inArray($(this).val(), counter)) {
    counter.push($(this).val());
}
karim79
Oh, I see. Then how would I add up all of the cases together for each one that is true?
Dan
@Dan - I thought you said you don't actually want to *count* occurrences, but rather just simply acknowledge them? Am I wrong?
karim79
Well for each case in the array that is true... I want them to add up to the total. That make sense?
Dan
@Dan - edited, hope it makes sense :)
karim79
OK so then how do I add up and get total?
Dan
@Dan - the above code does add up the totals (as far as I can tell).
karim79
I am getting NaN the first time. But can't I just make the counter INSIDE case test instead of making TWO case tests?
Dan
But the code you gave me adds to total everytime... so its not working for me :(
Dan
Weird.. if I change !== to == it works. But it says NaN the first time THEN it doesn't add... ummm weird. Which way do you do it?
Dan
I mean it ads 1 but then it doesn't add but I get NaN the first time.
Dan
@Dan - edited again. Try it now if you will, kind sir :)
karim79
It still keeps adding 1 everytime :(
Dan
Are you sure you don't need to add parens on the (? :) section? `(counter[$(this).val()] ? counter[$(this).val()]++ : counter[$(this).val()]) = 1;` That technique of `(p ? a : b) = c` was first shown in the Programming Perl book
SHiNKiROU
@Dan - this seems to work: http://jsfiddle.net/KQESf/ (it's a bit annoying with the alerts, but it should adequately demonstrate).
karim79
@SHiNKiROU - there is no need (though I *do* use them most of the time) as the first expression need only evaluate to a *boolean* :)
karim79
I want the counter to STOP at one for each case... I think you have it wrong.
Dan
@Dan - then my first solution was the way to go :)) Dang it, I've lost it in the edits....let me jog my memory!
karim79
Got it :) This did it: `if (counter[$(this).val()] == undefined) {`
Dan
Wow I have to add this to EVERY SINGELE case I make: http://www.dasdas.pastebin.com/EGFZTXT3
Dan
Stupid thing cuttign out on me. ANwyays... how do i make it so i only add it once?
Dan
@Dan - dude, you are killing me :) If you only want to know if something has 'happened' or not, then look to the solution above, which says 'if a word happens, then add it to the object and assign it `true`'.
karim79
I COULD create a function. But it will only work for the first one I do it for... :(
Dan
The first solution added 1 every time which was what I didn't want it to do.
Dan
I mean it WORKS but if I put it inside a function ... it will only work for the first one I use the function for.
Dan
Dan - my friend, I am lost. Like more lost than the guys from that stupid Lost show, and then some. Do you want to increment or just check if a value has just been typed in? Did I mention, I am really, really lost?
karim79
Both the increment of counter and checking if typed in already. If it HAS NOT been typed in before... add increment to counter... if it HAS ... then do not add... Sorry for confusion.
Dan
@Dan - first example above does exactly that. When it occurs, a key with that 'case' will get created and assigned 'true' so that you know it has happened. Subsequent occurrences will also get assigned 'true' so no incrementing is happening.
karim79
Oh ok. But in ` counter[$(this).val()] = true;` I do not see the counter being added up.
Dan
@Dan - you do not need to add 'one' to the counter if you need only 'one'. You just need to set a 'key' to `true`. Then you can check if it has been added with `if(counter.blahblah)`. Make sense?
karim79
Yeah it does but what do you mean by `if(counter.blahblah)`? If counter is true add to total count?
Dan
@Dan, the count will not increment. Once you have added a 'key' to it, it will stay as `{ theKey: true }` forever.
karim79
OK so then how do I get the total count for each case that is true?
Dan
A: 

Doing exactly what you asked:

var validKeys = ['test', 'testing', '1337'];
var checkedKeys = {};

function getCount() {
    var counter = 0;
    $.each(validKeys, function(index, value) { //jQuery.each, for neat array iteration
        if(checkedKeys[value])
            counter++;
    }); 
    return counter;
}

$(function() {
    $('#typing').keyup(function() {
        var val = $(this).val().toLowerCase();
        if(val == 'test') { //neater than a switch statement, often
            // DO THIS EVERYTIME TEST CASE IS CALLED
            $('#test').fadeOut("fast", function() {
                $(this).html("<span class='green'>That's correct!</span>").fadeIn("fast");
            });
        }
        checkedKeys[val] = true;
    });
});
Eric