GM_xmlhttpRequest数据被放置在错误的位置 [英] GM_xmlhttpRequest data is being placed in the wrong places
问题描述
我正在使用以下出色的用户脚本(适用于Chrome,Chrome的Tampermonkey和Firefox Greasemonkey).它应该在每个 IMDb 电影链接旁边显示电影等级,但是它无法正常工作.
I am using the following excellent userscript (for Chrome, Chrome's Tampermonkey and Firefox Greasemonkey). It's supposed to display movie ratings next to each IMDb movie link, but it stopped working properly.
这是完整的脚本:
// ==UserScript==
// @name Add IMDb rating next to all IMDb links (+voter count)
// @author Ali
// @description Adds movie ratings and number of voters to any IMDb link. Modified version of http://userscripts.org/scripts/show/9174
// @include *
// @version 2013-05-12
// @namespace http://userscripts.org/scripts/show/96884
// @grant GM_xmlhttpRequest
// @downloadURL http://www.alibakir.com/upload/addimdbratings.js
// @updateURL http://www.alibakir.com/upload/addimdbratings.js
// ==/UserScript==
var IMDBpluginlinks = document.links;
var IMDBcontinueelement=document.createElement("button");
IMDBcontinueelement.innerHTML="Get rating";
function processIMDBLinks(s){
IMDBcontinueelement.style.display = 'none';
var r=0;
for (IMDBi = s; IMDBi < IMDBpluginlinks.length; IMDBi++) {
if (IMDBpluginlinks[IMDBi].href.indexOf("/title/") != -1 && IMDBpluginlinks[IMDBi].href.indexOf("imdb.") != -1){
if(r>300){
IMDBcontinueelement.onclick=function(){ processIMDBLinks(IMDBi); };
IMDBcontinueelement.style.display='inline';
IMDBpluginlinks[IMDBi].parentNode.insertBefore(IMDBcontinueelement, IMDBpluginlinks[IMDBi]);
break;
}
r++;
GM_xmlhttpRequest({
method: 'get',
headers: {
},
url: IMDBpluginlinks[IMDBi].href,
onload: function (IMDBi){return function(result) {
rating = result.responseText.match(/Users rated this (.*) \(/);
votes = result.responseText.match(/\((.*) votes\) -/);
IMDBpluginlinks[IMDBi].parentNode.insertBefore(document.createElement("span"), IMDBpluginlinks[IMDBi]).innerHTML = (rating ? "<b> [" + rating[1] + " - "+votes[1]+"] </b>" : "<b style='color: red;'>[NA] </b> ");
}}(IMDBi)
});
}
}
}
processIMDBLinks(0);
这就是示例页面当前的样子:
And this is how an example page looks at the moment:
如您所见,脚本将结果显示在错误的位置.
As you can see, the script displays the results in the wrong places.
为什么将它们显示在错误的位置,以及如何解决?
Why does it present them in the wrong place and how can it be fixed?
推荐答案
引起您主要抱怨(导致错误放置)的问题是GM_xmlhttpRequest
异步运行(很好)并且onload
构造不正确.
The issue causing your main complaint (results in the wrong places) is that GM_xmlhttpRequest
operates asynchronously (which is good) and the onload
was improperly constructed.
您需要将对GM_xmlhttpRequest
的调用包装在适当的闭包中,或在GM_xmlhttpRequest
呼叫. (请参见下面的代码.)
You either need to wrap the call to GM_xmlhttpRequest
in a proper closure or provide a context
in the GM_xmlhttpRequest
call. (See the code below.)
有关为何需要关闭的详细信息,请参见对相同类型问题的答案.
For more information on why closures are needed, see this answer to the same type of problem.
其他重大问题包括AJAX获取数十个不正确的链接以及在每个页面和iframe上触发.两者都使浏览器速度大大降低.
Other big problems include AJAX-fetching dozens of improper links and firing on every page and iframe. Both of these slow the browser down quite a bit.
请勿使用@include *
.即使您不介意,该脚本的其他用户也会这样做.仅为您知道具有IMDB链接的站点添加@include
或@match
行.
Don't use @include *
. Even if you don't mind, other users of the script will. Add @include
or @match
lines for just the sites that you know have IMDB links.
我认为我可能想自己使用此脚本,因此我开始对其进行清理.您可以阅读内联注释并与原始脚本进行比较,以了解一些较小的问题. (不要使用onclick
并始终检查match
返回等)
I thought that I might want to use this script myself, so I started cleaning it up. You can read the inline comments and compare to the original script for an idea of some of the lesser problems. (Don't use onclick
and always check match
returns, etc.)
// ==UserScript==
// @name add IMDb rating next to all IMDb links (+voter count)
// @description Adds movie ratings and number of voters to any imdb link. Modified version of http://userscripts.org/scripts/show/96884
// @match *://www.imdb.com/*
// @grant GM_xmlhttpRequest
// ==/UserScript==
var maxLinksAtATime = 50; //-- pages can have 100's of links to fetch. Don't spam server or browser.
var fetchedLinkCnt = 0;
function processIMDB_Links () {
//--- Get only links that could be to IMBD movie/TV pages.
var linksToIMBD_Shows = document.querySelectorAll ("a[href*='/title/']");
for (var J = 0, L = linksToIMBD_Shows.length; J < L; J++) {
var currentLink = linksToIMBD_Shows[J];
/*--- Strict tests for the correct IMDB link to keep from spamming the page
with erroneous results.
*/
if ( ! /^(?:www\.)?IMDB\.com$/i.test (currentLink.hostname)
|| ! /^\/title\/tt\d+\/?$/i.test (currentLink.pathname)
)
continue;
if (! currentLink.getAttribute ("data-gm-fetched") ){
if (fetchedLinkCnt >= maxLinksAtATime){
//--- Position the "continue" button.
continueBttn.style.display = 'inline';
currentLink.parentNode.insertBefore (continueBttn, currentLink);
break;
}
fetchTargetLink (currentLink); //-- AJAX-in the ratings for a given link.
//---Mark the link with a data attribute, so we know it's been fetched.
currentLink.setAttribute ("data-gm-fetched", "true");
fetchedLinkCnt++;
}
}
}
function fetchTargetLink (linkNode) {
//--- This function provides a closure so that the callbacks can work correctly.
/*--- Must either call AJAX in a closure or pass a context.
But Tampermonkey does not implement context correctly!
(Tries to JSON serialize a DOM node.)
*/
GM_xmlhttpRequest ( {
method: 'get',
url: linkNode.href,
//context: linkNode,
onload: function (response) {
prependIMDB_Rating (response, linkNode);
},
onload: function (response) {
prependIMDB_Rating (response, linkNode);
},
onabort: function (response) {
prependIMDB_Rating (response, linkNode);
}
} );
}
function prependIMDB_Rating (resp, targetLink) {
var isError = true;
var ratingTxt = "** Unknown Error!";
if (resp.status != 200 && resp.status != 304) {
ratingTxt = '** ' + resp.status + ' Error!';
}
else {
if (/\(awaiting \d+ votes\)|\(voting begins after release\)|in development/i.test (resp.responseText) ) {
ratingTxt = "NR";
isError = false;
}
else {
var ratingM = resp.responseText.match (/Users rated this (.*) \(/);
var votesM = resp.responseText.match (/\((.*) votes\) -/);
if (ratingM && ratingM.length > 1 && votesM && votesM.length > 1) {
isError = false;
ratingTxt = ratingM[1] + " - " + votesM[1];
}
}
}
var resltSpan = document.createElement ("span");
resltSpan.innerHTML = '<b> [' + ratingTxt + '] </b> ';
if (isError)
resltSpan.style.color = 'red';
//var targetLink = resp.context;
//console.log ("targetLink: ", targetLink);
targetLink.parentNode.insertBefore (resltSpan, targetLink);
}
//--- Create the continue button
var continueBttn = document.createElement ("button");
continueBttn.innerHTML = "Get ratings";
continueBttn.addEventListener ("click", function (){
fetchedLinkCnt = 0;
continueBttn.style.display = 'none';
processIMDB_Links ();
},
false
);
processIMDB_Links ();
这篇关于GM_xmlhttpRequest数据被放置在错误的位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!