Created
February 28, 2011 00:29
-
-
Save sizzlemctwizzle/846738 to your computer and use it in GitHub Desktop.
Making this script more cross-browser compatible: http://userscripts.org/scripts/show/56641
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name Reddit Uppers and Downers Enhanced | |
| // @namespace mistercow | |
| // @description Show up-votes and down-votes next to the total score on reddit comments. | |
| // @require http://sizzlemctwizzle.com/updater.php?id=56641 | |
| // @include http://www.reddit.com/*/comments/* | |
| // @include http://www.reddit.com/user/* | |
| // ==/UserScript== | |
| /* | |
| 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. | |
| 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. | |
| SizzleMctwizzle added code to update the up and down vote totals when you click one of the | |
| arrows by intercepting calls to the vote function. The code gets dumped to the page in an | |
| anonymous function so that it gets executed in the scope of the page. | |
| 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 | |
| sizzlemctwizzle - http://sizzlemctwizzle.com | |
| */ | |
| // Get the URL for the JSON details of this comments page | |
| var loc = window.location.href; | |
| var jsonURL = loc + "/.json"; | |
| if(loc.indexOf("?") != -1) { | |
| jsonURL = loc.replace("?","/.json?"); | |
| } | |
| // Define a function to add styles if not in Greasemonkey | |
| if (typeof GM_addStyle == 'undefined') | |
| var GM_addStyle = function(css) { | |
| var head = document.getElementsByTagName('head')[0], | |
| style = document.createElement('style'); | |
| if (!head) {return} | |
| style.type = 'text/css'; | |
| style.textContent = css; | |
| head.appendChild(style); | |
| }; | |
| 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 = (new Function('return ' + jsonText + ';'))(); | |
| } | |
| // Load the vote table by processing the tree | |
| processTree(data); //this takes up no time (4ms on 4000 records) | |
| // Display the loaded votes | |
| displayVotes(); | |
| }; | |
| // spend up to 50msec a time with a task, wait for 25msec and continue if necessary | |
| var 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; }\n" + | |
| ".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); | |
| } | |
| } | |
| }); | |
| } | |
| // 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 | |
| // SizzleMctwizzle made this a regular xhr request because | |
| // cross-domain requests are unnecessary | |
| // This makes the script cross-browser compatible | |
| if (jsonURL.indexOf('/comscore-iframe/') === -1) { | |
| var res = new XMLHttpRequest(); | |
| res.onreadystatechange = function() { | |
| if (res.readyState==4 && res.status==200) onloadJSON(res); | |
| }; | |
| res.open('GET', jsonURL, true); | |
| res.send(null); | |
| } | |
| // Update vote counts when user up/down votes a comment | |
| // Yes I made it all one giant string because other browsers don't support toString | |
| // Injecting it in the page also gets rid of the need for unsafeWindow | |
| var codeWrapper = '(function() {' + | |
| 'var origFnVote = $.fn.vote;' + | |
| '$.fn.vote = function(vh, callback, event, ui_only) {' + | |
| // Store the state of the errors before we call the | |
| // original vote function | |
| 'if (reddit.logged &&' + | |
| '$(this).hasClass("arrow")) {' + | |
| 'var arrow = $(this);' + | |
| 'var arrows = arrow.parent();' + | |
| 'var isUpPrev = arrows.find(".upmod").length > 0;' + | |
| 'var isDownPrev = arrows.find(".downmod").length > 0;' + | |
| '}' + | |
| // Call the original vote function | |
| 'origFnVote.call(this, vh, callback, event, ui_only);' + | |
| 'if (!reddit.logged &&' + | |
| '!$(this).hasClass("arrow")) { return; }' + | |
| 'var comment = arrow.parent().parent();' + | |
| 'var upperAndDowers = comment.find(".moo_ups, .moo_downs");' + | |
| 'var upper = upperAndDowers.get(0);' + | |
| 'var downer = upperAndDowers.get(1);' + | |
| 'var ups = parseInt(upper.textContent);' + | |
| 'var downs = parseInt(downer.textContent);' + | |
| 'if (arrow.hasClass("upmod")) {' + | |
| 'upper.textContent = ++ups;' + | |
| 'if (isDownPrev) {' + | |
| 'downer.textContent = --downs;' + | |
| '}' + | |
| '} else if (arrow.hasClass("downmod")) {' + | |
| 'downer.textContent = ++downs;' + | |
| 'if (isUpPrev) {' + | |
| 'upper.textContent = --ups;' + | |
| '}' + | |
| '} else if (isUpPrev && arrow.hasClass("up")) {' + | |
| 'upper.textContent = --ups;' + | |
| '} else if (isDownPrev && arrow.hasClass("down"))' + | |
| 'downer.textContent = --downs;' + | |
| '}' + | |
| '})();'; | |
| // Dump code to the page | |
| var scriptEl = document.createElement('script'); | |
| scriptEl.type = "text/javascript"; | |
| scriptEl.textContent = codeWrapper; | |
| document.body.appendChild(scriptEl); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment