Skip to content

Instantly share code, notes, and snippets.

@satyr
Forked from satyr/google-keynav.ubiq.js
Last active March 12, 2022 18:06
  • Star 3 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save satyr/60561 to your computer and use it in GitHub Desktop.
google++
Utils.extend(feed, {
title: 'google++',
author: {
name: 'satyr', email: 'murky.satyr\x40gmail.com',
homepage: 'http://satyr.github.com',
},
license: 'X',
})
const
Google = 'https://www.google.com/',
GImages = 'https://image.google.com/',
GVideos = 'https://video.google.com/',
GMail = 'https://mail.google.com/mail/',
GBooks = 'https://books.google.com/',
GTranslate = 'https://translate.google.com/',
GBookmarks = 'https://www.google.com/bookmarks/',
GLogos = Google +'logos/',
Googl = 'http://goo.gl/',
IFLHelp = Google +'support/websearch/bin/answer.py?answer=30735',
Icon = 'chrome://ubiquity/skin/icons/google.ico',
PPath = 'extensions.ubiquity.google.',
PLang = PPath +'lang',
PFrom = PPath +'from',
PLogo = PPath +'logo',
{escapeHtml: H, prefs: Prefs} = Utils,
CSS = `
body {position:relative; line-height:1.23}
li {margin-bottom:0.2em}
em {line-height:1.8}
a img {border:none; vertical-align:middle}
kbd {text-decoration:underline; margin:-1px 4px 0 1px}
input[type=button] {padding:0; border-width:1px; cursor:pointer}
input[type=button][disabled] {cursor:inherit}
input[type=button], kbd {font:bold 92% monospace}
input[type=button].active {background-color:transparent; color:inherit}
input[type=button].number[disabled] {text-decoration:underline}
h2 a[accesskey]::before, h3 a[accesskey]::before {
content:attr(accesskey); margin-right:0.2em; padding:0 2px;
font:bold 92% monospace; text-transform:uppercase;
border:1px solid; border-radius:4px}
.list {list-style:none; padding:0; margin:0}
.pagination {text-align:center; font-size:111%}
.marker {margin-right:3px; vertical-align:bottom}
.content {font-size:96%}
.error {font-style:oblique; line-height:1.8}
.logo {display:inline-block}
.logo, .logo > img {vertical-align:middle}
.loading {opacity:0.9}
.loading + .logo {opacity:0.4}
.error + .logo {opacity:0.7}
.cite {font-style:italic}
`,
CSSLogo = 'background-color:#fff;padding:4px 4px 0',
Langs = noun_type_lang_google._list
.reduce((o, s) => (o[s.text] = s.data, o), {'*': ''}),
Regions = kv2vk({'':'*',AF:'Afghanistan',AL:'Albania',DZ:'Algeria',AS:'American Samoa',AD:'Andorra',AO:'Angola',AI:'Anguilla',AQ:'Antarctica',AG:'Antigua and Barbuda',AR:'Argentina',AM:'Armenia',AW:'Aruba',AU:'Australia',AT:'Austria',AZ:'Azerbaijan',BS:'Bahamas',BH:'Bahrain',BD:'Bangladesh',BB:'Barbados',BY:'Belarus',BE:'Belgium',BZ:'Belize',BJ:'Benin',BM:'Bermuda',BT:'Bhutan',BO:'Bolivia',BA:'Bosnia and Herzegovina',BW:'Botswana',BV:'Bouvet Island',BR:'Brazil',IO:'British Indian Ocean Territory',VG:'British Virgin Islands',BN:'Brunei',BG:'Bulgaria',BF:'Burkina Faso',BI:'Burundi',KH:'Cambodia',CM:'Cameroon',CA:'Canada',CV:'Cape Verde',KY:'Cayman Islands',CF:'Central African Republic',TD:'Chad',CL:'Chile',CN:'China',CX:'Christmas Island',CC:'Cocos Islands',CO:'Colombia',KM:'Comoros',CG:'Congo - Brazzaville',CD:'Congo - Kinshasa',CK:'Cook Islands',CR:'Costa Rica',HR:'Croatia',CU:'Cuba',CY:'Cyprus',CZ:'Czech Republic',DK:'Denmark',DJ:'Djibouti',DM:'Dominica',DO:'Dominican Republic',EC:'Ecuador',EG:'Egypt',SV:'El Salvador',GQ:'Equatorial Guinea',ER:'Eritrea',EE:'Estonia',ET:'Ethiopia',FK:'Falkland Islands',FO:'Faroe Islands',FJ:'Fiji',FI:'Finland',FR:'France',GF:'French Guiana',PF:'French Polynesia',TF:'French Southern Territories',GA:'Gabon',GM:'Gambia',GE:'Georgia',DE:'Germany',GH:'Ghana',GI:'Gibraltar',GR:'Greece',GL:'Greenland',GD:'Grenada',GP:'Guadeloupe',GU:'Guam',GT:'Guatemala',GN:'Guinea',GW:'Guinea-Bissau',GY:'Guyana',HT:'Haiti',HM:'Heard Island and McDonald Islands',HN:'Honduras',HK:'Hong Kong SAR China',HU:'Hungary',IS:'Iceland',IN:'India',ID:'Indonesia',IR:'Iran',IQ:'Iraq',IE:'Ireland',IL:'Israel',IT:'Italy',CI:'Ivory Coast',JM:'Jamaica',JP:'Japan',JO:'Jordan',KZ:'Kazakhstan',KE:'Kenya',KI:'Kiribati',KW:'Kuwait',KG:'Kyrgyzstan',LA:'Laos',LV:'Latvia',LB:'Lebanon',LS:'Lesotho',LR:'Liberia',LY:'Libya',LI:'Liechtenstein',LT:'Lithuania',LU:'Luxembourg',MO:'Macau SAR China',MK:'Macedonia',MG:'Madagascar',MW:'Malawi',MY:'Malaysia',MV:'Maldives',ML:'Mali',MT:'Malta',MH:'Marshall Islands',MQ:'Martinique',MR:'Mauritania',MU:'Mauritius',YT:'Mayotte',MX:'Mexico',FM:'Micronesia',MD:'Moldova',MC:'Monaco',MN:'Mongolia',MS:'Montserrat',MA:'Morocco',MZ:'Mozambique',MM:'Myanmar',NA:'Namibia',NR:'Nauru',NP:'Nepal',NL:'Netherlands',AN:'Netherlands Antilles',NC:'New Caledonia',NZ:'New Zealand',NI:'Nicaragua',NE:'Niger',NG:'Nigeria',NU:'Niue',NF:'Norfolk Island',KP:'North Korea',MP:'Northern Mariana Islands',NO:'Norway',OM:'Oman',PK:'Pakistan',PW:'Palau',PS:'Palestinian Territory',PA:'Panama',PG:'Papua New Guinea',PY:'Paraguay',PE:'Peru',PH:'Philippines',PN:'Pitcairn',PL:'Poland',PT:'Portugal',PR:'Puerto Rico',QA:'Qatar',RE:'Reunion',RO:'Romania',RU:'Russia',RW:'Rwanda',SH:'Saint Helena',KN:'Saint Kitts and Nevis',LC:'Saint Lucia',PM:'Saint Pierre and Miquelon',VC:'Saint Vincent and the Grenadines',WS:'Samoa',SM:'San Marino',ST:'Sao Tome and Principe',SA:'Saudi Arabia',SN:'Senegal',YU:'Serbia',SC:'Seychelles',SL:'Sierra Leone',SG:'Singapore',SK:'Slovakia',SI:'Slovenia',SB:'Solomon Islands',SO:'Somalia',ZA:'South Africa',GS:'South Georgia and the South Sandwich Islands',KR:'South Korea',ES:'Spain',LK:'Sri Lanka',SD:'Sudan',SR:'Suriname',SJ:'Svalbard and Jan Mayen',SZ:'Swaziland',SE:'Sweden',CH:'Switzerland',SY:'Syria',TW:'Taiwan',TJ:'Tajikistan',TZ:'Tanzania',TH:'Thailand',TG:'Togo',TK:'Tokelau',TO:'Tonga',TT:'Trinidad and Tobago',TN:'Tunisia',TR:'Turkey',TM:'Turkmenistan',TC:'Turks and Caicos Islands',TV:'Tuvalu',VI:'U.S. Virgin Islands',UG:'Uganda',UA:'Ukraine',AE:'United Arab Emirates',GB:'United Kingdom',US:'United States',UM:'United States Minor Outlying Islands',UY:'Uruguay',UZ:'Uzbekistan',VU:'Vanuatu',VA:'Vatican',VE:'Venezuela',VN:'Vietnam',WF:'Wallis and Futuna',EH:'Western Sahara',YE:'Yemen',ZM:'Zambia',ZW:'Zimbabwe'}),
NewsEditions = kv2vk({au:'Australia',in:'India',en_il:'Israel',en_my:'Malaysia',nz:'New Zealand',en_pk:'Pakistan',en_ph:'Philippines',en_sg:'Singapore',ar_me:'\u0627\u0644\u0639\u0627\u0644\u0645 \u0627\u0644\u0639\u0631\u0628\u064A (Arab world)',ar_ae:'\u0627\u0644\u0625\u0645\u0627\u0631\u0627\u062A (UAE)',ar_lb:'\u0644\u0628\u0646\u0627\u0646 (Lebanon)',ar_sa:'\u0627\u0644\u0633\u0639\u0648\u062F\u064A\u0629 (KSA)',cn:'\u4E2D\u56FD\u7248 (China)',hk:'\u9999\u6E2F\u7248 (Hong Kong)',hi_in:'\u092D\u093E\u0930\u0924 (India)',ta_in:'\u0BA4\u0BAE\u0BBF\u0BB4\u0BCD (India)',ml_in:'\u0D2E\u0D32\u0D2F\u0D3E\u0D33\u0D02 (India)',te_in:'\u0C24\u0C46\u0C32\u0C41\u0C17\u0C41 (India)',iw_il:'\u05D9\u05E9\u05E8\u05D0\u05DC (Israel)',jp:'\u65E5\u672C (Japan)',kr:'\uD55C\uAD6D (Korea)',tw:'\u53F0\u7063\u7248 (Taiwan)',vi_vn:'Vi\u1EC7t Nam (Vietnam)',nl_be:'Belgi\xEB',fr_be:'Belgique',en_bw:'Botswana',de:'Deutschland',es:'Espa\xF1a',en_et:'Ethiopia',fr:'France',en_gh:'Ghana',en_ie:'Ireland',it:'Italia',en_ke:'Kenya',hu_hu:'Magyarorsz\xE1g',en_na:'Namibia',nl_nl:'Nederland',en_ng:'Nigeria',no_no:'Norge',de_at:'\xD6sterreich',pl_pl:'Polska','pt-PT_pt':'Portugal',de_ch:'Schweiz',fr_sn:'S\xE9n\xE9gal',en_za:'South Africa',fr_ch:'Suisse',sv_se:'Sverige',en_tz:'Tanzania',tr_tr:'T\xFCrkiye',en_ug:'Uganda',uk:'U.K.',en_zw:'Zimbabwe',ar_eg:'\u0645\u0635\u0631 (Egypt)',el_gr:'\u0395\u03BB\u03BB\u03AC\u03B4\u03B1 (Greece)',ru_ru:'\u0420\u043E\u0441\u0441\u0438\u044F (Russia)',ru_ua:'\u0423\u043A\u0440\u0430\u0438\u043D\u0430 (Ukraine)',uk_ua:'\u0423\u043A\u0440\u0430\u0457\u043D\u0430 (Ukraine)',es_ar:'Argentina','pt-BR_br':'Brasil',ca:'Canada English',fr_ca:'Canada Fran\xE7ais',es_cl:'Chile',es_co:'Colombia',es_cu:'Cuba',es_us:'Estados Unidos',es_mx:'M\xE9xico',es_pe:'Per\xFA',us:'U.S.',es_ve:'Venezuela'}),
NewsTopics = kv2vk({'':'Top Stories',ss:'Starred',w:'World',n:'U.S.',b:'Business',t:'Sci/Tech',e:'Entertainment',s:'Sports',m:'Health',ir:'Spotlight',po:'Most Popular'}),
NounSiteSearch = {
name: 'google site search',
label: 'site',
suggest: function gss_suggest(txt, htm, cb, sx){
if(sx || !(txt = txt.trim())) return [];
var paths = [], ltrim = /\/[^/]*$/, rtrim = /^[^.]*.?/, exact;
var [, site] = /^\w+:\/+([^?#]*)/.exec(CmdUtils.window.location) || [, ''];
while(site !== (site = site.replace(ltrim, '')) ||
(site = site.replace(rtrim, ''))){
if(site === txt) exact = true;
paths.push(CmdUtils.makeSugg(site));
}
var ss = CmdUtils.grepSuggs(txt, paths);
exact || ss.push(CmdUtils.makeSugg(txt, null, null, .25));
return ss;
},
},
NounRegion = CmdUtils.NounType('region', Regions)
NounRegion.noSelection = true
function GoogleCommand(u, o){
const [Name] = o.names || [o.name]
, Base =
'<style>'+ CSS + [o._css] +'</style>'+
'<div class="'+ Name +'">'+
'<div id="'+ Name +'"></div>'+
'<a class=logo href="'+ u +'" accesskey="/">'+ o._logo +'</a>'+
'</div>'
delete o._css
delete o._logo
o._content = function gcmd_content(pb, cb){
var cn
while(!(cn = pb.ownerDocument.getElementById(Name))){
pb.innerHTML = Base
cb && cb.call(this)
}
return cn
}
o.url = u
'execute' in o || (o.execute = '_url' in o ? execute : u)
'preview' in o || (o.preview = preview)
'icon' in o || (o.icon = Icon)
return CmdUtils.CreateCommand(o)
}
function execute(args){
Utils.openUrlInBrowser(this._url(args) || this._durl || this.url);
}
function preview(pb, args){
var cn = this._content(pb), u = this._url(args);
u && cjax(cn, {url: u, pry: this._pry, fix: this._fix});
}
function cjax(cn, opts){
var {url, dat, pry, fix, typ} = opts;
cn.className = 'loading';
return CmdUtils.previewAjax(cn.ownerDocument.body, {
url: url, data: dat || null, dataType: typ || 'text',
success: function g_success(res){
pry && ok(cn, pry(res));
fix && fix(cn, res, opts);
},
error: ngx(cn),
});
}
function pjax(o, pb){
return pb ? CmdUtils.previewAjax(pb, o) : $.ajax(o)
}
function tie(it, fn, me){
it && it.addEventListener('click', function tied(e){
var b = e.target;
if(b.type !== 'button') return;
e.preventDefault();
fn.call(me, kick(b));
}, false);
}
function kick(b){
b.disabled = true;
b.className += ' active';
return b;
}
function ok(c, it){
if(!it) return;
if(typeof it.jquery == 'string'){
c.innerHTML = '';
it.appendTo(c);
} else c.innerHTML = it;
c.className = '';
c.ownerDocument.defaultView.scrollTo(0, 0);
}
function ng(c){
c.textContent = Array.slice(arguments, 1).join(' ');
c.className = 'error';
}
function ngx(c){
return function g_erjax(x){ if(x.status) ng(c, x.status, x.statusText) }
}
function btn(klass, key, attrs){
var h = `<input type=button
class="${klass}" accesskey="${H(key)}" value="${H(key)}"`
for(let k in attrs) h += ` ${k}="${H(attrs[k])}"`
return h +'/>'
}
function params(args, xq){
var q = args.object.text.trim();
if(!q) return '';
if(xq) q = xq(q);
var site = (args.source || 0).text;
if(site) q += ' site:' + site
var ps = {
q,
start: 0,
hl: args.format .data || Prefs.get(PLang, ''),
gl: args.location.data || Prefs.get(PFrom, ''),
};
return ps;
}
function fdur(s){ return (s / 60 | 0) +':'+ (s % 60 + 100 + '').slice(-2) }
function qse(lm, sl, fn, me){
return Array.forEach(lm.querySelectorAll(sl), fn, me)
}
function ul(){
return '<ul><li>'+ Array.join(arguments, '</li><li>') +'</li></ul>'
}
function kv2vk(o){
for(var [k, v] in new Iterator(o)) delete o[k], o[v] = k;
return o;
}
function opener(u){ return () => Utils.openUrlInBrowser(u) }
function logosrc(name){ return Google +'images/logos/'+ name +'.gif' }
function logoimg(name){
return '<img style="'+ CSSLogo +'" src="'+ logosrc(name) +'">'
}
function destyle(lmn){
for(let l of lmn.querySelectorAll('[style]')) l.removeAttribute('style')
}
function unweblight(a){
var u = Utils.urlToParams(a.href).q || a.href
if(/^https?:\/\/googleweblight.com\/\?/.test(u))
u = Utils.urlToParams(u).lite_url
a.href = u
return a
}
const Doodle = {}
function loget(){
var d = Date.now()
if(d - loget.last < 20 * 6e4) return
loget.last = d
$.ajax({url: Google +'doodles/doodles.xml', dataType: 'xml', success: logot})
}
function logot(xml){
var dscs = xml.getElementsByTagName('description')
, num = dscs.length - 1
, i = 1 + num * Math.pow(Math.random(), 2) | 0
, $dsc = $(dscs[i].textContent.trim())
, img = $dsc.find('img')[0].cloneNode()
img.src = img.src.replace(/^\w*:?(?=\/\/)/, 'http:')
Doodle.img = img
Doodle.title =
xml.getElementsByTagName('title')[i].textContent +
$dsc.find('strong')[0].nextSibling.nodeValue
}
loget()
function GSearchCommand(top, {tbm, selector, names, description, list, css}){
var [Name] = names
, Style = '<style>'+ CSS + css +'</style>'
, Base =
'<div class="'+ Name +'"><div id="'+ Name +'"></div>'+
'<a class="logo" accesskey="/" href="'+ top +
'"><img src=https://www.google.com/images/logo.png height=80></a></div>'
CmdUtils.CreateCommand({
names,
description: description.link(top),
icon: Icon,
arguments: {
object: noun_arb_text,
format: noun_type_lang_google,
location: NounRegion,
source: NounSiteSearch,
},
execute: function gs_execute(args){
var ps = params(args), u = top
if(ps){
u = Google +'search'+ Utils.paramsToString(ps)
if(tbm) u += '&tbm='+ tbm
}
Utils.openUrlInBrowser(u)
},
preview: function gs_preview(pb, args){
var cn, ps = params(args)
while(!(cn = pb.ownerDocument.getElementById(Name))){
pb.innerHTML = Style + Base
let logo = pb.querySelector('.logo')
if(Prefs.get(PLogo, true)){
if(Doodle.img){
logo.innerHTML = ''
logo.appendChild(Doodle.img.cloneNode())
logo.title = Doodle.title
}
loget()
} else logo.style.display = 'none'
}
if(!ps) return
if(tbm) ps.tbm = tbm
var starts = []
, ojax = {
url: Google +'search',
data: ps,
headers: {
'User-Agent': 'DoCoMo/2.0 N01C(c500;TB;W24H17)',
},
success: function gs_success(htm, st, xhr){
var doc = xhr.responseXML
, nfo = doc.querySelector('#topbar + div:not([id])')
, rs = doc.querySelectorAll(selector)
, h = ''
if(nfo)
h += nfo.outerHTML
h += '<div class="pagination">'
if(ps.start)
h += btn('navi', '<')
if(rs.length)
h += `<b> ${ps.start + 1} ~ ${ps.start + rs.length} </b>`
if(xhr.responseXML.querySelector('#navbar > b'))
h += btn('navi', '>')
h += '</div><ul class="list">'
var i = -1, alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
for(let r of rs){
destyle(r)
h += list(r, ++i, alpha[i])
}
h += '</ul>'
ok(cn, h)
tie(cn.querySelector('.list'), b => {
Utils.openUrlInBrowser(b.getAttribute('url'))
})
tie(cn.querySelector('.pagination'), b => {
if(b.value == '<')
ps.start = starts.pop() || 0
else {
starts.push(ps.start)
ps.start += rs.length
}
ojax.data = ps
pjax(ojax, pb)
})
},
error: ngx(cn),
}
pjax(ojax, pb)
},
previewDelay: 0,
})
}
GSearchCommand(Google, {
names: ['google', '/'],
description: 'Google Web Search',
selector: '.web_result',
list: function g_list(wr, id, alpha){
var a = unweblight(wr.querySelector('a'))
, div = wr.children[1]
return `<li>${btn('marker', alpha, {id, url: a.href})}
${a.outerHTML + div.outerHTML}`
},
css: `
.logo[title]::after {
content:attr(title); display:inline-block; padding:0 2px;
position:absolute; bottom:1px; left:1px; z-index:2;
opacity:0.6; color:#fff; background-color:#666;
font:bolder smaller sans-serif; border-radius:6px}
`,
})
GSearchCommand(GImages, {
names: ['gimages', '|'],
description: 'Google Images',
tbm: 'isch',
selector: '.image',
list: function gi_list(a, id, alpha){
a.href = Utils.urlToParams(a.href).imgurl
a.children[0].removeAttribute('height')
return `<li>${btn('knob', alpha, {id, url: a.href})}${a.outerHTML}`
},
css: `
li {
display:inline-block; vertical-align:top; position:relative;
margin:0 1px 2px; padding:0; line-height:92%;
min-width:12%; max-width:49%}
.list {text-align:center; margin:2px 0}
.knob {position:absolute; top:0; left:0; opacity:0.7}
.knob[disabled] {display:none}
`,
})
GSearchCommand(GVideos, {
names: ['gvideos', '^'],
description: 'Google Videos',
tbm: 'vid',
selector: '.video_result',
list: function gv_list(vr, id, alpha){
var a = unweblight(vr.querySelector('a'))
return `<li>${btn('marker', alpha, {id, url: a.href})}
${vr.querySelector('img').outerHTML}${a.outerHTML}<br>
${vr.querySelector('.metadata').outerHTML}<br>
${vr.querySelector('.cite').outerHTML}`
},
css: `
li {clear:both}
.list img {float:right}
`
})
GoogleCommand(GMail, {
names: ['gmail', '@'],
icon: 'https://ssl.gstatic.com/ui/v1/icons/mail/images/favicon5.ico',
description: 'Checks/Opens/Composes '+ 'Gmail'.link(GMail) +'.',
help: 'Use the buttons to read, archive or mark-as-spam mails inline.',
arguments: {'object @': {
__proto__: noun_type_contact,
suggest: function ntc_hacked_suggest(t, h, c, s){
if(s && s[1] && t.length < 3) return
return noun_type_contact.suggest.apply(this, arguments)
},
}},
execute: function gmail_execute({object: {text: addr}}){
if(!addr) return void Utils.openUrlInBrowser(GMail +'#search/l:^u')
var {title, URL} = CmdUtils.document
Utils.openUrlInBrowser(GMail + Utils.paramsToString({
su: title, to: addr, body: this._txt(URL), fs:1, tf:1, view: 'cm',
}))
},
preview: function gmail_preview(pb){
var me = this, cn = this._content(pb, gmail_reset)
if(me._checked) return
me._checked = true
cn.className = 'loading'
$.ajax({
url: GMail +'feed/atom', dataType: 'text',
success: function gmail_success(atom){
var x = new DOMParser().parseFromString(atom, 'application/xml')
if(x.nodeName == 'parsererror') return ng(cn, 'Error parsing Atom.')
ok(cn, me._lst(x))
tie(cn.querySelector('dl'), me._act, me)
Utils.listenOnce(
context.chromeWindow.gUbiquity.panel, 'popuphidden', gmail_reset)
},
})
function gmail_reset(){ me._checked = false }
},
_txt: function gmail_txt(u){ return u +'\n\n'+ CmdUtils.getSelection() },
_lst: function gmail_lst(feed){
var num = +feed.querySelector('fullcount').textContent
if(!num) return '<em>No new mail.</em>'
var action = (val, act, key) =>
'<input type=button act='+ act +' accesskey='+ (key || '_') +
' value="'+ val + (key ? '['+ key +']': '') +'">'
var dl = '<dl>', i = 0
for(let e of feed.querySelectorAll('entry')){
let url = e.querySelector('link').getAttribute('href')
, kr = 'ABCDEFGHIJKL'[i] || '-'
, ka = 'MNOPQRSTUVWX'[i]
, ks = 'YZ1234567890'[i]
, author = e.querySelector('author')
, issued = e.querySelector('issued')
dl += '<div id="'+ H(/[?&]message_id=(\w+)/.exec(url)[1]) +'">'
+ '<dt><input type=button value='+ kr +' accesskey='+ kr +'>'
+ '<a class=title href="'+ H(url) +'">'
+ H(e.querySelector('title').textContent) +'</a></dt>'
+ '<dd>'
+ '<span class=author>'
+ '<a href="mailto:'
+ H(author.querySelector('email').textContent) +'">'
+ H(author.querySelector('name' ).textContent) +'</a>'
+ '<span class=issued>('
+ H(issued.textContent.replace(/[TZ]/g, ' ').trim()) +')</span>'
+ '</span>'
+ '<span class=actions>'
+ action('Archive', 'arch', ka)
+ action('Spam', 'sp', ks)
+ '</span>'
+ '<div class=summary>'
+ H(e.querySelector('summary').textContent) +'</div>'
+ '</dd></div>'
i++
}
return '<div class=fullcount><b>'+ num +'</b><span> new mail'+
(num > 1 ? 's' : '') +'</span></div>' + dl +'</dl>'
},
_act: function gmail_act(b){
var me = this
if(!me._at){
$.ajax({
url: GMail +'h/_/',
success: function(h){
me._at = /;at=([\w-]+)/.exec(h)[1]
me._act(b)
},
})
return
}
var $div = $(b).closest('div'), sm = $div.find('.summary')[0]
, {id} = $div[0], url = GMail +'h/_/', act = b.getAttribute('act')
if(act) $.post(url, {act: act, t: id, at: me._at})
, sm.style.display = 'none'
else $.get(url, {v: 'c', th: id}, function(h){
sm.style.opacity = 1
sm.innerHTML = '<div class=content>'+
/<div class=msg>[^]+?(?=<\/table>\s*<a name="m_")/.exec(h) +'</div>'
CmdUtils.absUrl(sm, url)
qse(sm, 'a', function(a){
if(a.hostname == 'www.google.com' && a.pathname == '/url')
a.href = Utils.urlToParams(a.search).q
if(a.accessKey)
a.removeAttribute('accesskey')
})
}, 'text'), sm.style.opacity = 0.5
},
_css: `
dt {margin-left:0}
dd {margin:0.5ex 0 1ex}
.fullcount {margin-left:0.7em; font-weight:bolder}
.title {margin-left:0.2em}
.actions {float:right}
.content {
background-color:rgba(255,255,255,0.8) !important;
padding:4px; border-radius:1ex}
.content *
{color:#000 !important; background-color:transparent !important}
.content *:-moz-any-link {color:#33c !important}
.content *:-moz-any-link:visited {color:#00a !important}
`,
_logo: '<img src="http://www.google.com/mail/help/images/logo1.gif">',
})
GoogleCommand(GBookmarks, {
name: 'gbookmarks',
description: 'Google Bookmarks'.link(GBookmarks) +' the current page.',
icon: GBookmarks +'api/static/images/favicon.ico',
arguments: {object_labels: noun_arb_text, instrument_notes: noun_arb_text},
execute: function gbms_execute({
object: {text: labels}, instrument: {text: notes}}){
var {title, URL} = CmdUtils.document, me = this
if(!URL) return
title = title || URL
$.ajax({
url: GBookmarks +'mark', dataType: 'text',
data: {op: 'edit', output: 'popup', bkmk: URL, title: title},
success: function gbms_success(h){
var [, sig] = /name=sig value="(\w+)"/.exec(h) || []
if(!sig) return displayMessage({
text: 'Failed to bookmark. Not logged in?',
onclick: opener(this.url),
}, me)
$.post(GBookmarks +'mark', {
sig: sig, bkmk: URL, title: title,
labels: labels, annotation: notes,
}, function gbms_post(){
displayMessage({
icon: me.icon, title: title, onclick: opener(GBookmarks),
text: URL + (labels && ' ['+ labels +']') + (notes && ' '+ notes),
})
})
},
error: function gbms_error(x) {
return x.status && displayMessage(x.status +' '+ x.statusText, me)
},
})
},
preview: function gbms_preview(pb, {
object: {text: labels}, instrument: {text: notes}}){
var {title, URL} = CmdUtils.document, cn = this._content(pb)
if(!URL) return void this.previewDefault(cn)
var htm = '<h3 class="title"><a href="'+ H(URL) +'">'+
H(title || URL) +'</a></h3>'
var lu = GBookmarks +'l#!view=threadsmgmt&fo=Starred&q=label:'
if(labels){
htm += '<div class=labels>'
for(let lbl of labels.split(',').filter(Boolean).map(String.trim))
htm += '<a href="'+ H(lu + encodeURIComponent(lbl)) +'">'+
H(lbl) +'</a>'
htm += '</div>'
}
if(notes) htm += '<div class=notes>'+ H(notes) +'</div>'
cn.innerHTML = htm
},
_css: '\
.title {margin:1ex 0.5em}\
.labels, .notes {padding:0 1em 1ex}\
.labels > a {\
dispaly:inline-block; border: 1px solid; border-radius:1em;\
margin-right:0.5em; padding:0 0.5em;\
}\
.logo {background-color:#fff; border-radius:32px}\
',
_logo: '<img src="'+ Google +'toolbar/ie/images/feature_bookmarks.gif">',
})
CmdUtils.CreateCommand({
name: 'gcache',
description: 'Opens the Google cache of a URL.',
icon: Icon,
argument: noun_type_url,
execute: function gcache_execute({object: {text}}){
Utils.openUrlInBrowser(
'http://webcache.googleusercontent.com/search?q=cache:'+
encodeURIComponent(text))
},
})
GoogleCommand(Googl, {
name: 'gshorten',
description: 'Shortens a URL with '+ 'goo.gl'.link(Googl) +'.',
argument: noun_type_url,
execute: function gsh_execute({object: {text: u}}){
if(!u) return
this._shorten(u, function gsh_e(s){
CmdUtils.copyToClipboard(s)
~CmdUtils.selection.indexOf(u) &&
CmdUtils.setSelection(Utils.escapeHtml(s), {text: s})
displayMessage(s +' \u2190 '+ u, this)
})
},
preview: function gsh_preview(pb, {object: {text: u}}){
var cn = this._content(pb)
if(!u || /^(?!https?:)/.test(u)) return ng(cn, '')
var hu = H(u)
ok(cn, '<pre class=old><a href="'+ hu +'">'+ hu +'</a></pre>')
this._shorten(u, function gsh_p(s){
if(s === cn.querySelector('a').textContent) return
var hs = H(s)
$('.old', cn).animate({opacity: .5})
$('<pre class=new style=display:none><a href="'+ hs +'">'+ hs +
'<br><br><img src="'+ hs +'.qr"></a></pre>')
.prependTo(cn).slideDown()
}, pb)
},
_shorten: function gsh_shorten(u, cb, pb){
if(u in this._bin) return cb.call(this, this._bin[u])
var me = this
pjax({
type: 'post',
url: 'https://www.googleapis.com/urlshortener/v1/url'+
'?key=AIzaSyDm4gPhS_JVPaUtujcTkTC9jDnHbTXaMaw',
data: JSON.stringify({longUrl: u}),
processData: false,
contentType: 'application/json',
dataType: 'json',
success: function gsh_ok(o){
return cb.call(me, me._bin[u] = o.id)
},
error: function gsh_ng(x) {
return x.status && displayMessage(x.status +' '+ x.statusText, me)
},
}, pb)
},
_bin: {__proto__: null},
_css: `
pre {text-align:center}
.logo {font:bold 150% fantasy; margin:1px 2px}
`,
_logo: logoimg('url_shortener_logo'),
})
CmdUtils.CreateCommand({
name: 'gplusone',
icon: Icon,
description: "+1 to current page.",
argument: noun_type_url,
execute: function gp1_execute(){
try {
var doc = this._doc.get()
doc.defaultView[0].document.getElementById('button').click()
} catch(e if e.name === 'TypeError'){
var error = 'failed to +1'
Utils.reportInfo(this.name +': '+ e)
}
displayMessage(error || doc._url, this)
},
preview: function gp1_preview(pb, {object: {text}}){
if(!text) return void this.previewDefault(pb)
pb.parentNode.removeChild(pb.ownerDocument.head)
var script = pb.ownerDocument.createElement('script')
pb.innerHTML = '<g:plusone size=tall>'
pb.firstChild.setAttribute('href', text)
script.src = 'https://apis.google.com/js/platform.js'
doc = pb.appendChild(script).ownerDocument
doc ._url = text
this._doc = Cu.getWeakReference(doc)
},
previewUrl: 'https://google.com/404',
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment