Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 6 of 6
  1. #1
    Regular Coder d'Anconia's Avatar
    Join Date
    Jan 2010
    Location
    Tempe, AZ
    Posts
    149
    Thanks
    16
    Thanked 6 Times in 6 Posts

    Issue Looping and Setting Variables (Values vs. References?)

    I am simply trying to loop through some elements whose ID's are "0_score", "1_score", etc and attach events to each. I am finding, instead, that Javascript seems to assign a reference to the value instead of the actual numerical value and this is causing every instance of newPredictionRating to use "11" as the value for 'i'. I believe this is different from how PHP handles variables. The value is 11 because that's what 'i' is equal to after the end of the loop.

    If I want each sequential element to call newPredictionRating with the first passed variable being equal to "i" *at that moment in the loop*, how would I do that?

    Code:
    window.onload = function() {
        'use strict';
        
        var scores = [];
        scores['n/a'] = U.$('na_score');
        U.addEvent(scores['n/a'], 'click', function() { newPredictionRating ('n/a', userId, predId)});    
        var i = null;
        for (i=0; i <= 10; i++) {
            scores[i] = U.$(i + '_score');
            U.addEvent(scores[i], 'click', function() { newPredictionRating (i, userId, predId)});
        }
    }
    Any help is appreciated. Let me know if you need any further details.
    Datagonia Web (My Portfolio)

    Powerful ideas for all lovers of personal and political freedom:
    Freedomain Radio
    Free Talk Live

  • #2
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,020
    Thanks
    75
    Thanked 4,323 Times in 4,289 Posts
    Just for starters, it is technically illegal for an ID to start with a digit.

    If at all possible, you should use score_1 (etc.) in place of 1_score.

    But your real problem here is that you need a closure to use your variable i as you are doing. We could create a closure, but I see an easier way.

    I think this works (assumes there are no other onclick handlers in use on those elements):
    Code:
    window.onload = function() {
        'use strict';
        
        document.getElementById("na_score").onclick = 
            function() { newPredictionRating ('n/a', userId, predId)});
    
        for ( var i = 0; i <= 10; ++i )
        {
            document.getElementById( i + "_score").onclick = callRating;
        }
        function callRating( )
        {
            var which = this.id.split("_")[0];
            newPredictionRating ( which, userId, predId);    
        }
    }
    If you follow my advice and use score_1, et al., then just change
    Code:
            var which = this.id.split("_")[0];
    to
    Code:
            var which = this.id.split("_")[1];
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • Users who have thanked Old Pedant for this post:

    d'Anconia (06-20-2013)

  • #3
    Regular Coder d'Anconia's Avatar
    Join Date
    Jan 2010
    Location
    Tempe, AZ
    Posts
    149
    Thanks
    16
    Thanked 6 Times in 6 Posts
    You and Fou Lu always seem to be there when I need a good and expedient answer. Thanks a ton Old Pedant!

    Tried it and it worked. One additional point though is that the variable "which", when passed to the function, will need to specify which element of the array you are accessing. I did "score_x" where "x" is the number so I used which[1] (meaning the second element in the array after the ID is split). Of course this will depend on the syntax of the ID itself (I'm just adding this for other n00bs that may come across it).

    I'll have to take a second look into the subject of closure. I remember reading about it in the book I learned Javascript from but never encountered it again until now. Again, thanks a ton Old Pedant.
    Datagonia Web (My Portfolio)

    Powerful ideas for all lovers of personal and political freedom:
    Freedomain Radio
    Free Talk Live

  • #4
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,020
    Thanks
    75
    Thanked 4,323 Times in 4,289 Posts
    But your scores[] array is a *LOCAL* variable, so it is *ONLY* visible inside that function invoked by window.onload (which is likely not a good way to invoke it, by the by, but that's another topic).

    So what point is there in even having the scores[] array???
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #5
    Regular Coder d'Anconia's Avatar
    Join Date
    Jan 2010
    Location
    Tempe, AZ
    Posts
    149
    Thanks
    16
    Thanked 6 Times in 6 Posts
    When my initial attempt did not work I was trying to see if an array would behave differently. I'm not as versed with Javascript so I am not always as aware of things like scope as someone more experienced, like yourself, might be.
    Datagonia Web (My Portfolio)

    Powerful ideas for all lovers of personal and political freedom:
    Freedomain Radio
    Free Talk Live

  • #6
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,020
    Thanks
    75
    Thanked 4,323 Times in 4,289 Posts
    If you really need that array for other reasons, in other functions, then you must declare it *OUTSIDE* the function shown here.

    And if you do that, then yes, we could add the elements to it the same way you did before, quite easily:
    Code:
    var scores = [ ]; // global variable now!
    
    window.onload = function() {
        'use strict';
        
        var s = document.getElementById("na_score");
        scores["n/a"] = s;
        s.onclick = 
            function() { newPredictionRating ('n/a', userId, predId)});
    
        for ( var i = 0; i <= 10; ++i )
        {
            s = document.getElementById( i + "_score");
            scores[i] = s;
            s.onclick = callRating;
        }
        function callRating( )
        {
            var which = this.id.split("_")[1];
            newPredictionRating ( which, userId, predId);    
        }
    }
    CAUTION: That array is now a mixed array (which it was when you created it, previously).

    You would need to retrieve the "n/a" entry via scores["n/a"] separately from retrieving the other entries via their index, as in scores[7]

    If you wanted to iterate through all the entries is in the array, you might be better off just using the ID of each element as the key to the object.

    That is, perhaps:
    Code:
    var scores = [ ]; // global variable now!
    
    window.onload = function() {
        'use strict';
        
        var s = document.getElementById("na_score");
        scores[s.id] = s;
        s.onclick = 
            function() { newPredictionRating ('n/a', userId, predId)});
    
        for ( var i = 0; i <= 10; ++i )
        {
            s = document.getElementById( i + "_score");
            scores[s.id] = s;
            s.onclick = callRating;
        }
        function callRating( )
        {
            var which = this.id.split("_")[1];
            newPredictionRating ( which, userId, predId);    
        }
    }
    And then you could iterate through all of them via something like:
    Code:
    for ( var name in scores )
    {
        alert( "scores[" + name + "] is " + scores[name] );
    }
    Last edited by Old Pedant; 06-20-2013 at 02:05 AM.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.


  •  

    Tags for this Thread

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •