Skip to content

Instantly share code, notes, and snippets.

@kennethrapp
Created August 17, 2014 22:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kennethrapp/0ef17d2145f2a6e38cca to your computer and use it in GitHub Desktop.
Save kennethrapp/0ef17d2145f2a6e38cca to your computer and use it in GitHub Desktop.
general purpose hacker news thing
// ==UserScript==
// @name HackBar
// @namespace kennethrapp1@gmail.com
// @description Extras for Hacker News
// @include https://news.ycombinator.com/*
// @version 1
// @grant none
// ==/UserScript==
//Returns true if is a DOM node
function IsNode(o) {
return (typeof Node === 'object' ? o instanceof Node :
o && typeof o === 'object' && typeof o.nodeType === 'number' && typeof o.nodeName === 'string'
);
}
//Returns true if object o is a DOM element
function IsElement(o) {
return (typeof HTMLElement === 'object' ? o instanceof HTMLElement :
//DOM2
o && typeof o === 'object' && o !== null && o.nodeType === 1 && typeof o.nodeName === 'string'
);
}
// return true if array a contains value v
function ArrayContains(a, v) {
for (var i = 0; i < a.length; i++) {
if (a[i] === v) {
return true;
}
}
return false;
}
// remove a value from an array
function ArrayRemove(arr) {
var what,
a = arguments,
L = a.length,
ax;
while (L > 1 && arr.length) {
what = a[--L];
while ((ax = arr.indexOf(what)) !== - 1) {
arr.splice(ax, 1);
}
}
return arr;
}
// run a callback on an xpath
function AffectDOMPath(expression, callback) {
var result = document.evaluate(expression, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
if (result.snapshotLength) {
for (i = 0; i <= result.snapshotLength - 1; i++) {
callback.call(this, result.snapshotItem(i));
}
}
}
// generic html element builder
function MakeElement(tag, attrs, inner) {
var element = document.createElement(tag);
if (typeof attrs == 'object') {
for (var a in attrs) {
element.setAttribute(a, attrs[a]);
}
}
if (typeof inner == 'string') {
var b = document.createTextNode(inner);
element.appendChild(b);
}
else if (IsElement(inner)) {
element.appendChild(inner);
}
return element;
}
// generic text control builder
function TextControl(textcontent, callback, args) {
var control = MakeElement('a', {
'href': '#',
'class': 'hn_top'
}, textcontent);
control.addEventListener('click', function (event) {
event.preventDefault();
callback.apply(this, args);
}, false);
return control;
}
// create and return a 'menu' of text controls
function BuildMenu(menu) {
var menuItem = document.createElement('span');
for (var i = 0; i < menu.length; i++) {
menuItem.appendChild(document.createTextNode('['));
menuItem.appendChild(TextControl.apply(this, menu[i]));
menuItem.appendChild(document.createTextNode(']'));
}
return menuItem;
}
/* controls. Each control is three items - text, function and arguments as an array.*/
var HNMenu = [
['watching', function () {alert('test')},[]],
['following', function(f){alert(f)}, ['test2']],
['ignoring', function(f){ }, []],
];
var UserMenu = [
['watch', function(){}, []],
['follow', function(){}, []],
['ignore', function(){}, []],
]
// xpaths to target
var HNPath = {
'UIMain': '//center[1]/table[1]/tbody[1]/tr[2]',
// blank table row right after the hn menu
'MenuTop': '(//span[@class="pagetop"])[1]',
// top banner/menu
'Comments': '//span[@class="comhead"]'
};
//.dead
AffectDOMPath("//td | //*[@class='dead']", function(node) {
node.setAttribute("style","color:#000000;");
});
/* create a new table cell in the blank row, style it, create a menu, append the menu. */
AffectDOMPath(HNPath['UIMain'], function (node) {
node.appendChild(MakeElement('td', {
'id': 'HNHacker_UI',
'style': 'padding-top:1em!important;padding-bottom:1em!important'
}, BuildMenu(HNMenu)));
});
AffectDOMPath(HNPath['Comments'], function (node) {
node.appendChild(MakeElement('span', {
'class':'HNuserMenu',
'style':'padding-left:1em'
}, BuildMenu(UserMenu)));
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment