Google Search Extra Buttons

Add buttons (past 1/2/3 days, weeks, PDF search etc.) for Google search page

目前為 2018-11-30 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Google Search Extra Buttons
  3. // @name:ru GoogleSearchExtraButtons
  4. // @description Add buttons (past 1/2/3 days, weeks, PDF search etc.) for Google search page
  5. // @description:ru Кнопки вариантов поиска для страницы поиска Google (1-2-3 дня, недели, PDF, ...)
  6. // @version 32.2018.11.30
  7. // @namespace spmbt.github.com
  8. // @include http://www.google.*/search*
  9. // @include https://www.google.*/search*
  10. // @include https://www.google.*/*
  11. // @include https://encrypted.google.*/search*
  12. // @include https://encrypted.google.*/*
  13. // @include https://spmbt.github.io/googleSearchExtraButtons/saveYourLocalStorage.html
  14. // @include https://www.gstatic.com/sites/p/b9356d/system/services/test.html
  15. // @include https://www.gstatic.com/index.html
  16. // ==/UserScript==
  17. var xLocStI =0, xLocSto = [{origin:'https://spmbt.github.io', restHref:'/googleSearchExtraButtons/saveYourLocalStorage.html'},
  18. {origin:'https://www.gstatic.com', restHref:'/sites/p/b9356d/system/services/test.html', '//':'blank page'},
  19. {origin:'https://www.gstatic.com', restHref:'/index.html', '//':'404 page'}];
  20. // For use own eXternal LocalStorage add to array your origin+restHref of site with https protocol,
  21. // set xLocStI pointed to it, @include directive with this URL. If this script is Chrome extension, fill include_globs in manifest.json.
  22. // TODO If localStorage will be unavailable, script will be use next indexes of array.
  23. if(location.host == xLocSto[xLocStI].origin.replace(/[^/]*\/\//,'')){
  24. window.addEventListener('message', function(ev){
  25. if(/^https?:\/\/www\.google\./.test(ev.origin)){
  26. var d = typeof ev.data =='string' && ev.data[0] =='{' ? JSON.parse(ev.data) : ev.data;
  27. if(!d.do) return;
  28. var tok = d.tok, key = d.key; try{
  29. switch(d.do){
  30. case 'set':
  31. var prev = localStorage[key];
  32. if(d.val !==undefined)
  33. localStorage[key] = JSON.stringify(d.val);
  34. else
  35. localStorage.removeItem(key);
  36. break;
  37. case 'get':
  38. prev = localStorage[key];
  39. prev = prev === undefined || typeof prev =='string'&& prev[0] !='{'? prev : JSON.parse(prev); break;
  40. case 'remove':
  41. prev = localStorage[key];
  42. if(prev !==undefined)
  43. localStorage.removeItem(key);
  44. }} catch(er){}
  45. xLocStI !=0 && console.log('[xLocSto]', tok, 'prev=', prev);
  46. xLocStI !=0 && ev.source.postMessage(JSON.stringify(prev !==undefined ? {tok: tok, prev: prev} : {tok: tok, undef:1}), ev.origin);
  47. }},!1); console.log('[xLocSto-1]_'+ xLocStI);
  48. }else (function(setts){ //lang, sites, lastHoursLess
  49.  
  50. var $x = function(el, h){if(h) for(var i in h) el[i] = h[i]; return el;} //===extend===
  51. ,$pd = function(ev){ev.preventDefault();}
  52. ,d = document
  53. ,$q = function(q, el){return (el||d).querySelector(q)}
  54. ,lh = location.href
  55. ,$e = function(g,el){ //===create or use existing element=== //g={el|clone,cl,ht,cs,at,atRemove,on,apT}
  56. g.el = el || g.el || g.clone ||'DIV';
  57. var o = g.o = g.clone && g.clone.cloneNode && g.clone.cloneNode(!0)
  58. || (typeof g.el =='string' ? d.createElement(g.el) : g.el);
  59. if(o){ //execute if exist
  60. if(g.cl)
  61. o.className = g.cl;
  62. if(g.clRemove)
  63. o.classList.remove(g.clRemove);
  64. if(g.clAdd)
  65. o.classList.add(g.clAdd);
  66. if(g.cs)
  67. $x(o.style, g.cs);
  68. if(g.ht || g.at){
  69. var at = g.at ||{}; if(g.ht) at.innerHTML = g.ht;}
  70. if(at)
  71. for(var i in at){
  72. if(i=='innerHTML') o[i] = at[i];
  73. else o.setAttribute(i, at[i]);}
  74. if(g.atRemove)
  75. for(var i in g.atRemove)
  76. o.removeAttribute(g.atRemove[i]);
  77. if(g.on)
  78. for(var i in g.on) if(g.on[i])
  79. o.addEventListener(i, g.on[i],!1);
  80. g.ap && o.appendChild(g.ap);
  81. g.apT && g.apT.appendChild(o);
  82. }
  83. return o;
  84. },
  85. addRules = function(css){$e({apT: d.getElementsByTagName('head')[0], ap: d.createTextNode(css)},'style')},
  86. //check occurrence of third-party event with growing interval: h.t=time, h.i=count, h.c=check, h.o=occur, h.m=multi
  87. CS = function(h,d){d?h.o(d):h.i--&&setTimeout(function(){CS(h,h.c())},h.t*=h.m)} //example: t:120, i:12, m: 1.6 => wait around 55 sec
  88. //for xLocStor:
  89. ,xLocStorOrigin = d.location.protocol + xLocSto[xLocStI].origin.replace(/[^/]*/,'')
  90. ,qr, qrs ={} //set of queries "key-calls" (ок, toutLitt, toutLong, noService, noStorage)
  91. ,qrI = 0 //queries counter
  92. ,qrN = 12 //max number of waiting queries
  93. ,errIMax = 120, errNMax = errIMax //max number of errors
  94. ,ns ='googXButtons_' //namespace for keys
  95. ,listenMsg
  96. /**
  97. * external localStorage for using another domain if current domain storage is erased anywhere
  98. * @param{String} h.do - action: set|get|remove
  99. * @param{String} h.key
  100. * @param{Object|undefined} h.val (any type)
  101. * @param{Number|undefined} h.toutLitt
  102. * @param{Number|undefined} h.tout
  103. * @param{Function} h.cB - callback with 2 arguments
  104. * @param{Function|undefined} h.err - callback for err with one argument
  105. */
  106. ,xLocStor = function(h){
  107. var h0 = h;
  108. h.toutLitt = h.toutLitt || 400;
  109. h.tout = h.tout || 4000;
  110. var ifr = d.getElementById('xLocStor')
  111. ,query = function(){
  112. if((qrI += 1) > qrN){
  113. xCatch('longQrs', null, h);
  114. return;}
  115. ifr.contentWindow.postMessage(JSON.stringify($x({
  116. do: h.do
  117. ,tok: token
  118. ,key: ns + h.key
  119. }, h.val !==undefined ? {val: h.val}:{}) )
  120. , xLocStorOrigin);
  121. qrs[token] = $x({ //for wait of response
  122. wToutLitt: (function(h, qrI, errIMax){return setTimeout(function(){
  123. qrI -= 1;
  124. if((errIMax -= 1) >=0)
  125. ;//console.warn('toutLitt', h);
  126. chkErrMax();
  127. }, h.toutLitt);})(h, qrI, errIMax)
  128. ,wTout: (function(h, qrI){return setTimeout(function(){
  129. qrI -= 1;
  130. //xCatch('tout', null, h);
  131. //xLocStor(h0);
  132. }, h.tout);})(h, qrI)
  133. }, h);
  134. }
  135. ,token = +new Date() + (Math.random()+'').substr(1,8)
  136. ,el = h.el;
  137. delete h.el;
  138. if(ifr) query();
  139. else ifr = $e({
  140. el: 'iframe',
  141. at:{id: 'xLocStor'
  142. ,src: xLocStorOrigin + xLocSto[xLocStI].restHref},
  143. cs: {display: 'none'},
  144. on: {load: query},
  145. apT: el || d.body
  146. });
  147. if(!listenMsg) addEventListener('message', function(ev){
  148. if(ev.origin == xLocStorOrigin){ // {"tok":"<value>"[,"err":"<txt>"],"h":...}
  149. //console.log('from_io', JSON.parse(ev.data))
  150. var resp = ev.data && ev.data[0] =='{' && JSON.parse(ev.data);
  151. if(!resp) xCatch('bad_format', resp, h);
  152. if(( qr = qrs[resp.tok] )){
  153. qrI -= 1;
  154. qr.cB(resp.prev, resp.undef);
  155. var er = qr.err;
  156. delete qrs[resp.tok];} // else ignore unsufficient token
  157. if(resp.err && (!er || er(resp.err)) ) //individual or common error processing depends of er()
  158. xCatch(resp.err, resp, h);
  159. }},!1);
  160. listenMsg =1;
  161. },
  162. //for tests: localStorage.googXButtons_dwmyh = JSON.stringify({h:[1,2,1,1,1]})
  163. //$('#xLocStor').contentWindow.postMessage('{"do":"get","key":"googXButtons_dwmyh"}',xLocSto[xLocStI].origin)
  164. xCatch = function(er, resp, h){
  165. if((errIMax -= 1) >=0)
  166. console.error('tok:', resp && resp.tok ||'--','; err:', er,'; h:', h,'; respH:', resp && resp.h);
  167. chkErrMax();
  168. },
  169. chkErrMax = function(){if(!errIMax) console.error('Too many err messages:', errNMax)}
  170. ,fileType ='PDF,DOC,RTF,ODF,XLS,ODS,PPT,ODP,TXT,XML,More..., KML,DWF,PS,WPM,BAS,C,CC,CPP,CXX, Java,PL,PY,H,HPP,CS'
  171. .split(/,\s*/).map(function(x){return '&nbsp; '+x+'&nbsp; '})
  172. ,isFTMore =0
  173. ,$l ={ru:{
  174. 'search in PDF files':'поиск по документам PDF'
  175. ,'search in':'искать по'
  176. ,'from / to':'за период'
  177. ,'past':['за последний','за последние','за последнюю']
  178. ,'day':'сутки'
  179. ,'days':['дня','дней']
  180. ,'week':'неделю'
  181. ,'weeks':['недели','недель']
  182. ,'month':'месяц'
  183. ,'months':['месяца','месяцев']
  184. ,'year':'год'
  185. ,'years':['года','лет']
  186. ,'hour':'час'
  187. ,'hours':['часа','часов']
  188. ,'Settings':'Настройки'
  189. ,'of userscript':'юзерскрипта'
  190. ,'reload page for effect':'перезагрузить страницу'
  191. ,'Interface language':'Язык интерфейса'
  192. ,'Less positions at the end of selects':'Меньше выбора в конце селектов'
  193. ,'Gray design of buttons':'Серый дизайн кнопок'
  194. ,'Sites':'Сайты'
  195. },fr:{
  196. 'search in PDF files':'la recherche dans les fichiers PDF'
  197. ,'search in':'rechercher dans'
  198. ,'from / to':'pour la période'
  199. ,'past':['le dernier','dans les derniers','dans les derniers']
  200. ,'day':'jour'
  201. ,'days':['jours','jours']
  202. ,'week':'semaine'
  203. ,'weeks':['semaines','semaines']
  204. ,'month':'mois'
  205. ,'months':['mois','mois']
  206. ,'year':'an'
  207. ,'years':['ans','ans']
  208. ,'hour':'heure'
  209. ,'hours':['heures','heures']
  210. ,'Settings':'Paramètres'
  211. ,'of userscript':'de Userscript'
  212. ,'reload page for effect':'recharger la page pour effet'
  213. ,'Interface language':'Langue de l\'interface'
  214. ,'Less positions at the end of selects':'Moins de choix les longues listes'
  215. ,'Gray design of buttons':'Gris design des boutons'
  216. ,'Sites':'Les sites'
  217. },de:{
  218. 'search in PDF files':'Suche in PDF-Dateien'
  219. ,'search in':'Suche in'
  220. ,'from / to':'im Zeitraum'
  221. ,'past':['letzte','letzte','letzte']
  222. ,'day':'Tag'
  223. ,'days':['Tage','Tage']
  224. ,'week':'Woche'
  225. ,'weeks':['Wochen','Wochen']
  226. ,'month':'Monat'
  227. ,'months':['Monate','Monate']
  228. ,'year':'Jahr'
  229. ,'years':['Jahre','Jahre']
  230. ,'hour':'Stunde'
  231. ,'hours':['Stunden','Stunden']
  232. ,'Settings':'Einstellungen'
  233. ,'of userscript':'von Userscript'
  234. ,'reload page for effect':'Seite neu laden'
  235. ,'Interface language':'Sprache'
  236. ,'Less positions at the end of selects':'Weniger Auswahl in langen Listen'
  237. ,'Gray design of buttons':'Graues Design der Schaltflächen'
  238. ,'Sites':'Websites'
  239. },es:{
  240. 'search in PDF files':'búsqueda en archivos PDF'
  241. ,'search in':'busca en'
  242. ,'from / to':'para el período'
  243. ,'past':['el último','en los últimos','en los últimos']
  244. ,'day':'día'
  245. ,'days':['días','días']
  246. ,'week':'Semana'
  247. ,'weeks':['semanas','semanas']
  248. ,'month':'mes'
  249. ,'months':['meses','meses']
  250. ,'year':'año'
  251. ,'years':['años','años']
  252. ,'hour':'hora'
  253. ,'hours':['horas','horas']
  254. ,'Settings':'Ajustes'
  255. ,'of userscript':'de userscript'
  256. ,'reload page for effect':'página para efecto de recargar'
  257. ,'Interface language':'Idioma de interfaz'
  258. ,'Less positions at the end of selects':'Menos elección en listas largas'
  259. ,'Gray design of buttons':'Diseño gris de botones'
  260. ,'Sites':'Sitios'
  261. }},cB; //if !lang, then no hints
  262. addRules('.hp .sfsbc,.sfsbc{display: inline-block}.siteList:hover button{display: block}'
  263. +'.gb_Ib >.gb_e{height:47px}.gb_Fb{z-index:1087}.tsf-p{z-index:203}'
  264. +'.lsbb .xButt,.sbibod .xButt,.lsbb >.siteList,.sbibod >.siteList{z-index: 2002; width:34px; height:17px;'
  265. +'padding:0 2px; line-height:14px; font-size:14px; border:1px solid transparent; border-radius:2px;'
  266. +'background-color:#dddae6; color:#eee; opacity: .07; transition: opacity .57s ease-in}'
  267. +'.lsbb .xButt:not(.xButt2),.sbibod .xButt:not(.xButt2),.lsbb >.siteList{text-align: center; background-color:#4889f1; color:#fff; opacity: 0.75}'
  268. +'.xButt2{padding:0 0 2px; background-color:#dad6e2; color:#eee; opacity: 1}'
  269. +'.lsbb .xButt:hover,.sbibod .xButt:hover,.xButt.xButt2:hover .xButt2,.xButt2:hover{background-color:#c3d4e1; color:#fff; opacity:1}'
  270. +'.sbibod .xButt:hover,.sbibod .xButt2:hover,.sbibod .xButt:hover .xButt2{background-color:#c3c6c7}.lsbb >.siteList:hover{background-color:#4889f1}'
  271. +'.lsbb >.siteList,.sbibod >.siteList{width:32px; height:auto; padding:1px 0 2px; text-align:center}'
  272. +'.lsbb >.siteList .lsb,.sbibod >.siteList .lsb{font-weight: normal; color:#d4d4d4}'
  273. +'.lsbb .lsb:hover,.sbibod .lsb:hover{opacity: 1; color: #987b2b; cursor:default}'
  274. +'.sbibod >.siteList:hover,.lsbb >.siteList >div:not([class]):hover{background-color:#c2d4e0; color: #f7f7f7; opacity:.93}'
  275. +'.lsbb > .siteList > div:not([class]):hover span{color: #aa6c1c}'
  276. +'.sbibod:not(.lsbb) >.siteList, .sbibod:not(.lsbb) > .xButt2{background-color:#dddae6; opacity:.45}'
  277. +'.sbibod:not(.lsbb) >.siteList:hover, .sbibod:not(.lsbb) > .xButt2:hover{background-color:#dddae6; opacity:.87}'
  278. +'.sbibod.lsbb{height:44px}'
  279. +'.sbibod >.siteList >.list{background-color:#e1deeb}.list .more ~ .xButt{display:none!important}'
  280. +'.sbibod >.siteList.fade:hover{opacity: 1; transition: opacity .1s ease-in}'
  281. +'.sbibod >.siteList.fade{opacity: 0.23}'
  282. +'.siteList .sett .txt{padding:2px 2px 4px; font-size: 14px}'
  283. +'.lsbb >.siteList .sett .txt{background-color:#4889f1}'
  284. +'.siteList .settIn{display: none; width: 250px; padding: 2px 4px; text-align:left; border:1px solid #48f; font-size: 14px;'
  285. +'background-color:#eef; color:#336}'
  286. +'.siteList .settIn hr{margin:2px 0}'
  287. +'.sbibtd .sfsbc .nojsb, .siteList .sett:hover .settIn, .siteList .settIn.changed,'
  288. +'.siteList .settIn.changed .reload{display: block}.siteList .settIn .reload, .siteList.hiddn{display: none}'
  289. +'div.gb_g[aria-label="promo"],.pdp-psy.og-pdp, .gb_Sc.gb_g .gb_ha, .gb_g.gb_ha:not(.xpdopen ){display: none}'
  290. +'.xpdopen{display: block!important}.rhsvw{opacity:.16; transition:.4s}.rhsvw:hover{opacity:1}'
  291. +'.srp #sfdiv{overflow: inherit}' //hide promo
  292. +'.UUbT9 >div.aajZCb{background-color: rgba(255, 255, 255, 0.7);}' //opacity for suggests
  293. +'.UUbT9 ul li div span b{background-color: rgba(237, 242, 248, 0.9); margin: 0 -6px 0 -1px; padding: 0 6px 0 1px;}'); //white under suggest texts
  294. console.log('==cB-00');
  295. try{xLocStor({do:'get', key:'sett', val:setts, cB: cB=function(prev,undef){
  296. console.log('==cB-0');
  297. S = prev || setts;
  298. S.dwmyh = S.dwmyh || setts.dwmyh; //temp. transitional expr.
  299. console.timeStamp = function(){};
  300.  
  301. CS({t:120, i:12, m: 1.6
  302. ,c: function(){
  303. return d && d.getElementsByName('q') && d.getElementsByName('q')[0];
  304. },
  305. o: function(dat){
  306. var lang = S.lang != null ? S.lang : setts.lang
  307. ,sites = S.sites && (S.sites.length && S.sites[0] || S.sites.length >1) && S.sites
  308. || typeof sites =='string'&& [sites] || !S.sites && setts.sites || null;
  309. var strSites = sites && sites.join('\n').replace(/^\n/,'\n\n') ||''
  310. ,$L = $l[lang] || $l.ru; //default template of lang
  311. if(!lang || !$l[lang] || lang =='en') for(var l in $L){ //replace 'en' lang for default or substitution
  312. if($L[l] instanceof Array) for(var l2 in $L[l])
  313. $L[l][l2] = l;
  314. else
  315. $L[l] = l;
  316. }
  317. var $LSettings = $L['Settings'];
  318. if(sites && sites.length)
  319. sites.push($LSettings)
  320. var mainPg = /\/search\?|&q=|#q=/.test(lh)
  321. ,inputSearch = dat
  322. ,layout1811 = $q('.Tg7LZd') || $q('button[aria-label="Google Search"]')
  323. ,design1612 = ($q('#_fZl') || $q('.sbico-c')) && !layout1811
  324. ,d16 = (design1612 || layout1811) && S.design1612
  325. ,buttSearch = d.getElementsByName("btnG") && d.getElementsByName('btnG')[0] || design1612 || layout1811
  326. ,buttS ={
  327. Srch:{url:'', txt:'search'}
  328. ,PDF:{url:'filetype:PDF', txt:$L['search in PDF files']}
  329. ,site:{url:'site:'+ S.sites[0], txt:$L['search in']+' '+ S.sites[0], one:'day'} //you may comment this line
  330. ,'.. : ..':{url:'', txt:$L['from / to']}
  331. ,'1D':{url:'&tbs=qdr:d', txt:$L['past'][1] +' '+ $L['day'], one:'day', up:13,lett:'D'}
  332. ,'1W':{url:'&tbs=qdr:w', txt:$L['past'][2] +' '+ $L['week'], one:'week', up:14,lett:'W'}
  333. ,'1M':{url:'&tbs=qdr:m', txt:$L['past'][0] +' '+ $L['month'], one:'month', up:20,lett:'M'}
  334. ,'1Y':{url:'&tbs=qdr:y', txt:$L['past'][0] +' '+ $L['year'], one:'year', up:10,lett:'Y'}
  335. ,'1H':{url:'&tbs=qdr:h', txt:$L['past'][0] +' '+ $L['hour'], one:'hour', up:23,lett:'H'}
  336. }, ii = 0, iD = -1;
  337. if((design1612 || layout1811) && !d16)
  338. buttSearch.parentNode.className +=' lsbb';
  339. !sites && delete buttS.site;
  340. buttSearch.parentNode.style.position ='relative';
  341. buttSearch.parentNode.style.zIndex ='1003';
  342. if(buttSearch && top == self) for(var i in buttS) if(i !='site'|| S.sites){ //buttons under search input line
  343. if(i.length ==2) iD++; else iD=-1;
  344. var bI = buttS[i]
  345. ,Gesch = ({m:'letzter',f:'letzte',n:'letztes'})['m,f,m,n,f'.split(',')[iD]]
  346. ,hint = function(j){return (j+1) +' '+ (j % 10 || j==10 ? $L[bI.one +'s'][j % 10 <4 && (j/10|0)!=1 ?0:1] : $L[bI.one]) }
  347. ,csLeft = function(ii,a){a = -127 + 37 * (ii-1 - (ii >2 && !mainPg)); return design1612 || layout1811 ?{right: -a+33+'px'}:{left: a+'px'}}
  348. ,butt2 = $e({clone: i =='site'|| i.length ==2 || i=='PDF'
  349. ? $e({cl: 'siteList', cs: {cursor:'default'}, at: {site: S.sites[0], date: bI.url} })
  350. : i !='.. : ..'|| mainPg ? $e({el:'button', cl: 'xButt ' +(d16 ?'xButt2':'lsb')}) : $e({cl: 'siteList hiddn'})
  351. ,at: {value: iD !=-1 && S.dwmyh[iD] !=1 ? S.dwmyh[iD] + bI.lett : i
  352. ,innerHTML: '<div'+ (d16 ?' class=xButt2':'') +'><span class=txt onclick=this.parentNode.click();return!1 title="'
  353. +(lang || i=='site'|| i=='.. : ..'
  354. ? (iD==-1 || S.dwmyh[iD]==1 ? bI.txt : $L['past'][1] +' '+ hint(S.dwmyh[iD]-1)).replace(/letzte/,Gesch) :'')
  355. +'" itrvNum="'+ (i=='site'?'': bI.url + S.dwmyh[iD]) +'">'
  356. +(iD !=-1 && S.dwmyh[iD] !=1 ? S.dwmyh[iD] + bI.lett : i) +'</span></div>'}
  357. ,cs: $x({position:'absolute', top:'33px',wordSpacing:'-1px'}, csLeft(++ii))
  358. ,on: {click: (function(bI, i, iD){
  359. //console.log('clic0:', i, iD);
  360. return /Srch|PDF|DOC|site/.test(i)
  361. ? function(ev){
  362. var t = ev.target;
  363. console.log('cli-DocSite:',i,bI,ev, t.className, inputSearch.value, this.form, ',' +
  364. ' attr: ', t.getAttribute('site'), $LSettings, t.parentNode.getAttribute('site'), t.value);
  365. if(t.className =='defa')
  366. saveLocStor('','','remove'); $pd(ev);
  367. if((t.getAttribute('site')==$LSettings || t.parentNode.getAttribute('site')==$LSettings)
  368. && !/Srch|PDF|DOC/.test(i)) return;
  369. inputSearch.value = (inputSearch.value||'')
  370. //.replace(/ site\:[\w.]*$/ig, function(a){return i=='Srch'? a :''})
  371. .replace(/( site(:|%3A)\s*\S*|$)/ig, /Srch|site/.test(i)?'':'$1')
  372. .replace(/( |\+|&as_)filetype(:|%3A)[^\&]*/g,'') +' '+ (/Srch|PDF|DOC/.test(i) ? bI.url
  373. : 'site:'+ (t.getAttribute('site')|| t.parentNode.getAttribute('site')||''));
  374. if(t.getAttribute('site') ==null && t.parentNode.getAttribute('site') ==null && !/Srch|PDF|DOC/.test(i))
  375. return;
  376. if(/xButt|txt/.test(t.className) && !(i=='site'&& !(/list/.test(t.parentNode.className)
  377. || /list/.test(t.parentNode.parentNode.className))) || /Srch|PDF|DOC/.test(t.value))
  378. buttSearch.click();
  379. }: !bI.url ? function(ev){ //from-to date
  380. var el = $q('#cdrlnk'), o;
  381. el && el.dispatchEvent(((o = d.createEvent('Events')).initEvent('click', !0, !1), o));
  382. $pd(ev);
  383. }: function(ev){ //past interval
  384. var t = ev && ev.target, sbd = /,sbd:1/.test(lh), ta = t
  385. ,tOvr = t && t.parentNode, tOv0 = tOvr
  386. ,date2 = tOvr.getAttribute('date');
  387. console.log('cli-Past:','/search?q='+ encodeURIComponent(inputSearch.value) +(date2 ||''),
  388. tOvr.className+','+t.className, tOvr.classList.contains('siteList'), t.classList.contains('list'));
  389. /* +((t.getAttribute('date') || t.parentNode.getAttribute('date'))
  390. + (t.value || t.parentNode.value).replace(/\D/g,'') || bI.url) );
  391. var locationhref = '/search?q='+ encodeURIComponent(inputSearch.value)
  392. +(tOvr.getAttribute('date')
  393. + tOvr.value.replace(/\D/g,'') || bI.url)
  394. +(/tbs=\w+(:|%3A)\w+(,|%2C)sbd(:|%3A)1/.test(lh) ?',sbd:1':'') //save "sort by date" option
  395. +(/[&?]tbm=/.test(lh) ? '&'+/tbm=[^&]* /.exec(lh)[0]:''); //saving type of page*/
  396. if(tOvr.classList.contains('siteList') && !ta.classList.contains('list')){ //clicked by top button
  397. var elTop = $q('div:not(.list) >.txt', tOvr) ||''
  398. ,itrvNum = elTop && elTop.getAttribute('itrvNum') ||''
  399. ,newSrch = lh.replace(/(&|\?)q=([^&]+)(&|$)/g,'$1q='+ encodeURIComponent(inputSearch.value) +'$3');
  400. if(layout1811 && itrvNum !=='') location.href = /qdr(:|%3A)([dwmyh])\d*/.test(lh)
  401. ? newSrch.replace(/qdr(:|%3A)[dwmyh]\d*/, itrvNum)
  402. : newSrch + (/\?/.test(newSrch) ?'&':'?') + itrvNum;
  403. if(itrvNum != null) S.dwmyh[iD] = +(itrvNum ||'').replace(/\D/g,'');
  404. }else if(t.textContent || tOv0.textContent){
  405. var sa = (t.textContent || tOv0.textContent ||'').replace(/\D/g,'');
  406. if(sa.length <=6)
  407. S.dwmyh[iD] = +sa;
  408. }
  409. //console.log('==noDocNoSite', tOvr.value, itrvNum);
  410. $pd(ev);
  411. ev.stopPropagation();
  412. saveLocStor();
  413. }
  414. })(bI, i, iD),
  415. mouseover: i =='site' || i.length ==2 || i=='PDF' ? (function(bI,i){return function(ev){
  416. clearTimeout(bI.ww);
  417. var t = ev.currentTarget;
  418. t.classList.add('fade');
  419. $q('.list', t).style.display ='block';
  420. }})(bI,i) :'',
  421. mouseout: i =='site' || i.length ==2 || i=='PDF' ? (function(bI,i){return function(ev){
  422. var t = ev.currentTarget;
  423. clearTimeout(bI.ww);
  424. bI.ww = setTimeout(function(){
  425. $q('.list',t).style.display ='none';
  426. t.classList.remove('fade');
  427. }, 570);
  428. }})(bI,i) :'',
  429. change: saveLocStor
  430. }
  431. ,apT: buttSearch.parentNode
  432. });
  433. bI.el = butt2;
  434. if(i =='site' || i.length ==2 || i =='PDF'){ //dropdown lists under some buttons
  435. var siteList = $e({cl:'list',cs:{display:'none'}, apT: butt2}), arr =[];
  436. for(var j =0; j <= bI.up -1 -(i=='1W'&& S.lastHoursLess ?4:0) -(i=='1M'&& S.lastHoursLess ?9:0); j++)
  437. if(i !='1H' || !S.lastHoursLess || j < 8 || j % 2 )
  438. arr.push(hint(j));
  439. //console.log(S.sites,i, S.dwmyh);
  440. var list = i=='site' ? sites||[] : i =='1D'&& !sites ? arr.concat([$LSettings])
  441. : i=='PDF'? fileType : arr;
  442. for(var j in list) if(j !=0 || iD!=-1 && S.dwmyh[iD] !=1){
  443. //console.log('==i,sI', i, sI);
  444. var sI = list[j]
  445. ,fTyp = sI.replace(/&nbsp; ?/g,'')
  446. ,fTMore = /More\.\.\./.test(fTyp)
  447. ,butt3 = $e({clone: sI==$LSettings
  448. ? $e({cl: 'sett' +(d16 ?' xButt xButt2':' lsb')})
  449. : $e({el:'button', cl: 'xButt' +(d16 ?' xButt2':' lsb') +(fTMore ?' more':'')})
  450. ,at:{value: sI
  451. ,site: sI
  452. ,date: bI.url.replace(/pdf$/i, fTyp)
  453. ,title: sI==$LSettings || !lang ?'':(/site|PDF/.test(i)
  454. ? ($L[i=='PDF'?'search in PDF files':'search in'] +(i=='PDF'?'':' '+ sI)).replace(/PDF/,fTyp)
  455. : j==0 ? bI.txt : $L['past'][1] +' '+ sI).replace(/letzte/,Gesch)
  456. ,innerHTML:'<span class=txt>'+ sI +'</span>'+ (sI != $LSettings &&!(!S.sites && i =='1H')
  457. ?'':'<div class="settIn">'
  458. +$L.Settings +' '+ $L['of userscript'] +'<br/>"Google Search Extra Buttons"<hr/>'
  459. +$L['Interface language'] +': <select class="lang" style="width:70px">'
  460. +(function(){var s='<option'+ (lang=='en'?' selected':'') +'>en</option>';
  461. for(var i in $l)
  462. s+='<option'+ (lang==i ?' selected':'') +'>'+ i +'</option>';
  463. return s +'<option value=""'+ (lang==''?' selected':'') +'>en w/o hints</option>'})()
  464. +'</select><br/>'
  465. +'<input type="checkbox" class="less" id="hoursLess"'+ (S.lastHoursLess ?' checked':'') +'/>'
  466. +'<label for="hoursLess" id="hoursLessL">'+ $L['Less positions at the end of selects'] +'</label><br/>'
  467. +'<input type="checkbox" class="des16" id="design1612"'+ (!layout1811 && S.design1612 ?' checked':'')+ (layout1811 ?' disabled':'') +'/>'
  468. +'<label for="design1612" id="design1612L">'+ $L['Gray design of buttons'] +'</label><br/>'
  469. +'<i><a href="#" class="defa" style="float: right">Default settings</a></i>'
  470. +$L.Sites +': <br/><textarea class="sites" style="width:97%" rows=8>'
  471. + strSites +'</textarea><br/>'
  472. +'<a class="reload" href=# onclick="location.reload();return!1">'
  473. + $L['reload page for effect'] +'</a>'
  474. +'</div>')}
  475. ,cs: Object.assign({position: (sI != $LSettings || design1612 || layout1811)&& !fTMore ?'static':'absolute',display:'block'
  476. ,width: sI != $LSettings ?'auto': /en|es/.test(lang)||!lang ?'4em':'6.2em'
  477. ,height: sI != $LSettings ?'18px':'16px',margin:'2px 0 -1px -13px', padding:'0 2px 0 1px'
  478. ,textAlign:'left', fontWeight:'normal', opacity:1, whiteSpace:'nowrap'}, fTMore ?{top:'1.8em',left:'47px'}:{})
  479. ,on:{click: (function(fTyp,pdf,fTMore){return function(ev){
  480. var less = $q('#hoursLess')
  481. ,des16 = $q('#design1612') && !layout1811, t = ev.target
  482. ,itrv = t.getAttribute('date')||t.parentNode.getAttribute('date')||''
  483. ,num = (t.getAttribute('site')||t.parentNode.getAttribute('site')||'').replace(/\D/g,'');
  484. console.log('==clic3:t,itrv,num,fTyp,pdf:',t, itrv, num,'|',fTyp,pdf);
  485. if(less && /hoursLess/.test(t.id)){
  486. less.outerHTML = '<input type="checkbox" class="less" id="hoursLess"'
  487. +(less.getAttribute('checked')!=null ?'':' checked="checked"')+'/>';
  488. saveLocStor();}
  489. if(des16 && /design1612/.test(t.id)){
  490. des16.outerHTML = '<input type="checkbox" class="des16" id="design1612"'
  491. +(des16.getAttribute('checked')!=null ?'':' checked="checked"')+'/>';
  492. saveLocStor();}
  493. if(pdf) inputSearch.value = inputSearch.value.replace(/ filetype(:|%3A)\s*\S*|$/, fTMore ?'': ' '+ itrv);
  494. console.log('==inputSearch.value', inputSearch.value, fTyp);
  495. var newSrch = lh.replace(/(&|\?)q=([^&]+)(&|$)/g,'$1q='+ encodeURIComponent(inputSearch.value) +'$3');
  496. if(layout1811 && num !==''|| pdf) {pdf && ev.stopPropagation();
  497. if(!fTMore) location.href = /qdr(:|%3A)([dwmyh])\d*/.test(lh)
  498. ? newSrch.replace(/qdr(:|%3A)[dwmyh]\d*/, pdf ?'': itrv + num)
  499. : newSrch + (/\?/.test(newSrch) ?'&':'?') + (pdf ?'': itrv + num);
  500. else
  501. t.classList.toggle('more');
  502. }
  503. $pd(ev);
  504. }})(fTyp,i=='PDF',fTMore)}//, mouseover: function(ev){ev.stopPropagation()}, mouseout: function(ev){ev.stopPropagation()}
  505. ,apT: siteList
  506. });}
  507. siteList.style.height ='auto'; siteList.style.textAlign ='center';
  508. }
  509. }
  510. }
  511. });
  512.  
  513. }, el: d.body})}catch(er){console.log('==cB');cB()}
  514. var saveLocStor = function(ev, val, do2){ var aaa,aab,aac,aad, t = ev && ev.target.form || document.documentElement || document.body;
  515. xLocStor({do: do2 ||'set', key:'sett'
  516. , val:{lang: (aaa=d.querySelectorAll('.lang', t))[aaa.length-1].value
  517. ,sites: ((aab=d.querySelectorAll('.sites', t))[aab.length-1].value||'').replace(/^[ \t]*|[ \n\t]*$/g,'')
  518. .split('\n')
  519. ,lastHoursLess: (aac=d.querySelectorAll('.less', t))[aac.length-1].checked
  520. ,design1612: (aad=d.querySelectorAll('.des16', t))[aad.length-1].checked
  521. ,dwmyh: S.dwmyh || setts.dwmyh
  522. }
  523. ,cB: function(prev){
  524. console.info('Settings are saved. prev=', prev);}
  525. });
  526. $q('.siteList .settIn').classList.add('changed');
  527. };
  528.  
  529. })({ //write "lang:''," to remove hints; 'en' for English hints (fr - Français, es - espagnol), 'ru' for Russian
  530. lang:''|| (navigator.languages && navigator.languages[1] || navigator.language.substr(0,2)) //='' if hide hints, or 2 letters from $l{}
  531. ,sites: [ //=array or one site in string
  532. '','slashdot.org','reddit.com','techcrunch.com','habr.com','geektimes.com'
  533. ,'smashingmagazine.com','engadget.com'] //write your favorite sites
  534. ,design1612: 0 //=boolean - gray design is disabled for layout1811
  535. ,lastHoursLess: 1 //=boolean - not show odd some values of hours after 8 h
  536. ,dwmyh: [1,1,1,1,1] //=array of numbers - current vals of days, weeks, months, years, hours
  537. });