Created
December 16, 2008 13:45
-
-
Save satyr/36459 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 GoogleReaderKeys | |
// @description Extra keybinds for Google Reader | |
// @namespace http://d.hatena.ne.jp/murky-satyr | |
// @include http://www.google.com/reader/view/* | |
// @include https://www.google.com/reader/view/* | |
// ==/UserScript== | |
http://gist.github.com/36459.txt?.user.js | |
const KE = document.createEvent('KeyEvents') | |
const Keys = { // C_ : ctrl / A_ : alt / M_ : meta | |
0: toggleExpandedOrListView, | |
3: showNewItems, | |
4: showAllItems, | |
9: toggleSortByNewOrOlder, | |
i: toggleShowAllItems, | |
'#': showUpdatedFeeds, | |
$: showAllFeeds, | |
y: toggleShowAllFeeds, | |
b: getHatebuComments, | |
B: hatebuIt, | |
d: toggleDetails, | |
h: jumpToItsFeed, | |
F: feedSettings, | |
5: showDetailedUnreadCount, | |
z: toggleManageFeeds, | |
'@': feedSpecificCommand, | |
c: increaseColumn, | |
C: decreaseColumn, | |
x: expandLinks, | |
'.': scrollUp(1/3), | |
',': scrollDn(1/3), | |
}; | |
for each(let k in ['Left', 'Right']) Keys[k] = free; | |
function free(e) !e.stopPropagation(); | |
function scrollUp(r) function(){ scrollEntries(-r) }; | |
function scrollDn(r) function(){ scrollEntries(+r) }; | |
function showNewItems(){ click('show-new') } | |
function showAllItems(){ click('show-all') } | |
function toggleShowAllItems() | |
(ofClass('show-all', 'selected') ? showNewItems : showAllItems)(); | |
function showUpdatedFeeds() | |
doMenu('lhn-subscriptions-menubutton', ':p') | |
function showAllFeeds() | |
doMenu('lhn-subscriptions-menubutton', ':o') | |
function toggleShowAllFeeds(){ | |
(ofClass('sub-tree', 'updated') ? showAllFeeds : showUpdatedFeeds)(); | |
} | |
function hatebuIt(){ | |
withURL(function(u) open('http://b.hatena.ne.jp/bookmarklet?url='+ | |
u.replace(/#/g, '%23'))); | |
} | |
function getHatebuComments(){ | |
withURL(function(u, it){ | |
xAppend( | |
it, | |
'curvebox-lb-body', | |
'http://b.hatena.ne.jp/entry/'+ u.replace(/#/g, '%23'), | |
function(htm)( | |
/<ul id="bookmarked_user"[^]+?<\/ul>/.test(htm) && | |
(RegExp.lastMatch | |
.replace(/\bhref=\"(?=\/)/g, '$&http://b.hatena.ne.jp') | |
.replace(/<ul/, '$& style="padding:0"')))); | |
}); | |
} | |
function toggleDetails(){ click('viewer-details-toggle') } | |
function jumpToItsFeed(){ | |
withIt(function(it){ | |
var ea = it.getElementsByClassName('entry-author')[0]; | |
ea && click((ea.getElementsByClassName('entry-source-title') || 0)[0]); | |
}); | |
} | |
function toggleManageFeeds(){ | |
click(ofClass(document.body, 'settings')? | |
id('settings-frame').contentDocument | |
.getElementById('close-settings-link'): | |
'sub-tree-subscriptions'); | |
} | |
function feedSpecificCommand(){ withURL(function(u, it){ switch(true){ | |
// Ads of the World: get the image of original size | |
case /^http:\/\/adsoftheworld\.com/.test(u):{ | |
var img = it.getElementsByTagName('img')[0]; | |
img.src = img.src.replace(/\.preview/, ''); | |
} break; | |
// Hateda: get comments | |
case /^http:\/\/(?:d|\w+\.g)\.hatena\.ne\.jp\/[a-zA-Z]/.test(u):{ | |
xAppend( | |
it, 'hateda-comments', u, | |
/<div class="commentshort"[^]+?(?=<p class="commentform"|<\/div>)/); | |
} break; | |
// Ajaxian: get comments | |
case /^http:\/\/feedproxy\.google\.com\/~r\/ajaxian\/~/.test(u):{ | |
xAppend(it, 'ajaxian-comments', u, | |
/<dl id="commentlist"[^]+?<\/dl>/); | |
} break; | |
// Wordpress: get comments | |
case (/^http:\/\/[\w-]+\.wordpress\.com[/]/.test(u) || | |
/^http:\/\/feedproxy\.google\.com\/~r\/Techcrunch[/]/.test(u)):{ | |
xAppend(it, 'wordpress-comments', u, | |
/<[ou]l class=".*?\bcommentlist\b.*?"[^]+?<\/[ou]l>/); | |
} break; | |
// 4koma.livedoor.com: get comments | |
case /^http:\/\/4koma\.livedoor\.com\/./.test(u):{ | |
xAppend(it, 'ld4koma-comments', u, | |
/<ul id="commentlist"[^]+?<!-- \/#commentList --><\/ul>/, | |
'euc-jp') | |
} break | |
// dankogai: get extras | |
case /^http:\/\/blog\.livedoor\.jp\/dankogai\/archives\b/.test(u):{ | |
xAppend(it, 'dankogai-comments', u, | |
/<div class="trackback-body"[^]+?(?=<form)/, | |
'euc-jp'); | |
} break; | |
}})} | |
function feedSettings(){ | |
doME('stream-prefs-menu', 'mousedown'); | |
} | |
function toggleExpandedOrListView(){ | |
click(ofClass('view-list', 'selected') ? 'view-cards' : 'view-list'); | |
} | |
function toggleSortByNewOrOlder(){ | |
doME('stream-prefs-menu', 'mousedown'); | |
var [sbn, sbo] = id('stream-prefs-menu-menu').children; | |
var b = ofClass(sbn, 'goog-option-selected') ? sbo.children[0] : sbn.children[0]; | |
doDU(b, b); | |
} | |
function showDetailedUnreadCount(){ | |
var e, s = 0, d = {}, x = document.evaluate( | |
['id("sub-tree")', | |
'li[contains(concat(" ",@class," ")," sub ")]', | |
'span[contains(concat(" ",@class," ")," unread-count ")]'].join('//'), | |
document, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null); | |
while((e = x.iterateNext())) d[e.innerHTML] = true; | |
for(var h in d) s += +/\d+/(h); | |
[[id('reading-list-unread-count'), 'innerHTML'], [document, 'title']].forEach( | |
function([o, p]){ o[p] = o[p].replace(/\d+\+?/, s) }); | |
} | |
function increaseColumn(){ addColumn(1) } | |
function decreaseColumn(){ addColumn(-1) } | |
function expandLinks(){ | |
withIt(function(it){ | |
Array.forEach(it.getElementsByTagName('a'), xpandLink); | |
}); | |
} | |
function id(x) typeof x === 'string' ? document.getElementById(x) : x; | |
function ofClass(elm, cls) !!~id(elm).className.search('\\b'+ cls +'\\b'); | |
function doME(lm, type){ | |
lm = id(lm); | |
var me = document.createEvent('MouseEvents'); | |
me.initMouseEvent(type, 1, 1, window, 1, 0,0, 0,0, 0,0,0,0, 0, null); | |
lm.dispatchEvent(me); | |
return lm; | |
} | |
function doKE(lm, type, key){ | |
lm = id(lm); | |
var ke = document.createEvent('KeyEvents') | |
ke.initKeyEvent(type, 1, 1, window | |
, key.ctrl, key.alt, key.shift, key.meta, key.code, key.char) | |
lm.dispatchEvent(ke) | |
return lm | |
} | |
function doDU(d, u) (doME(d, 'mousedown') && doME(u, 'mouseup') && | |
!document.activeElement.blur()); | |
function doMenu(menu, item){ | |
doME(menu, 'mousedown') | |
doME(item, 'mouseover') | |
doKE(menu, 'keypress', {code:13}) | |
} | |
function click(x) doME(x, 'click'); | |
function focus(x){ x.focus() } | |
function caret(x){ | |
x.ownerDocument.defaultView.getSelection().collapse(x, 0); | |
} | |
function withIt(f, it) (it = id('current-entry')) && f(it); | |
function withURL(f) withIt( | |
function(it) f(it.getElementsByClassName('entry-title-link')[0].href, it)); | |
var Style; | |
function style(css){ | |
(Style || (Style = document.body.appendChild( | |
document.createElement('style')))) | |
.appendChild(document.createTextNode(css +'\n\n')); | |
} | |
var CC = 1; | |
function addColumn(n){ | |
var c = CC + n; | |
if(c < 1 || 7 < c) return; | |
style('.item-body{-moz-column-count:'+ c +'}'); | |
CC += n; | |
} | |
function scrollEntries(rate){ | |
with(id('entries')) scrollTop += offsetHeight * rate; | |
} | |
function xGet(url, cb, charset) { | |
var options = {method: 'get', url: url, onload: cb}; | |
if (charset) options.overrideMimeType = 'text/html;charset=' + charset; | |
GM_xmlhttpRequest(options); | |
} | |
function xAppend(it, klass, url, cb, charset){ | |
if(it.getElementsByClassName(klass).length) return; | |
var div = document.createElement('div'); | |
div.className = klass; | |
div.innerHTML = '<i>...</i>'; | |
it.getElementsByClassName('item-body')[0].appendChild(div); | |
xGet(url.replace(/~/g, '%7E'), function(x){ | |
div.innerHTML = (cb.exec || cb).call(cb, x.responseText) || '<b>x</b>'; | |
}, charset); | |
} | |
function xpandLink(a){ | |
if(/^\s*https?:/.test(a.innerHTML)){ | |
xGet( | |
'http://api.longurl.org/v2/expand?format=json&title=1&url='+ | |
encodeURIComponent(a.href), | |
function(x){ | |
if(x.status == 200) | |
var {'long-url': url, title} = JSON.parse(x.responseText) | |
if(!url) return void(a.style.opacity = .8) | |
url = url.replace(/^http:\/+|[?&#]utm_\w+=.+/g, '') + a.hash | |
try { var du = decodeURIComponent(url) } catch(_){ du = url } | |
if(title) du = title +' <'+ du +'>' | |
maybeImg(a, url, du) | |
a.style.opacity = 1 | |
}) | |
a.style.opacity = .5 | |
} else maybeImg(a) | |
} | |
function maybeImg(a, url, els){ | |
if(/\.(?:jpe?g|gif|png)$/i.test(url || a.href)) | |
a.innerHTML = <img src={url}/>.toXMLString() | |
else if(els) | |
a.textContent = els | |
} | |
setTimeout(function(){ | |
const F = {}, C = 9, A = 10, M = 11, K = 1<<12 | |
, Modic = {C_:1<<C, A_:1<<A, M_:1<<M}; | |
function acc(n, k) n | (k.length === 1 && k.charCodeAt() || | |
Modic[k = k.toUpperCase()] || | |
KE['DOM_VK_'+ k] | K); | |
for(var k in Keys) F[k.match(/[CAM]_|.+/giy).reduce(acc, 0)] = Keys[k]; | |
document.addEventListener('keypress', function(e){ | |
with(e) if(/^(?!INPUT|TEXTAREA)/.test(target.nodeName)){ | |
var f = F[ctrlKey<<C | altKey<<A | metaKey<<M | (which || keyCode | K)]; | |
if(f) f(e) || preventDefault(stopPropagation()); | |
} | |
}, true); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment