0

I'm writing a userscript for a website that uses Prototype. Rather than use the GM libs (mainly so I can easily repurpose it for Chrome), I decided to use the already-loaded Prototype functions.

I'm iterating through the rows of a table, each signifying a unique user, by checking for an online status element on their profile page.

dom = unsafeWindow; //shortening unsafewindow

console.log("main start");
var rows = dom.$$("#users tbody>tr");
var users = dom.$$("#users tbody>tr .user_avatar");
console.log(rows);
for (var i=0; i < users.length; i++) {
    var row = rows[i];
    var user = users[i];
    new dom.Ajax.Request("/users/" + user["title"] + ".html", { //user["title"] is the username
            method:'get',
            onSuccess:     function(response) {
                                var state = "offline";
                                if (response.responseText.indexOf("now_online") > -1) {
                                    state = "online";
                                }
                                row.childElements()[1].innerHTML += "<br /><b>" + state + "</b>";
                        }, 
            onFailure:    function(request) {
                            row.childElements()[1].innerHTML += "<br /><b>Error</b>";
                        }
        }
    );
}

Observing the script executing in Firebug, I see all of the GETs return valid response bodies with a status of 200. However, "online" only gets displayed in the last row. It appears as if the callbacks for the previous rows aren't being called. I have verified this with console.log statements after each line.

I searched and found that there were issues with how FB and Firefox 3.5 handled multiple Ajax.Requests http://code.google.com/p/fbug/issues/detail?id=1948. I upgraded to the most recent beta of Firebug and have the most recent non-beta version of Firefox, and still no dice. The problem occurs even when I have FB disabled completely.

I'm pretty much drawing a blank at this point, so I'm open to any and all suggestions. Thanks.

Rob W
  • 341,306
  • 83
  • 791
  • 678
Mr. S
  • 1,469
  • 2
  • 15
  • 27
  • 1
    This is a FAQ. See http://stackoverflow.com/questions/1061622/javascript-onclick-anonymous-function-help/1061671#1061671 – Chetan S Nov 19 '09 at 00:22
  • Where does the 'element' come from? How was it instantiated? – o.k.w Nov 19 '09 at 00:24
  • Also this - http://james.padolsey.com/javascript/closures-in-javascript/ – Chetan S Nov 19 '09 at 00:27
  • @o.k.w: thanks for the catch - element was a result of me moving code from a function back into the main ajax callback. @Chetan: Thanks for the links, but I don't think this is a closure issue. I have replaced the contents of the callbacks with console.log statements, and I'm still only seeing the last row getting the callback, despite all the requests being made. – Mr. S Nov 19 '09 at 11:42

1 Answers1

0

try using function.bind() to set the scope/prepend a variable.

        onSuccess:     function(response) {
                            var state = "offline";
                            if (response.responseText.indexOf("now_online") > -1) {
                                state = "online";
                            }
                            arguments[0].innerHTML += "<br /><b>" + state + "</b>";
                    }.bind(this,row), 

EDIT: or check out This Way Of Doing It

Community
  • 1
  • 1
Dereleased
  • 9,939
  • 3
  • 35
  • 51
  • I can't bind to a function like that. The only binding technique that could possibly work in these circumstances is if I could do ajaxReq.onSuccess.bind(this, row), but the minute I instantiate onSuccess, the request gets made. – Mr. S Nov 19 '09 at 11:37
  • I'm sorry, I don't understand why you can't bind like this; the function "bind" returns a functor, which is exactly what the onSuccess argument is expecting. – Dereleased Nov 19 '09 at 18:09
  • I can't call bind like this function(param) { ... }.bind(scope vars), I get js errors. – Mr. S Nov 19 '09 at 21:50
  • 1
    That is very strange, I have used that convention many times with no errors, mind sharing what browser/version this is on? Also, try surrounding the function declaration with parenthesis to hand-serialize it, e.g. `onSuccess: (function () {}).bind(this,...)` – Dereleased Nov 19 '09 at 22:58