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.';
}
Kokas
  • 131
  • 1
  • 11
  • 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 – Kokas Sep 09 '13 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](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) on how to fix that. – Bergi Sep 09 '13 at 23:13
  • 2
    If you're looping an array make sure to use a regular `for` loop, not a `for..in` – elclanrs Sep 09 '13 at 23:14
  • had no idea about this 'closure' trap, thanks a lot – Kokas Sep 09 '13 at 23:18

1 Answers1

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)); 
}
Andrew Clark
  • 202,379
  • 35
  • 273
  • 306