I have written a UserScript for Greasemonkey (Firefox) and am testing it for compatibility with Chrome's Tampermonkey, and getting errors in the developer console:
Uncaught TypeError: Cannot read property 'profile_url' of undefined
Uncaught TypeError: Cannot read property 'encoded_name' of undefined
The errors seem to be referencing the onreadystatechanged
callback of GM_xmlhttpRequest
which is called like this:
var flairs = document.querySelectorAll('span.flair');
var steam_re = /(?:(?:https?:\/\/)?www\.)?(?:steam|pc)(?:community\.com\/?(?:(id|profiles)\/?)?|[\s\-_]*id)?[\/:\s\|]*(.{2,}?)(?:[\/|:\-\[(] ?(?:\/?(?:ghost|enforcer|tech|mm|master))+[\[)]?)?$/i
function get_text(e) { return e.innerText || e.textContent; }
function set_text(e, t) {
if (e.innerText)
e.innerText = t;
else
e.textContent = t;
}
var parser = new DOMParser();
for (var i = 0; i < flairs.length; i++) {
var text = get_text(flairs[i]);
var match = steam_re.exec(text);
if (match == null || match.length < 3)
continue;
var type = match[1] || 'id';
var name = encodeURIComponent(match[2]);
var url = 'http://steamcommunity.com/' + type + '/' + name;
var xml_url = url + '?xml=1';
GM_xmlhttpRequest({
method: 'GET',
url: xml_url, // Link to a steam profile with ?xml=1 added
accept: 'text/xml',
context: {
flair_index: i,
flair_text: text, // textContent of span element
encoded_name: name,
profile_url: url, // Link to steam profile
query_url: xml_url
},
onreadystatechange: function(response) {
if (response.readyState != 4)
return;
// Attempt to fall back to alternate forms of context,
// none of which works. response.context works on Firefox/Greasemonkey.
var context = response.context || this.context || context;
var doc = parser.parseFromString(response.responseText, 'text/xml');
var validProfile = doc.documentElement.nodeName == 'profile';
var a = document.createElement('a');
a.href = validProfile ?
context.profile_url : // TypeError here, context is undefined
('http://steamcommunity.com/actions/SearchFriends?K=' + context.encoded_name);
a.className += (validProfile ? 'steam-profile-link' : 'steam-profile-search-link');
var a_text = document.createTextNode(context.flair_text);
a.appendChild(a_text);
set_text(flairs[context.flair_index], '');
flairs[context.flair_index].appendChild(a);
}
});
}
The function itself is called fine, and the callback is invoked, but once I try to access the context
var inside it, it's undefined.
It all works as expected in Firefox. What it does is iterating over span
elements that have the "flair" class and checking with a regex if they contain a Steam username, and if so, makes it a link to their SteamCommunity page. (Full source on github). The script runs on /r/PaydayTheHeistOnline.
I have tested using an array defined outside the function to store the data instead of using the context property passed to xmlhttpRequest, but I'm getting the exact same error.
Update:
Tampermonkey now reports that this feature is fixed as of version 3.8.4116 (in beta at the moment). See:
Older/generic workaround:
The
context
property is a relatively new feature ofGM_xmlhttpRequest()
, in Firefox. I doubt it's been implemented in Tampermonkey yet; see Tampermonkey's docs forGM_xmlhttpRequest()
.Meanwhile, the tried-and-true method for this kind of thing is to use a closure.
Change your
GM_xmlhttpRequest()
call to something like: