Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Re: Perlmonks AJAX Voting (greasemonkey plugin)

by eric256 (Parson)
on Dec 13, 2007 at 02:16 UTC ( #656736=note: print w/replies, xml ) Need Help??

in reply to Perlmonks AJAX Voting

  • Updated 12-17-07: Added a refresh link to the XP Nodelet (click the @ to get a refreshed count of votes)
  • Updated 12-15-07: removed the need for javascript in a big string, fixed issues with voting booth and picked some better XPath's.
  • Updated 12-14-07: fix error with parent_node_id that caused it to be detected as a bot
  • Updated 12-13-07: use local XMLHttpRequest objects and removed extraneous code.

// // ==UserScript== // @name Perlmonks AJAX Vote // @namespace // @description Allow background voting via AJAX // @include http://www.perlmonks.* // @include http://perlmonks.* // @exclude http://www.perlmonks.*/?node=Fullpage%20Chat // @exclude http://perlmonks.*/?node=Fullpage%20Chat // ==/UserScript== function postRequest (url, params, onLoad) { var xmlHttpReq = new XMLHttpRequest();'POST', url, true); xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-for +m-urlencoded'); xmlHttpReq.onreadystatechange = function() { if (xmlHttpReq.readyState == 4) { onLoad(xmlHttpReq.responseText); }; }; xmlHttpReq.send(params); } function _cast_vote(node_id, voteString, vc, vote) { document.getElementById('pm_'+voteString).innerHTML='<b>Casting Vote. +..</b>'; postRequest('/?', 'displaytype=xml&vc='+vc+'&op=vote&.cgifields='+vot +eString+'&'+voteString+'='+vote, function () { document.getElementById('pm_'+voteString).innerHTML = 'Retriev +ing Node Reputation...'; postRequest('/?', 'displaytype=xml&node_id=' + node_id, function (retHTML) { var parser=new DOMParser(); var doc=parser.parseFromString(retHTML,'text/xml'); var x=doc.getElementsByTagName('field'); for(i=0;i<x.length;i++) { var item=x.item(i); if (item.attributes.getNamedItem('name').value == +'reputation') { document.getElementById('pm_'+voteString).inne +rHTML = 'Reputation: ' + item.childNodes[0].nodeValue; } }; }); }); }; function getNode_byPath (path) { var temp = document.evaluate(path, document, null, XPathResult.FIR +ST_ORDERED_NODE_TYPE, null); if (temp) { return temp.singleNodeValue; } else { return null; } } function getNodes_byPath(path,context) { var nodes = document.evaluate(path,context, null, XPathResult.ORDE +RED_NODE_SNAPSHOT_TYPE, null); var ret = []; for (var i = 0; i < nodes.snapshotLength; i++) { ret.push(nodes.snapshotItem(i)); } return ret; } function remove_byPath (path, context) { var nodes = getNodes_byPath(path, context); for (i in nodes) { nodes[i].parentNode.removeChild(nodes[i]); } } function cast_vote (node_id, voteString, vc, vote) { return function () { _cast_vote(node_id, voteString, vc, vote); }; } function _refresh_votes () { postRequest('/?', 'node_id=16046', function (retHTML) { var parser=new DOMParser(); var doc=parser.parseFromString(retHTML,'text/xml'); var x=doc.getElementsByTagName('XP'); for(i=0;i<x.length;i++) { var item=x.item(i); var xpNodelet = getNode_byPath("//tr[@id='nodelet_body +_row_XP_Nodelet']/td"); if (xpNodelet) xpNodelet.innerHTML = "You have " + item.attribut +es.getNamedItem('votesleft').value + ' votes left today.'; }; }); } function refresh_votes () { return function () { _refresh_votes() } } var xpNodelet = getNode_byPath("//tr[@id='nodelet_head_row_XP_Nodelet' +]/th"); if (xpNodelet) var refresh = document.createElement('a'); refresh.setAttribute("href",'javascript:void(0);'); refresh.removeAttribute("onclick"); refresh.addEventListener("click", refresh_votes(), true); refresh.innerHTML = " @"; xpNodelet.appendChild(refresh); } var inputNode = getNode_byPath("//input[@name='op' and @value='vote']" +); if (inputNode) { var formNode = inputNode.parentNode; var vc; var inputVC = getNode_byPath("//input[@name='vc']", formNode); if (inputVC) { vc = inputVC.value; } var votinginputs = getNodes_byPath("//label/input[@type='radio']", + formNode); for (var i in votinginputs) { var thisInput = votinginputs[i]; if (thisInput.value == 0) { var voteString =; var node_id = voteString.substring(6); var voting_both = document.createElement("div"); voting_both.class = 'reputation'; = "pm_" + voteString; var up_vote = document.createElement('a'); up_vote.setAttribute("href",'javascript:void(0);'); up_vote.removeAttribute("onclick"); up_vote.addEventListener("click", cast_vote(node_id, voteS +tring, vc, 1), true); up_vote.innerHTML = "++"; voting_both.appendChild(up_vote); var spacer = document.createElement("span"); spacer.innerHTML = "&nbsp;"; voting_both.appendChild(spacer); var down_vote = document.createElement('a'); down_vote.setAttribute("href",'javascript:void(0);'); down_vote.removeAttribute("onclick"); down_vote.addEventListener("click", cast_vote(node_id, vot +eString, vc, -1), true); down_vote.innerHTML = "--"; voting_both.appendChild(down_vote); thisInput.parentNode.insertBefore(voting_both, thisInput); } thisInput.parentNode.removeChild(thisInput); } // remove the original voting labels remove_byPath("//div[@class='vote']//tt", formNode); // delete the submit button remove_byPath("//input[@name='sexisgreat']", document); }

Eric Hodges

Replies are listed 'Best First'.
Re^2: Perlmonks AJAX Voting (greasemonkey plugin)
by citromatik (Curate) on Dec 13, 2007 at 11:17 UTC

    Maybe I'm wrong, but I see that you are using global xmlHttpReq objects in asynchronous requests. This could lead into problems, because a second (and successive) asynchronous request (i.e. a second vote in the page) will overwrite previous ones if they are not finished and you'll never receive a response from them.

    There are some ways of solving this, for example, putting multiple xmlHttpReq objects in an array.

    Sorry if I misread your code


      Thanks for that catch, I updated the code to use local variables, some testing shows that this works now. Guess I never though of anyone voting that fast!

      Eric Hodges
Re^2: Perlmonks AJAX Voting (greasemonkey plugin)
by ikegami (Pope) on Dec 13, 2007 at 03:01 UTC
    Greasemonkey isn't needed since PerlMonks already allows you to inject HTML and scripts via the Free Nodelet. Perhaps I'll take a stab at converting the code next week.
Re^2: Perlmonks AJAX Voting (greasemonkey plugin)
by eric256 (Parson) on Dec 17, 2007 at 21:18 UTC

    Updated 12-17-07: Added a refresh link to the XP Nodelet (click the @ to get a refreshed count of votes)

    Eric Hodges

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://656736]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (6)
As of 2017-01-23 18:14 GMT
Find Nodes?
    Voting Booth?
    Do you watch meteor showers?

    Results (194 votes). Check out past polls.