GM_xmlhttpRequest数据被放置在错误的位置 [英] GM_xmlhttpRequest data is being placed in the wrong places

查看:59
本文介绍了GM_xmlhttpRequest数据被放置在错误的位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下出色的用户脚本(适用于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>&nbsp;");
                }}(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>&nbsp;';

    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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆