Skip to content

Instantly share code, notes, and snippets.

@satyr
Created December 16, 2008 13:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save satyr/36459 to your computer and use it in GitHub Desktop.
Save satyr/36459 to your computer and use it in GitHub Desktop.
// ==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