Yandex Extra Buttons

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

目前为 2016-03-29 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Yandex Extra Buttons
  3. // @name:ru Yandex_Extra_Buttons
  4. // @description Add buttons (last 1/2/3 days, weeks, PDF search etc.) for Yandex search page
  5. // @description:ru Кнопки вариантов поиска для страницы результатов поиска Yandex (1-2-3 дня, недели, PDF, ...)
  6. // @version 5.2016.3.28
  7. // @namespace spmbt.github.com
  8. // @include https://www.yandex.*
  9. // @include https://yandex.*/search*
  10. // @include https://yandex.*/yandsearch*
  11. // @include https://spmbt.github.io/googleSearchExtraButtons/saveYourLocalStorage.html
  12. // @update buttons CSP fix for main page(native settings) (w/o authorization)
  13. // ==/UserScript==
  14. if(location.host=='spmbt.github.io'){
  15. window.addEventListener('message', function(ev){
  16. //console.log('[io0]', ev.origin);
  17. if(/^https?:\/\/(www\.)?yandex\./.test(ev.origin)){
  18. var d = typeof ev.data =='string' && ev.data[0] =='{' ? JSON.parse(ev.data) : ev.data;
  19. if(!d.do) return;
  20. var tok = d.tok, key = d.key;
  21. switch(d.do){
  22. case 'set':
  23. var prev = localStorage[key];
  24. if(d.val !==undefined)
  25. localStorage[key] = JSON.stringify(d.val);
  26. else
  27. localStorage.removeItem(key);
  28. break;
  29. case 'get':
  30. prev = localStorage[key];
  31. prev = prev === undefined || typeof prev =='string'&& prev[0] !='{'? prev : JSON.parse(prev);
  32. break;
  33. case 'remove':
  34. prev = localStorage[key];
  35. if(prev !==undefined)
  36. localStorage.removeItem(key);
  37. }
  38. //console.log('[io1]', tok, 'prev=', prev);
  39. //ev.source.postMessage(JSON.stringify(prev !==undefined ? {tok: tok, prev: prev} : {tok: tok, undef:1}), ev.origin);
  40. }},!1);
  41. }else
  42.  
  43. (function(setts){ //lang, sites, lastHoursLess
  44. if(window != top) return;
  45.  
  46. var $x = function(el, h){if(h) for(var i in h) el[i] = h[i]; return el;} //===extend===
  47. ,$pd = function(ev){ev.preventDefault();}
  48. ,$q = function(q, el){return (el||document).querySelector(q)}
  49. ,$qA = function(q, el){return (el||document).querySelectorAll(q)}
  50. ,lh = location.href
  51. ,d = document, S //current settings
  52. ,cspState //if 1 set constant setts
  53. ,$e = function(g){ //===create or use existing element=== //g={el|clone,cl,ht,cs,at,atRemove,on,apT}
  54. g.el = g.el || g.clone ||'DIV';
  55. var o = g.o = g.clone && g.clone.cloneNode && g.clone.cloneNode(!0)
  56. || (typeof g.el =='string' ? d.createElement(g.el) : g.el);
  57. if(o){ //execute if exist
  58. if(g.cl)
  59. o.className = g.cl;
  60. if(g.clAdd)
  61. o.classList.add(g.clAdd);
  62. if(g.cs)
  63. $x(o.style, g.cs);
  64. if(g.ht || g.at){
  65. var at = g.at ||{}; if(g.ht) at.innerHTML = g.ht;}
  66. if(at)
  67. for(var i in at){
  68. if(i=='innerHTML') o[i] = at[i];
  69. else o.setAttribute(i, at[i]);}
  70. if(g.atRemove)
  71. for(var i in g.atRemove)
  72. o.removeAttribute(g.atRemove[i]);
  73. if(g.on)
  74. for(var i in g.on) if(g.on[i])
  75. o.addEventListener(i, g.on[i],!1);
  76. g.ap && o.appendChild(g.ap);
  77. g.apT && g.apT.appendChild(o);
  78. }
  79. return o;
  80. },
  81. addRules = function(css){
  82. var heads = d.getElementsByTagName('head')
  83. ,node = d.createElement('style');
  84. heads.length && heads[0].appendChild(node);
  85. node.appendChild(d.createTextNode(css));
  86. };
  87. /**
  88. * check occurrence of third-party event with growing interval
  89. * @constructor
  90. * @param{Number} h.t start period of check
  91. * @param{Number} h.i number of checks
  92. * @param{Number} h.m multiplier of period increment
  93. * @param{Function} h.check event condition
  94. * @param{Function} h.occur event handler
  95. */
  96. var Tout = function(h){
  97. var th = this;
  98. (function(){
  99. if((h.dat = h.check() )) //wait of positive result, then occurs
  100. h.occur();
  101. else if(h.i-- >0) //next slower step
  102. th.ww = setTimeout(arguments.callee, (h.t *= h.m) );
  103. })();
  104. }
  105. //for xLocStor:
  106. ,xLocStorOrigin = d.location.protocol +'//spmbt.github.io'
  107. ,qr, qrs ={} //set of queries "key-calls" (ок, toutLitt, toutLong, noService, noStorage)
  108. ,qrI = 0 //queries counter
  109. ,qrN = 12 //max number of waiting queries
  110. ,errIMax = 120, errNMax = errIMax //max number of errors
  111. ,ns ='googXButtons_' //namespace for keys
  112. ,listenMsg
  113. /**
  114. * external localStorage for using another domain if current domain storage is erased anywhere
  115. * @param{String} h.do - action: set|get|remove
  116. * @param{String} h.key
  117. * @param{Object|undefined} h.val (any type)
  118. * @param{Number|undefined} h.toutLitt
  119. * @param{Number|undefined} h.tout
  120. * @param{Function} h.cB - callback with 2 arguments
  121. * @param{Function|undefined} h.err - callback for err with one argument
  122. */
  123. ,xLocStor = function(h){
  124. var h0 = h;
  125. h.toutLitt = h.toutLitt || 400;
  126. h.tout = h.tout || 4000;
  127. var ifr = $q('#xLocStor')
  128. ,query = function(){
  129. if((qrI += 1) > qrN){
  130. xCatch('longQrs', null, h);
  131. return;}
  132. ifr.contentWindow.postMessage(JSON.stringify($x({
  133. do: h.do
  134. ,tok: token
  135. ,key: ns + h.key
  136. }, h.val !==undefined ? {val: h.val}:{}) )
  137. , xLocStorOrigin);
  138. qrs[token] = $x({ //for wait of response
  139. wToutLitt: (function(h, qrI, errIMax){return setTimeout(function(){
  140. qrI -= 1;
  141. if((errIMax -= 1) >=0)
  142. ;//console.warn('toutLitt', h);
  143. chkErrMax();
  144. }, h.toutLitt);})(h, qrI, errIMax)
  145. ,wTout: (function(h, qrI){return setTimeout(function(){
  146. qrI -= 1;
  147. //xCatch('tout', null, h);
  148. //xLocStor(h0);
  149. }, h.tout);})(h, qrI)
  150. }, h);
  151. }
  152. ,token = +new Date() + (Math.random()+'').substr(1,8)
  153. ,el = h.el;
  154. delete h.el;
  155. /*
  156. //csp in main page
  157. media-src yastatic.net kiks.yandex.ru;
  158. img-src 'self' data: https://yastatic.net https://home.yastatic.net https://*.yandex.ru https://*.yandex.net
  159. https://*.tns-counter.ru yastatic.net home.yastatic.net yandex.ru *.yandex.ru *.yandex.net *.tns-counter.ru *.gemius.pl yandex.st;
  160. font-src 'self' https://yastatic.net yastatic.net;
  161. connect-src 'self' wss://push.yandex.ru wss://portal-xiva.yandex.net https://yastatic.net https://home.yastatic.net
  162. https://yandex.ru https://*.yandex.ru portal-xiva.yandex.net yastatic.net home.yastatic.net yandex.ru
  163. *.yandex.ru *.yandex.net yandex.st;
  164. script-src 'self' 'unsafe-inline' 'unsafe-eval' https://suburban-widget.rasp.yandex.ru https://suburban-widget.rasp.yandex.net
  165. https://yastatic.net https://home.yastatic.net https://mc.yandex.ru https://pass.yandex.ru yastatic.net
  166. home.yastatic.net yandex.ru www.yandex.ru mc.yandex.ru suggest.yandex.ru clck.yandex.ru awaps.yandex.net;
  167. default-src 'self' wss://portal-xiva.yandex.net portal-xiva.yandex.net;
  168. style-src 'self' 'unsafe-inline' https://yastatic.net https://home.yastatic.net yastatic.net home.yastatic.net;
  169. frame-src 'self' https://yastatic.net https://yandex.ru https://*.yandex.ru wfarm.yandex.net yastatic.net
  170. yandex.ru *.yandex.ru awaps.yandex.net;
  171. report-uri https://csp.yandex.net/csp?from=big.ru&showid=22900.20964.1459066888.30083&h=n58&yandexuid=833832981443596954;
  172. object-src *.yandex.net yastatic.net kiks.yandex.ru awaps.yandex.net storage.mds.yandex.net;
  173.  
  174. //csp in results
  175. default-src 'self' 'unsafe-inline' 'unsafe-eval' data: https://!*.yandex.net:* *.yandex.net:* https://!*.yandex.ru:*
  176. *.yandex.ru:* https://yandex.ru:* yandex.ru:* https://yandex.st:* yandex.st:* yastatic.net https://yastatic.net
  177. *.tns-counter.ru https://!*.tns-counter.ru https://video.khl.ru https://www.video.khl.ru https://1tv.ru
  178. https://www.1tv.ru https://stream.1tv.ru https://www.stream.1tv.ru https://www.youtube.com https://video.kinopoisk.ru
  179. https://pbs.twimg.com yandex.ua https://yandex.ua *.yandex.ua https://!*.yandex.ua;
  180. report-uri https://csp.yandex.net/csp?from=web&reqid=1459037130208387-17346427857802980809255285-sas1-1677&yandexuid=833832981443596954&yandex_login=
  181. */
  182. //console.info('h.csp: ',h.csp)
  183. if(!h.csp){
  184. cspState =1;
  185. if(ifr){
  186. //ifr.src = xLocStorOrigin +'/googleSearchExtraButtons/saveYourLocalStorage.html?1'
  187. query();
  188. }
  189. else ifr = $e({
  190. el: 'iframe',
  191. at:{id: 'xLocStor'
  192. ,src: xLocStorOrigin +'/googleSearchExtraButtons/saveYourLocalStorage.html'
  193. },
  194. cs: {display: 'none'},
  195. on: {load: query},
  196. apT: el || d.body
  197. });
  198. setTimeout(function(){cspState =2;},0);
  199. if(!listenMsg) addEventListener('message', function(ev){
  200. if(ev.origin == xLocStorOrigin){ // {"tok":"<value>"[,"err":"<txt>"],"h":...}
  201. //console.log('from_io', JSON.parse(ev.data))
  202. var resp = ev.data && ev.data[0] =='{' && JSON.parse(ev.data);
  203. if(!resp) xCatch('bad_format', resp, h);
  204. if(( qr = qrs[resp.tok] )){
  205. qrI -= 1;
  206. qr.cB(resp.prev, resp.undef);
  207. var er = qr.err;
  208. delete qrs[resp.tok];} // else ignore unsufficient token
  209. if(resp.err && (!er || er(resp.err)) ) //individual or common error processing depends of er()
  210. xCatch(resp.err, resp, h);
  211. cspState =3;
  212. }},!1);
  213. }else{
  214. h.cB && h.cB(setts, 1);
  215. }
  216. listenMsg =1;
  217. },
  218. //for tests: localStorage.googXButtons_dwmyh = JSON.stringify({h:[1,2,1,1,1]})
  219. //$('#xLocStor').contentWindow.postMessage('{"do":"get","key":"googXButtons_dwmyh"}','https://spmbt.github.io')
  220. xCatch = function(er, resp, h){
  221. if((errIMax -= 1) >=0)
  222. console.error('tok:', resp && resp.tok ||'--','; err:', er,'; h:', h,'; respH:', resp && resp.h);
  223. chkErrMax();
  224. },
  225. chkErrMax = function(){if(!errIMax) console.error('Too many err messages:', errNMax)}
  226. ,type ='PDF,DOC,docx,RTF,SWF,XLS,PPT,ODT,ODS,ODP,ODG'.split(',').map(function(x){return '&nbsp; '+x+'&nbsp; '})
  227. ,$l ={ru:{
  228. 'search in PDF files':'поиск по документам PDF'
  229. ,'search in':'искать по'
  230. ,'from / to':'за период'
  231. ,'last':['за последний','за последние','за последнюю']
  232. ,'day':'сутки'
  233. ,'days':['дня','дней']
  234. ,'week':'неделю'
  235. ,'weeks':['недели','недель']
  236. ,'month':'месяц'
  237. ,'months':['месяца','месяцев']
  238. ,'year':'год'
  239. ,'years':['года','лет']
  240. ,'hour':'час'
  241. ,'hours':['часа','часов']
  242. ,'Settings':'Настройки'
  243. ,'of userscript':'юзерскрипта'
  244. ,'reload page for effect':'перезагрузить страницу'
  245. ,'Interface language':'Язык интерфейса'
  246. ,'Less positions at the end of selects':'Меньше выбора в конце селектов'
  247. ,'Sites':'Сайты'
  248. },ua:{
  249. 'search in PDF files':'пошук по документах PDF'
  250. ,'search in':'шукати по'
  251. ,'from / to':'за період'
  252. ,'last':['за останній','за останні','за останню']
  253. ,'day':'добу'
  254. ,'days':['дні','днів']
  255. ,'week':'тиждень'
  256. ,'weeks':['тижня','тижнів']
  257. ,'month':'місяць'
  258. ,'months':['місяці','місяців']
  259. ,'year':'рiк'
  260. ,'years':['роки','рокiв']
  261. ,'hour':'годину'
  262. ,'hours':['години','годин']
  263. ,'Settings':'Настройки'
  264. ,'of userscript':'юзерскрипту'
  265. ,'reload page for effect':'перезавантажити сторінку'
  266. ,'Interface language':'Мова інтерфейсу'
  267. ,'Less positions at the end of selects':'Менше вибору в кінці селектів'
  268. ,'Sites':'Сайти'
  269. },by:{
  270. 'search in PDF files':'пошук па дакументах PDF'
  271. ,'search in':'шукаць па'
  272. ,'from / to':'за перыяд'
  273. ,'last':['за апошні','за апошнія','за апошнюю']
  274. ,'day':'суткі'
  275. ,'days':['дня','дзён']
  276. ,'week':'тыдзень'
  277. ,'weeks':['тыдня','тыдняў']
  278. ,'month':'месяц'
  279. ,'months':['месяца','месяцаў']
  280. ,'year':'год'
  281. ,'years':['года','гадоў']
  282. ,'hour':'гадзіну'
  283. ,'hours':['гадзіны','гадзін']
  284. ,'Settings':'Налады'
  285. ,'of userscript':'юзерскрипта'
  286. ,'reload page for effect':'перазагрузіць старонку'
  287. ,'Interface language':'Мова інтэрфейсу'
  288. ,'Less positions at the end of selects':'Менш выбару ў канцы селект'
  289. ,'Sites':'Сайты'
  290. },fr:{
  291. 'search in PDF files':'la recherche dans les fichiers PDF'
  292. ,'search in':'rechercher dans'
  293. ,'from / to':'pour la période'
  294. ,'last':['le dernier','dans les derniers','dans les derniers']
  295. ,'day':'jour'
  296. ,'days':['jours','jours']
  297. ,'week':'semaine'
  298. ,'weeks':['semaines','semaines']
  299. ,'month':'mois'
  300. ,'months':['mois','mois']
  301. ,'year':'an'
  302. ,'years':['ans','ans']
  303. ,'hour':'heure'
  304. ,'hours':['heures','heures']
  305. ,'Settings':'Paramètres'
  306. ,'of userscript':'de Userscript'
  307. ,'reload page for effect':'recharger la page pour effet'
  308. ,'Interface language':'Langue de l\'interface'
  309. ,'Less positions at the end of selects':'Moins de choix les longues listes'
  310. ,'Sites':'Les sites'
  311. },de:{
  312. 'search in PDF files':'Suche in PDF-Dateien'
  313. ,'search in':'Suche in'
  314. ,'from / to':'im Zeitraum'
  315. ,'last':['letzter','letztes','letzte']
  316. ,'day':'Tag'
  317. ,'days':['Tage','Tage']
  318. ,'week':'Woche'
  319. ,'weeks':['Wochen','Wochen']
  320. ,'month':'Monat'
  321. ,'months':['Monate','Monate']
  322. ,'year':'Jahr'
  323. ,'years':['Jahre','Jahre']
  324. ,'hour':'Stunde'
  325. ,'hours':['Stunden','Stunden']
  326. ,'Settings':'Einstellungen'
  327. ,'of userscript':'von Userscript'
  328. ,'reload page for effect':'Seite neu laden'
  329. ,'Interface language':'Sprache'
  330. ,'Less positions at the end of selects':'Weniger Auswahl in langen Listen'
  331. ,'Sites':'Websites'
  332. },es:{
  333. 'search in PDF files':'búsqueda en archivos PDF'
  334. ,'search in':'busca en'
  335. ,'from / to':'para el período'
  336. ,'last':['el último','en los últimos','en los últimos']
  337. ,'day':'día'
  338. ,'days':['días','días']
  339. ,'week':'Semana'
  340. ,'weeks':['semanas','semanas']
  341. ,'month':'mes'
  342. ,'months':['meses','meses']
  343. ,'year':'año'
  344. ,'years':['años','años']
  345. ,'hour':'hora'
  346. ,'hours':['horas','horas']
  347. ,'Settings':'Ajustes'
  348. ,'of userscript':'de userscript'
  349. ,'reload page for effect':'página para efecto de recargar'
  350. ,'Interface language':'Idioma de interfaz'
  351. ,'Less positions at the end of selects':'Menos elección en listas largas'
  352. ,'Sites':'Sitios'
  353. }}; //if !lang, then no hints
  354. addRules('.z-index-group_level_9{z-index: 11002}' //buttons above suggest
  355. +'.lsbb .xButt,.search2__button >.siteList, .search2__button .suggest2-form__button:not([role="button"]){'
  356. +'z-index: 11002; width: 34px; height:17px; padding: 0 2px; line-height:14px; font-size:14px;'
  357. +'border:1px solid transparent; border-radius: 1px; background-color: rgba(214, 188, 76, 0.92); color:#fff; opacity:.6}'
  358. +'.search2__button >.siteList{width:31px; height:auto; padding: 1px 0 2px; text-align:center; font-weight: bold;'
  359. +'background-color: rgba(228, 189, 17, 0.7);} .search2__button >.siteList .lsb{font-weight: normal; color:#ece3dd}'
  360. +'.search2__button >.siteList:after{display:block; border-left:3px solid rgba(228, 189, 17, 0.7); border-top:8px solid transparent;'
  361. +' border-bottom:9px solid transparent; content:""; position: absolute; left:32px; top:0; height:2px;}'
  362. +'.search2__button .suggest2-form__button:hover,.search2__button .xButt:hover{opacity:.85; color:#6f6e69;}'
  363. +'.search2__button .xButt:not(.sett):hover{background-color: rgba(226, 194, 27, 0.47);}'
  364. +'.search2__button .xButt .suggest2-form__button:hover{background-color: #e4d68c}'
  365. +'.siteList .xButt{display: block} .siteList .xButt .txt{padding: 0 2px 0 1px;} .siteList .sett .txt{background-color: #e2c043}'
  366. +'.siteList .settIn{display: none; width: 250px; padding: 2px 4px; text-align: left; border:1px solid #dacb97;'
  367. +'background-color: rgba(239, 235, 217, 0.94); color: #653} .siteList .settIn hr{margin:2px 0}'
  368. +'.sbibtd .sfsbc .nojsb, .siteList .sett:hover .settIn, .siteList .settIn.changed,'
  369. +'.siteList .settIn.changed .reload{display: block}.siteList .settIn .reload, .siteList.hiddn{display: none}'
  370. +'.select .button.button_checked_yes, .select .button.button_checked_yes .button__text{background-color: rgba(245, 226, 140, 0.7)}');
  371. var ff; (ff=function(CSPolicy){xLocStor({do:'get', key:'sett', val:setts, csp: CSPolicy, cB: function(prev,undef){
  372. S = prev || setts;
  373. S.dwmyh = S.dwmyh || setts.dwmyh; //temp. transitional expr.
  374. console.timeStamp = function(){};
  375.  
  376. new Tout({t:120, i:8, m: 1.6
  377. ,check: function(){
  378. return d && $q('.suggest2-form__button');
  379. },
  380. occur: function(){
  381. var lang = S.lang != null && S.lang || setts.lang
  382. ,sites = S.sites && (S.sites.length && S.sites[0] || S.sites.length >1) && S.sites
  383. || typeof sites =='string'&& [sites] || !S.sites && setts.sites || null;
  384. var strSites = sites && sites.join('\n').replace(/^\n/,'\n\n') ||''
  385. ,$L = $l[lang] || $l.ru; //default template of lang
  386. if(!lang || !$l[lang] || lang =='en') for(var l in $L){ //replace 'en' lang for default or substitution
  387. if($L[l] instanceof Array) for(var l2 in $L[l])
  388. $L[l][l2] = l;
  389. else
  390. $L[l] = l;
  391. }
  392. var $LSettings = $L['Settings'];
  393. if(sites && sites.length)
  394. sites.push($LSettings);
  395. var mainPg = /\/search\?/.test(lh)
  396. ,inputSearch = $q('.suggest2-form .input__control.input__input') || $q('.input__control') //trueth place for 1 of 2 pages
  397. ,buttSearch = this.dat
  398. ,ua = lang=='ua', by = lang=='by',de = lang=='de'
  399. ,buttS ={
  400. site:{url:'site:'+ S.sites[0], txt:$L['search in']+' '+ S.sites[0], one:'day'} //you may comment this line
  401. ,'.. : ..':{url:'', txt:$L['from / to']}
  402. ,'1D':{url:'&tbs=qdr:d', txt:$L['last'][de?0:ua?2:1] +' '+ $L['day'], one:'day', up:13,lett:'D',itrv:1}
  403. ,'1W':{url:'&tbs=qdr:w', txt:$L['last'][ua||by?0:2] +' '+ $L['week'], one:'week', up:14,lett:'W',itrv:7}
  404. ,'1M':{url:'&tbs=qdr:m', txt:$L['last'][0] +' '+ $L['month'], one:'month', up:20,lett:'M',itrv:30.5}
  405. ,'1Y':{url:'&tbs=qdr:y', txt:$L['last'][de?1:0] +' '+ $L['year'], one:'year', up:10,lett:'Y',itrv:365.24}
  406. //,'1H':{url:'&tbs=qdr:h', txt:$L['last'][ua||de||by?2:0] +' '+ $L['hour'], one:'hour', up:23,lett:'H',itrv:1/24}
  407. //,DOC:{url:'&mime=doc', txt:$L['search in PDF files'].replace(/PDF/,'DOC'), up: type.length}
  408. ,PDF:{url:'&mime=pdf', txt:$L['search in PDF files'], up: type.length}
  409. }, ii = 0, iD = -1;
  410. !sites && delete buttS.site;
  411. buttSearch.parentNode.style.position ='relative';
  412. if(buttSearch && top == self) for(var i in buttS) if(i !='site'|| S.sites){ //buttons under search input line
  413. if(i.length ==2) iD++; else iD=-1;
  414. var bI = buttS[i], titl
  415. ,Gesch = ({m:'letzter',f:'letzte',n:'letztes'})['m,f,m,n,f'.split(',')[iD]]
  416. ,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]) }
  417. ,butt2 = $e({clone: i =='site'|| i.length ==2 || i=='PDF'
  418. ? $e({cl: 'siteList', cs: {cursor:'default'}, at: {site: S.sites[0], date: bI.url} })
  419. : i !='.. : ..'|| mainPg ? buttSearch : $e({cl: 'siteList hiddn'})
  420. ,clAdd:'xButt'
  421. ,atRemove: ['id', 'name','role']
  422. ,at: {value: iD !=-1 && S.dwmyh[iD] !=1 ? S.dwmyh[iD] + bI.lett : i
  423. ,innerHTML: '<span class=txt onclick=this.parentNode.click();return!1 title="' +(titl = lang || i=='site'|| i=='.. : ..'
  424. ? (iD==-1 || S.dwmyh[iD]==1 ? bI.txt : $L['last'][1] +' '+ hint(S.dwmyh[iD]-1)).replace(/letztes/,Gesch) :'')+'">'
  425. +(iD !=-1 && S.dwmyh[iD] !=1 ? S.dwmyh[iD] + bI.lett : i) +'</span>'
  426. ,title: titl}
  427. ,cs: {position: 'absolute', top: '33px', left: (-127 + 37 * (ii++ - (ii >2 && !mainPg))) +'px'}
  428. ,on: {click: (function(bI, i, iD){
  429. return /PDF|DOC|site/.test(i)
  430. ? function(ev){
  431. var doc, t = ev.target
  432. ,dat = (t.getAttribute('date')||t.parentNode.getAttribute('date')||'').replace(/^&\w+=/,'').toLowerCase();
  433. if(t.className =='defa')
  434. saveLocStor('','','remove'); $pd(ev);
  435. if(((t.getAttribute('site') ==null && t.parentNode.getAttribute('site') ==null)
  436. || t.getAttribute('site')==$LSettings || t.parentNode.getAttribute('site')==$LSettings)
  437. && !/PDF|DOC/.test(t.getAttribute('value'))) return;
  438. inputSearch.value = inputSearch.value.replace(/ site\:[\w.]*$/ig,'') +(/site/.test(i)
  439. ?' site:'+ (t.getAttribute('site') || t.parentNode.getAttribute('site')||''):'');
  440. //console.log('clic:',i,dat,bI,ev, t.className, inputSearch.value, ev.currentTarget, buttSearch.form)
  441. if(/PDF|DOC/.test(i)){
  442. if(doc = $q('select[name="mime"]')){
  443. var opts = Array.prototype.slice.call(doc).reduce(function(memo, el, i){
  444. memo[el.value] = el; return memo;},{});
  445. var opt = opts[dat];
  446. if(opt)
  447. opt.selected = opt.selected ?'':'selected';
  448. }else
  449. $e({el: buttSearch.form, ap: $e({el: $q('input[name="mime"]')||'input'
  450. ,at:{type:'hidden', name:'mime', value: dat}}) });}
  451. //console.log('clic2:', /xButt|txt/.test(t.className) && i !='site', opt, opts)
  452. if(/xButt|txt/.test(t.className) && !(i=='site' && !(/list/.test(t.parentNode.className)
  453. || /list/.test(t.parentNode.parentNode.className)))) buttSearch.click();
  454. }: !bI.url ? function(ev){ //from-to date
  455. var el = $q('#cdrlnk'), o;
  456. el && el.dispatchEvent(((o = d.createEvent('Events')).initEvent('click', !0, !1), o));
  457. $pd(ev);
  458. }: function(ev){ //last interval
  459. var val = (ev.target.getAttribute('value')||ev.target.parentNode.getAttribute('value')).replace(/\D/g,'')
  460. ,dat = ev.target.getAttribute('date')||ev.target.parentNode.getAttribute('date')
  461. ,daysAgo = buttS['1'+ ((dat.match(/:(\w)/) ||[])[1] ||'d').toUpperCase()].itrv * val
  462. ,date = function(d){
  463. d = new Date(+new Date() - d * 86400000)
  464. return (d.getDate()>9?'':'0') + d.getDate() +'.'+ (d.getMonth()>8?'':'0')
  465. +(d.getMonth()+1) +'.'+ d.getFullYear();
  466. };
  467. location.href = '/search?text='+ encodeURIComponent(inputSearch.value)
  468. +('&from_date_full='+ date(daysAgo) +'&to_date_full='+ date(-1) || bI.url);
  469. //+(/[&?]tbm=/.test(lh) ? '&'+/tbm=[^&]*/.exec(lh)[0]:''); //saving type of page
  470. S.dwmyh[iD] = +val;
  471. $pd(ev);
  472. ev.stopPropagation();
  473. saveLocStor();
  474. }
  475. })(bI, i, iD),
  476. mouseover: i =='site' || i.length ==2 || i=='PDF'? (function(bI,i){return function(ev){
  477. clearTimeout(bI.ww);
  478. $q('.list', ev.currentTarget).style.display ='block';
  479. }})(bI,i) :'',
  480. mouseout: i =='site' || i.length ==2 || i=='PDF'? (function(bI,i){return function(ev){
  481. var t = ev.currentTarget;
  482. if(ev.relatedTarget && /^<option/i.test(ev.relatedTarget.innerHTML)){
  483. ($q('.settIn')||{classList: {add:function(){}}}).classList.add('changed'); return;}
  484. clearTimeout(bI.ww);
  485. bI.ww = setTimeout(function(){
  486. $q('.list',t).style.display ='none';
  487. }, 450);
  488. }})(bI,i) :'',
  489. change: saveLocStor
  490. }
  491. ,apT: buttSearch.parentNode
  492. });
  493. bI.el = butt2;
  494. if(i =='site'|| i.length ==2 || i =='PDF'){ //dropdown lists under some buttons
  495. var siteList = $e({cl:'list',cs:{display:'none'}, apT: butt2}), arr =[];
  496. for(var j =0; j <= bI.up -1 -(i=='1W'&& S.lastHoursLess ?4:0) -(i=='1M'&& S.lastHoursLess ?9:0); j++)
  497. if(i!='PDF' &&(i !='1H' || !S.lastHoursLess || j < 8 || j % 2 ))
  498. arr.push(hint(j));
  499. //console.log(S.sites,i, S.dwmyh);
  500. var list = i == 'site' ? sites||[] : i =='1D'&& !sites ? arr.concat([$LSettings])
  501. : i=='PDF' ? type : arr;
  502. for(var j in list) if(j !=0 || iD !=-1 && S.dwmyh[iD] !=1)
  503. var sI = list[j]
  504. ,butt3 = $e({clone: sI==$LSettings
  505. ? $e({cl: 'sett lsb'})
  506. : buttSearch
  507. ,clAdd:'xButt'
  508. ,atRemove:['id','name','role']
  509. ,at:{value: sI
  510. ,site: sI
  511. ,date: bI.url.replace(/doc$/, sI.replace(/&nbsp; /g,'').toLowerCase())
  512. ,title: sI==$LSettings || !lang ?'':(/site|PDF/.test(i) ? $L['search in'] +' '+ sI.replace(/&nbsp; /g,'')
  513. : j==0 ? bI.txt : $L['last'][1] +' '+ sI).replace(/letztes/,Gesch)
  514. ,innerHTML:'<span class=txt>'+ sI +'</span>'+ (sI != $LSettings &&!(!S.sites && i =='1H')
  515. ?'':'<div class="settIn">'
  516. +$LSettings +' '+ $L['of userscript'] +'<br>"Yandex Extra Buttons"<hr>'
  517. +$L['Interface language'] +': <select class="lang" style="width:70px">'
  518. +(function(){var s='<option'+ (lang=='en'?' selected':'') +'>en</option>';
  519. for(var i in $l)
  520. s+='<option'+ (lang==i ?' selected':'') +'>'+ i +'</option>';
  521. return s +'<option value="" '+ (lang==''?'selected':'') +'>en w/o hints</option>'})()
  522. +'</select><br>'
  523. +'<input type="checkbox" class="less" id="hoursLess" '+ (S.lastHoursLess ?'checked':'') +'/>'
  524. +'<label for="hoursLess" id="hoursLessL">'+ $L['Less positions at the end of selects'] +'</label><br>'
  525. +'<i><a href="#" class="defa" style="float: right">Default settings</a></i>'
  526. +$L.Sites +': <br><textarea class="sites" style="width:97%" rows=8>'
  527. + strSites +'</textarea><br>'
  528. +'<a class="reload" href=# onclick="location.reload();return!1">'
  529. + $L['reload page for effect'] +'</a>'
  530. +'</div>')}
  531. ,cs: {position: sI != $LSettings ?'static':'absolute',display:'block', width:'auto', height: sI != $LSettings ?'18px':'16px'
  532. ,margin:'2px 0 -1px -13px', padding:0, textAlign:'left', fontWeight:'normal', opacity:1}
  533. ,on:{click: function(ev){
  534. //console.log('c3',ev.target.outerHTML);
  535. var chk = $q('#hoursLess');
  536. if(chk && /hoursLess/.test(ev.target.id)){
  537. chk.outerHTML = '<input type="checkbox" class="less" id="hoursLess"'
  538. +(chk.getAttribute('checked')!=null ?'':' checked="checked"')+'>';
  539. saveLocStor();
  540. }
  541. $pd(ev);}}
  542. ,apT: siteList
  543. });
  544. siteList.style.height ='auto'; siteList.style.textAlign ='center';
  545. }
  546. }
  547. }
  548. });
  549.  
  550. }, el: d.body});})(); setTimeout(function(){/*console.log('S1 ', cspState);*/if(cspState <3) ff('CSPolicyFrame');},2000);
  551. var saveLocStor = function(ev, val, do2){ var aaa,aab,aac, t = ev && ev.target.form || document.documentElement || document.body;
  552. xLocStor({do: do2 ||'set', key:'sett'
  553. , val:{lang: (aaa=d.querySelectorAll('.lang', t))[aaa.length-1].value
  554. ,sites: (aab=d.querySelectorAll('.sites', t))[aab.length-1].value.replace(/^[ \t]*|[ \n\t]*$/g,'')
  555. .split('\n')
  556. ,lastHoursLess: (aac=d.querySelectorAll('.less', t))[aac.length-1].checked
  557. ,dwmyh: S.dwmyh || setts.dwmyh
  558. }
  559. ,cB: function(prev){
  560. console.info('Settings are saved. prev=', prev);}
  561. });
  562. $q('.siteList .settIn').classList.add('changed');
  563. };
  564.  
  565. })({ //write "lang:''," to remove hints; 'en' for English hints (fr - Français, es - espagnol), 'ru' for Russian
  566. lang:''|| (navigator.languages && navigator.languages[1] || navigator.language.substr(0,2)) //='' if hide hints, or 2 letters from $l{}
  567. ,sites: [ //=array or one site in string
  568. '','slashdot.org','reddit.com','techcrunch.com','habrahabr.ru','geektimes.ru'
  569. ,'smashingmagazine.com','engadget.com'] //write your favorite sites
  570. ,lastHoursLess: 1 //=boolean - not show odd some values of hours after 8 h
  571. ,dwmyh: [1,1,1,1,1] //=array of numbers - current vals of days, weeks, months, years, hours
  572. });