javascript - GM_xmlhttpRequest data is being placed in the wrong places -


i using following excellent userscript (for chrome, chrome's tampermonkey , firefox greasemonkey). it's supposed display movie ratings next each imdb movie link, stopped working properly.

this complete script:

// ==userscript== // @name           add imdb rating next imdb links (+voter count) // @author         ali // @description    adds movie ratings , number of voters 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;     (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 (.*) \(/);                      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); 


, how an example page looks @ moment:

results being added wrong links


can see, script displays results in wrong places.

why present them in wrong place , how can fixed?

the issue causing main complaint (results in wrong places) gm_xmlhttprequest operates asynchronously (which good) , onload improperly constructed.

you either need wrap call gm_xmlhttprequest in proper closure or provide context in gm_xmlhttprequest call. (see code below.)

for more information on why closures needed, see this answer same type of problem.


other big problems include ajax-fetching dozens of improper links , firing on every page , iframe. both of these slow browser down quite bit.

don't use @include *. if don't mind, other users of script will. add @include or @match lines sites know have imdb links.

i thought might want use script myself, started cleaning up. can read inline comments , compare original script idea of of lesser problems. (don't use onclick , check match returns, etc.)

// ==userscript== // @name         add imdb rating next imdb links (+voter count) // @description  adds movie ratings , number of voters 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 fetch. don't spam server or browser. var fetchedlinkcnt      = 0;  function processimdb_links () {     //--- links imbd movie/tv pages.     var linkstoimbd_shows   = document.queryselectorall ("a[href*='/title/']");      (var j = 0, l = linkstoimbd_shows.length;  j < l;  j++) {         var currentlink = linkstoimbd_shows[j];          /*--- strict tests correct imdb link keep spamming page             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 "continue" button.                 continuebttn.style.display = 'inline';                 currentlink.parentnode.insertbefore (continuebttn, currentlink);                 break;             }              fetchtargetlink (currentlink); //-- ajax-in ratings given link.              //---mark link data attribute, know it's been fetched.             currentlink.setattribute ("data-gm-fetched", "true");             fetchedlinkcnt++;         }     } }  function fetchtargetlink (linknode) {     //--- function provides closure callbacks can work correctly.      /*--- must either call ajax in closure or pass context.         tampermonkey not implement context correctly!         (tries json serialize 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 (.*) \(/);             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 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 (); 

Comments

Popular posts from this blog

commonjs - How to write a typescript definition file for a node module that exports a function? -

openid - Okta: Failed to get authorization code through API call -

ios - Change Storyboard View using Seague -