Created
March 23, 2016 15:19
-
-
Save kms70847/d0d98dc7fe6d07aff1b1 to your computer and use it in GitHub Desktop.
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 Hacker News Post Sorter | |
// @namespace . | |
// @include https://news.ycombinator.com/ | |
// @version 1 | |
// @grant none | |
// ==/UserScript== | |
HTMLCollection.prototype.forEach = Array.prototype.forEach; | |
function keySort(seq, key){ | |
function compare(a,b){ | |
if(a<b){return -1;} | |
if(a>b){return 1;} | |
return 0; | |
} | |
seq.sort((a,b)=>compare(key(a),key(b))); | |
} | |
function Story(titleNode, infoNode, spacerNode){ | |
this.titleNode = titleNode; | |
this.infoNode = infoNode; | |
this.spacerNode = spacerNode; | |
} | |
Story.prototype.getCommentCount = function(){ | |
var links = this.infoNode.getElementsByTagName("A"); | |
//not sure which link, if any, is the comments link. | |
//iterate through them all looking for a reasonable match. | |
for(var i = 0; i < links.length; i+=1){ | |
link = links[i]; | |
var groups = /(\d*) comments?/.exec(link.innerHTML); | |
if (groups != null){ | |
return parseInt(groups[1]); | |
} | |
} | |
//some posts don't have comments at all. | |
return 0; | |
} | |
Story.prototype.getPoints = function(){ | |
var node = this.infoNode.getElementsByClassName("score")[0]; | |
if (node == undefined){return 0;} | |
var groups = /(\d*) points?/.exec(node.innerHTML); | |
if (groups == null){return 0;} | |
return parseInt(groups[1]); | |
} | |
Story.prototype.getRank = function(){ | |
var rankNode = this.titleNode.getElementsByClassName("Rank")[0]; | |
return parseInt(rankNode.innerHTML.replace(/\D/g, "")); | |
} | |
function rearrange(func){ | |
var table = document.getElementsByClassName("itemList")[0]; | |
var body = table.getElementsByTagName("tbody")[0]; | |
var rows = body.getElementsByTagName("tr"); | |
var stories = []; | |
for(var i = 0; i < rows.length-2; i+=3){ | |
stories.push(new Story(rows[i], rows[i+1], rows[i+2])); | |
} | |
keySort(stories, func); | |
while (body.firstChild) { | |
body.removeChild(body.firstChild); | |
} | |
stories.forEach(function(story){ | |
body.appendChild(story.titleNode); | |
body.appendChild(story.infoNode); | |
body.appendChild(story.spacerNode); | |
}); | |
} | |
function makeRotaryButton(config){ | |
var button = document.createElement("A"); | |
var idx = 0; | |
button.innerHTML = config[idx]["text"]; | |
button.onclick = function(){ | |
config[idx]["func"](); | |
idx = (idx + 1) % config.length; | |
button.innerHTML = config[idx]["text"]; | |
}; | |
return button | |
} | |
//this is kind of dumb... We want the label to indicate the effect that the last button press had. | |
//it's a little awkward that the functions don't match up with their descriptions. | |
//This makes it harder to rearrange the rotation order. | |
var button = makeRotaryButton([ | |
{text: "sorting by rank", func: ()=>rearrange(s=>-s.getCommentCount())}, | |
{text: "sorting by comments", func: ()=>rearrange(s=>-s.getPoints())}, | |
{text: "sorting by points", func: ()=>rearrange(s=>s.getRank())} | |
]); | |
var x = document.getElementsByClassName("pagetop")[0]; | |
x.innerHTML += "| "; | |
x.appendChild(button); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment