
Reddit Uppers and Downers Enhanced – JSLint, Fragment, and Chunking Update
Below is the updated Reddit Uppers and Downers Enhanced. This update forces RUDE to wait for 25ms after processing for 50ms to allow the UI to update. One complaint that I’ve often had is that the UI gets stuck when there are a lot of comments on the page. This update should fix that issue. It also speeds up the code quite a bit by processing the objects slightly better than before.
A known bug that might occur is on some comments the script doesn’t create the ups/downs span. This only happens on hidden comments which can be shown by clicking the “load more comments” link. The link queries the server, then updates a layer with the new information from the server. The RUDE script doesn’t get called to process those new results, so I will have to attach a method to call the RUDE script on those results after they’ve loaded.
// ==UserScript== // @name Reddit Uppers and Downers Enhanced // @namespace mistercow // @description Show up-votes and down-votes next to the total score on reddit comments. // @include http://www.reddit.com/*/comments/* // @include http://www.reddit.com/user/* // ==/UserScript== /*jslint strict:false, browser:true, plusplus:false, newcap:false*/ /*global window:false, GM_addStyle:false, GM_xmlhttpRequest:false*/ /* This code is provided as is, with no warranty of any kind. I hacked it together in one night for my own use, and have not tested it extensively. The script can slow down comment page load time; if the lag is noticeable, you may want to change your preferences to load fewer comments per page. Note that this runs once and does not install any persistent code on the page. So any votes you cast will not affect the numbers displayed until you reload. Also note that the ups and downs will not always add up to the score displayed on reddit. I think this is because of caching on reddit's part. It's usually within one or two points though. Update: Allan Bogh contributed code which significantly sped up the processing of comments. 1500 comments could be processed in 113ms, over previous cases of 3000+ms. skeww contributed code which chunks the rendering of comments into 50ms time slots, then pauses for 25ms. Additionally, he cleaned up various parts of the code to enable faster processing. Allan included skeww's contribution and also cleaned up the code to further improve speed. Time testing code (in comments) are left in quick user tests. 1500 records processed at 6ms, although this may be related to when the function returns, but not when it's actually complete. Code contributors: Allan Bogh - http://www.opencodeproject.com brasso - http://userscripts.org/scripts/show/56641 savetheclocktower - http://gist.github.com/174069 skeww (jslint, fragment, chunking) - http://kaioa.com */ var loc, jsonURL, voteTable, onloadJSON, displayVotes, processTree, isComment, processChildren, processReplies, chunker; //Get the URL for the JSON details of this comments page var loc = ""+location; var jsonURL = loc + "/.json"; if(loc.indexOf("?") != -1) { jsonURL = loc.replace("?","/.json?"); } var voteTable = {}; function onloadJSON(response) { var jsonText = response.responseText,data; //Parse the json text // Use native JSON (if it's available) because it's much faster. // code by savetheclocktower - http://gist.github.com/174069 if (window.JSON && JSON.parse) { data = JSON.parse(jsonText); }else{ data = eval("("+jsonText+")"); } //Load the vote table by processing the tree processTree(data); //this takes up no time (4ms on 4000 records) //Display the loaded votes //date1 = new Date(); //milliseconds1 = date1.getTime(); displayVotes(); //date2 = new Date(); //milliseconds2 = date2.getTime(); //difference = milliseconds2 - milliseconds1; //alert(difference+"ms - "); }; // spend up to 50msec a time with a task, wait for 25msec and continue if necessary chunker = function (items, process) { var todo = items.concat(); setTimeout(function () { var start = Date.now(); do { process(todo.shift()); } while (todo.length && Date.now() - start < 50); if (todo.length) { setTimeout(arguments.callee, 25); } }, 25); }; function displayVotes(){ //Add the style sheets for up and down ratings GM_addStyle(".moo_ups { color:rgb(255, 139, 36); font-weight:bold; }"); GM_addStyle(".moo_downs { color:rgb(148,148,255); font-weight:bold; }"); var taglines, commentID = null, toArray; toArray = function(col){ var a = [], i, len; for(i=0, len=col.length; i< len; i++){ a[i] = col[i]; } return a; }; taglines = toArray(document.getElementsByClassName("tagline")); chunker(taglines, function(item){ var votes, openparen, mooups, pipe, moodowns, voteDowns, voteUps, closeparen, frag; if(item.nextSibling.nodeName === "FORM"){ //the first item is the title of the post commentID = item.nextSibling.firstChild.value; if(voteTable[commentID]){ frag = document.createDocumentFragment(); //using a fragment speeds this up by a factor of about 2 votes = voteTable[commentID]; openparen = document.createTextNode(" ("); frag.appendChild(openparen); mooups = document.createElement("span"); mooups.className = "moo_ups"; voteUps = document.createTextNode(votes.ups); mooups.appendChild(voteUps); frag.appendChild(mooups); pipe = document.createTextNode("|"); item.appendChild(pipe); moodowns = document.createElement("span"); moodowns.className = "moo_downs"; voteDowns = document.createTextNode(votes.downs); moodowns.appendChild(voteDowns); frag.appendChild(moodowns); closeparen = document.createTextNode(")"); frag.appendChild(closeparen); frag.appendChild(openparen); frag.appendChild(mooups); frag.appendChild(pipe); frag.appendChild(moodowns); frag.appendChild(closeparen); item.appendChild(frag); } } }); /*var commentID = null; for(i=0, il=taglines.length; i < il; i++){ if(taglines[i].nextSibling.nodeName === "FORM"){ //the first item is the title of the post commentID = taglines[i].nextSibling.firstChild.value; if(voteTable[commentID]){ votes = voteTable[commentID]; var parent = taglines[i]; var openparen = document.createTextNode(" ("); parent.appendChild(openparen); var mooups = document.createElement("span"); mooups.className = "moo_ups"; var voteUps = document.createTextNode(votes.ups); mooups.appendChild(voteUps); parent.appendChild(mooups); var pipe = document.createTextNode("|"); parent.appendChild(pipe); var moodowns = document.createElement("span"); moodowns.className = "moo_downs"; var voteDowns = document.createTextNode(votes.downs); moodowns.appendChild(voteDowns); parent.appendChild(moodowns); var closeparen = document.createTextNode(")"); parent.appendChild(closeparen); parent.appendChild(openparen); parent.appendChild(mooups); parent.appendChild(pipe); parent.appendChild(moodowns); parent.appendChild(closeparen); } } }*/ } //Recursively process the comment tree function processTree(obj) { var i, il, data, name; if(obj instanceof Array) { for(var i=0, il=obj.length; i < il; i++) { processTree(obj[i]); } } data = obj.data; if(data) { //Data found if(isComment(obj) && data.author !== "[deleted]") { name = data.name; if(name) { //Store the votes in the vote table voteTable[name] = { downs:data.downs || 0, ups:data.ups || 0 }; } } //Process any subtrees processChildren(data); processReplies(data); } }; function isComment(obj) { return obj.kind === "t1"; }; function processChildren(data) { var children = data.children, i, il; if(children) { for(i=0, il=children.length; i < il; i++){ processTree(children[i]); } } }; function processReplies(data) { var replies = data.replies; if(replies) processTree(replies); }; //load the JSON if (jsonURL.indexOf('/comscore-iframe/') === -1) { GM_xmlhttpRequest({ method: "GET", url: jsonURL, onload: onloadJSON }); }
There are no comments yet.