我正在使用以下优秀用户(适用于Chrome,Chrome&#t; Tampermonkey和Firefox Greasemonkey)。它应该在每个IMDb电影链接旁边显示电影评级,但它已停止正常工作。
这是完整的脚本:
// ==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);
这就是an example page目前的看法:
如您所见,脚本在错误的位置显示结果。
为什么它出现在错误的地方以及如何解决?
答案 0 :(得分:2)
导致主要投诉的问题(导致错误的地方)是GM_xmlhttpRequest
异步操作(这很好)并且onload
构造不正确。
您需要将来电GM_xmlhttpRequest
打包到正确的closure或在context
来电中提供GM_xmlhttpRequest
。 (参见下面的代码。)
有关为何需要关闭的详细信息,请参阅this answer to the same type of problem。
其他重大问题包括AJAX-获取数十个不正确的链接以及在每个页面和iframe上触发。这两种方式都会使浏览器慢下来。
请勿使用@include *
。即使你不介意,脚本的其他用户也会。仅为您知道有IMDB链接的网站添加@include
或@match
行。
我以为我可能想自己使用这个脚本,所以我开始清理它。您可以阅读内联注释并与原始脚本进行比较,以了解一些较小的问题。 (不要使用onclick
并始终检查match
返回等。)
// ==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 ();