0
for (var i in tokens) {
    var id = tokens[i].substring(0, tokens[i].indexOf('='));
    var name = tokens[i].substring(tokens[i].indexOf('=') + 1); 
    .                   
    .   
    .
    var button = document.createElement('button');
    button.id = id;
    $(button).addClass('friend-invite-button')
        .html('Invite')
        .click(function() {             
        $.ajax({ url: path + '/twitter/directmessage.php',
                     data: {'screen_name': name},
                     type: 'post',
                     success: function(output) { alert(output); }
                });
            }); 
}

The code above seems to attach the same value of variable 'name' to the click event. Every time i click on a button I get the same value in the alert, and that value is the last one i get by looping. Can you correct me please? my php file is below

<?php
session_start();
require_once('twitteroauth.php');
require_once('config.php');

$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET);
$request_token = $connection->getRequestToken(OAUTH_CALLBACK);

$_SESSION['oauth_token'] = $token = $request_token['oauth_token'];
$_SESSION['oauth_token_secret'] = $request_token['oauth_token_secret'];

switch ($connection->http_code) {
  case 200:
    $options = array("screen_name" => $_POST["screen_name"], "text" => "message");
    $status = $connection->post('direct_messages/new', $options);
    echo $_POST["screen_name"];
    break;
  default:
    echo 'Could not connect to Twitter. Refresh the page or try again later.';
}
4
  • tokens=1849157244=79papakon&18404957=Kartesios&79528454=ai_katerina&125322383=TheKoulWay&275882593=lawgreece&18627400=nqtv&617386550=epamhellas&544153184=toxwni, on which I do a .split('&') before looping Commented Sep 9, 2013 at 23:09
  • 3
    Your click handler does access the values that were processed during the last iteration and set to the same variables. See Javascript closure inside loops - simple practical example on how to fix that. Commented Sep 9, 2013 at 23:13
  • 2
    If you're looping an array make sure to use a regular for loop, not a for..in Commented Sep 9, 2013 at 23:14
  • had no idea about this 'closure' trap, thanks a lot Commented Sep 9, 2013 at 23:18

1 Answer 1

1

The issue here is that the functions created on each iteration of your loop are going to look in the enclosing scope for the value of the name variable when the function is called. This means that every one of those functions will end up using the value of name from the final iteration.

Consider the following simple example which illustrates what is going on here:

var functions = [];
for (var i = 0; i < 3; i++) {
    functions.push(function() {
        console.log(i);
    });
}
functions[0]();  // logs 3

So even though at a glance it looks like functions[0](); should log 0 since that was the value of i when functions[0] was created, it logs 3 because that is the value of i when the function is called.

One way to fix this is to use a closure that fixes the variables to their current value in each iteration:

function createClickHandler(path, name) {
    return function() {             
        $.ajax({ url: path + '/twitter/directmessage.php',
                 data: {'screen_name': name},
                 type: 'post',
                 success: function(output) { alert(output); }
                });
    };
};
for (var i in tokens) {
    .                   
    .   
    .
    $(button).addClass('friend-invite-button')
        .html('Invite')
        .click(createClickHandler(path, name)); 
}
Sign up to request clarification or add additional context in comments.

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.