translate.google tooltip

Translates selected text into a `tooltip' via Google translate

当前为 2015-12-17 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name translate.google tooltip
  3. // @namespace trespassersW
  4. // @author trespassersW
  5. // @copyright trespassersW
  6. // @license MIT
  7. // @description Translates selected text into a `tooltip' via Google translate
  8. // @include http://*
  9. // @include https://*
  10. // @include file://*
  11. // about:config -> greasemonkey.fileIsGreaseable <- true
  12. // @homepageURL https://openuserjs.org/scripts/trespassersW/translate.google_tooltip
  13. // @version 3.9.99
  14. //* This is a descendant of lazyttrick's http://userscripts.org/scripts/show/36898.
  15. // 3.9.99 2015-12-17 ? Googleplex, we have a problem
  16. // 3.9.50 2015-10-17 + multi-sentence; GM_menu item
  17. // 3.9.10 2015-07-29 * fix for Ff39; + now works in chrome
  18. // 3.7.96 2015-05-10 * TTS in ff37; * DOMparser instead of IFRAME; * bugfixes
  19. // 3.7.8.2 2015-04-26 + new country flags host
  20. // 3.7.2 2015-04-20 * TTS: alt-select text inside tooltip and [ctrl/shift]-click language icon below
  21. // * [shift] tts window in IFRAME (: only works on google.* and file://* :(
  22. // * [ctrl] tts window in new tab
  23. // 3.6.2.2 2015-04-19 * gray gradient background
  24. // 3.5.1 2015-04-15
  25. // + TTS: alt-select text inside tooltip and shift-click language icon below
  26. // * From<->To buttons fix; * err handler
  27. // 3.0.0 - national flags icons -- from www.senojflags.com
  28. // 2.3
  29. // - new editable 'source text' field
  30. // 2.2.2
  31. // - backward translation - select text inside tooltip and click the icon under your selection.
  32. // 2.2.1
  33. // - Ctrl-Alt-click removes item from the history of translations
  34. // - Ability to change translation in the history -
  35. // select desired translation in the tooltip window using ctrl or alt -
  36. // which one is checked in your settings - then click on the icon below the selection.
  37. // 2.2
  38. // - history of translations
  39. // 2.1.2
  40. // - Selected text is fetched in the moment when you hover over the icon.
  41. // So, you can select a few letters, then adjust your selection using shift + arrows.
  42. // 2.0.0d
  43. // - native GT languages list
  44. // 2.0.0c
  45. // Alt key option added
  46. // If something goes wrong:
  47. // Tools->SQLite manager-> Database-> Connect_database->
  48. // %YourBrowserProfile%\gm_scripts\translate.google_tooltip.db ->
  49. // scriptvals-> alt/ctrl <- false
  50. // 2.0.0b
  51. // - exit by ESC
  52. // - 1k letters limit -- don't strain your Google
  53. //*/
  54. // /grant GM_addStyle
  55. // @grant GM_getValue
  56. // #grant GM_log
  57. // @grant GM_openInTab
  58. // @grant GM_setValue
  59. // @grant GM_xmlhttpRequest
  60. // @grant GM_registerMenuCommand
  61. // @icon data:image/jpg;base64, R0lGODlhIAARALP/AAAAAP///xMYfAqf////Zv/qDuCeH8VmB8DAwAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAgALAAAAAAgABEAQASdEMlJgb00awkMKQZYjB8RBsE4AtLQvtt0sXHcEcT1pbxK0hsXRmYIGUUgA3DiQjQtssInRAjglMsa4ibtlqSGgECQymmaAwDYUhSFfKoQDQ3LdA6Hoh6qbW4sJHpFWTUAOEA3Vj1WZjF+HQU9X18oPxl0Wx4kXoFiZF1zMEJgbW8qJnAHoU4takocpW5IIISYGh1HRlh9hRZ4eIRaEQA7
  62. //
  63. // ==/UserScript==
  64.  
  65. if(document.body){
  66.  
  67. main = function (){ "use strict";
  68.  
  69. var GTsuffix=".com"; // ".fr" ".de" ".ru" ".com"
  70. //{[ hacks
  71. var UA = navigator.userAgent;
  72. 0 && (UA="Mozilla/5.0 (Windows NT 5.1; rv:39.0) Gecko/20100101 Firefox/39.0");
  73. //]}
  74. var isChrome= (navigator.userAgent.indexOf("AppleWebKit")>0);
  75. var moz=isChrome? "-webkit-": "-moz-";
  76.  
  77. var GTurl= "https://translate.google"+GTsuffix+"/?";
  78. //var dictURL= "https://translate.google"+GTsuffix+"/translate_a/t?client=t";
  79. var dictURL= "https://translate.google"+GTsuffix+"/translate_a/single?client=t";
  80. var ttsURL= "https://translate.google.com/translate_tts?client=t";
  81. var version= 3790;
  82.  
  83. var HREF_NO = 'javascript:void(0)';
  84.  
  85. var llii=0, _log = function(){ /* * /
  86. for (var s=++llii +':', li=arguments.length, i = 0; i<li; i++)
  87. s+=' ' + arguments[i];
  88. console.log(s)
  89. /* */
  90. }
  91. //_log=console.log.bind(console);
  92. _log("tgtt..");
  93. var URL='*'; var tURL;
  94. var GT_tl='auto';
  95. var body;
  96.  
  97. // http://www.senojflags.com/
  98. var senop="https://cdn.rawgit.com",
  99. seno="/trespassersW/UserScripts/master/Flags/",
  100. senox="index.html?gtrantoltip#",
  101. senoj=senop+seno+senox,
  102. senojflags = [seno, "http://lh/Flags/" ],
  103. senoext=".png";
  104. ;
  105. //
  106.  
  107. var res_dict='gt-res-dict'; //'gt_res_dict';
  108. var languagesGoogle, isInited=false;
  109. var rtl_langs="ar fa iw ur";
  110. var inTextArea= null;
  111. var maxHT=20, maxWC=3;
  112. var sourceBH = 3, sourceDP =10;
  113. var ht=null; // history table,
  114.  
  115. var imgForw,imgBack,imgSwap,imgUse,imgSave,imgFlags,imgForwSrc,imgBackSrc;
  116. var txtSel; // text selected
  117. var currentURL, Qtxt='***'; var e6 =999999;
  118. var ampTK = Math.round(Math.random()*e6)+"."+Math.round(Math.random()*e6);
  119. var gt_sl_gms, gt_tl_gms, gt_sl, gt_tl;
  120.  
  121. var sT;
  122. var noMup=0;
  123. var _G = (isChrome?'':moz)+"linear-gradient",_T='transparent';
  124. var G_ ='rgba(0,0,0,.1)',W_='rgba(255,255,255,.1)';
  125. var FG={
  126. t: ['#000' ,'#000' ,'#000' ,'#000' ,'#eec' ,'#000' ,'#000' ], // text
  127. l: ['#047' ,'#047' ,'#047' ,'#052' ,'#7CF' ,'#047' ,'#670000'], // links
  128. g: ['#404040','#404040' ,'#404040','#404040','#ccb' ,'#404040','#404040'] // greyed txt
  129. };
  130. var BG={
  131. t: ["yellow" ,"grey" ,"blue" ,"green" ,"dark" ,"striped", "pink" ], // titles
  132. C: ['#FFFFE1','#D1D1D1','#D3ECEC','#C4FFC4' ,'#333' , // bg Color
  133. _G+'(-45deg, #DDD, #AAA )' ,'#FFE6E6'],
  134. T: [_G+"(to right,#FFFFE1,#DDDDAA)", _G+"(to right,#D1D1D1,#A0A097)", // buttons
  135. _G+"(to right,#D3ECED,#8CCCCE)", _G+"(to right,#C4FFC4,#6BEF69)",
  136. _G+"(to right,#777,#373737)" , _G+"(to right,#CCC, #888)",
  137. _G+"(to right,#FFE6E6,#FFC6C8)" ],
  138. H: [_T,_T,_T,_T,_T, // dictionary items
  139. _G+'(to bottom ,rgba(127,127,127,.0),rgba(127,127,127,.15))', _T],
  140. F: [G_,G_,G_,G_,W_,G_,G_], // historic phrases
  141. E: ['#F4F4E8','#EEEEEE','#E8E8F4','#E8F4E8','#777777','#DDDDDD','#FFF2F2'] // Edit box
  142. }
  143.  
  144. function bgClick(e){
  145. css(e.target.paletteN);
  146. }
  147.  
  148. function mousedownCleaning(evt){
  149. var divDic = getId('divDic');
  150. var divLookup = getId('divLookup');
  151. var dU = getId('divUse');
  152. var t=evt.target;
  153. noMup=0; // patch :/
  154. if(divDic) {
  155. if(!clickedInsideID(evt.target,'divDic')){
  156. evt.preventDefault(),evt.stopPropagation();
  157. if(dU && clickedInsideID(t,'divUse')){
  158. if(clickedInsideID(t,'divGetback')) forwLookup(evt); else
  159. if(clickedInsideID(t,'divGetforw')) backLookup(evt); else
  160. if(clickedInsideID(t,'imgUse')) useClick(evt); else
  161. _log('x3 click');
  162. return;
  163. }
  164. else
  165. cleanUp('MC');
  166. } else killId(dU);
  167. }
  168. killId(divLookup);
  169. }
  170.  
  171. var documentcontentEditable=false;
  172. var documentdesignMode = '';
  173. var divExtract;
  174.  
  175. var escHnd;
  176. function setEscHnd(){
  177. if(!escHnd) escHnd=
  178. document.addEventListener('keydown', escCleanup, false);
  179. }
  180.  
  181. function cleanUp(s){
  182. _log(s);
  183. var d=getId('divSourcetext');
  184. if(d) sT= d.value;
  185. killId('divDic');
  186. killId('divExtract');
  187. killId('divLookup');
  188. killId('divUse');
  189. killId('divBack');
  190. killId('divSelflag');
  191. killId('divTtsIfr');
  192.  
  193. //divExtract='';
  194. if(documentcontentEditable)
  195. documentcontent.Editable=documentcontentEditable,
  196. documentcontentEditable = false;
  197. if(documentdesignMode == 'on')
  198. document.designMode='on',
  199. documentdesignMode=null;
  200. }
  201.  
  202. function useClick(e){
  203. killId('divUse');
  204. if(e.shiftKey) ht[0][1] += '\n'+txtSel;
  205. else ht[0][1] = txtSel;
  206. GM_setValue('hist',JSON.stringify(ht));
  207. if(getId('divHist')){
  208. killId('divHist');
  209. history();
  210. }
  211. }
  212. var last_tl, last_sl;
  213. function backLookup(e){
  214. if(e.shiftKey || e.ctrlKey) {
  215. noMup=1;
  216. ttsRequest(txtSel,gt_tl, e.ctrlKey!=0);
  217. return;
  218. }
  219. killId('divUse');
  220. gtRequest(txtSel,gt_sl,gt_tl);
  221. currentURL = GTurl + "langpair=" + gt_sl + "|" + gt_tl + "&text=" + escAp(txtSel);
  222. }
  223. //GET https://translate.google.com/?langpair=en|ru&text=Varnish
  224. //POST https://translate.google.com/translate_a/t?client=t&hl=ru&sl=en&tl=ru&text=Varnish
  225. function forwLookup(e){
  226. if(e.shiftKey || e.ctrlKey) {
  227. noMup=1;
  228. ttsRequest(txtSel,gt_sl, e.ctrlKey!=0);
  229. return;
  230. }
  231. killId('divUse');
  232. var t=gt_tl; gt_tl=gt_sl; gt_sl=t;
  233. gtRequest(txtSel,gt_sl,gt_tl);
  234. currentURL = GTurl + "langpair=" + gt_sl + "|" + gt_tl + "&text=" + escAp(txtSel);
  235. }
  236. var Gctrl, Galt;
  237. var sayTip="\n[shift / ctrl] listen (";
  238. function showLookupIcon(evt){
  239. Gctrl=GM_getValue('ctrl',false), Galt=GM_getValue('alt',true);
  240. if((!evt.ctrlKey && Gctrl)
  241. ||(!evt.altKey && Galt)
  242. // to avoid collision
  243. ||(evt.ctrlKey && !Gctrl)
  244. ||(evt.altKey && !Galt)
  245. ) return;
  246. evt.preventDefault(),evt.stopPropagation();
  247.  
  248. var divDic = getId('divDic');
  249. var divLookup = getId('divLookup');
  250. txtSel = getSelection(evt.target)+'';
  251.  
  252. if(txtSel.length>1024){
  253. return;
  254. }
  255. //exit if no text is selected
  256. if(!txtSel || txtSel===""){
  257. _log('S:notext ')
  258. if(divDic) {
  259. if(!clickedInsideID(evt.target,'divDic'))
  260. cleanUp('no sel');
  261. }
  262. if(divLookup){
  263. killId(divLookup);
  264. }
  265. return;
  266. }
  267. //possible cleanup
  268. if(divDic){
  269. if(!clickedInsideID(evt.target,'divDic'))
  270. {cleanUp('!divdic'); return; }
  271. // inside divDic:
  272. var dU=getId('divUse');
  273. if(dU){
  274. if(!clickedInsideId('divUse')){
  275. killId(dU);
  276. } return;
  277. }
  278. try{
  279. var p= belowCursor(evt,10,10,'r');
  280. var divUse= buildEl('div', {id:'divUse',
  281. style:'z-index:11000; border: none'+
  282. ';top:' + p.t +';left:' + p.l +';right:' + p.r +';bottom: auto;'
  283. }, null, null );
  284.  
  285. var iTo = getFlagSrc(gt_tl,'to');
  286. var divForw=buildEl('span', {id:'divGetforw', // 'class': 'gootranslink', href: HREF_NO,
  287. //border: 0, src: iTo,
  288. title: gt_sl_gms + '\u2192 '+gt_tl_gms +sayTip+gt_tl+')'},
  289. null, imgH+iTo+imgT);
  290. // ['mousedown', forwLookup], imgH+iTo+imgT);
  291. divUse.appendChild(divForw);
  292. var iFrom = getFlagSrc(gt_sl,'from');
  293. var divBack=buildEl('span', {id:'divGetback', //'class': 'gootranslink', href: HREF_NO,
  294. //border: 0, src: iFrom,
  295. title: gt_tl_gms + '\u2192 '+gt_sl_gms +sayTip+gt_sl+')'},
  296. null, imgH+iFrom+imgT);
  297. // ['mousedown', backLookup], imgH+iFrom+imgT);
  298. gt_sl !='auto' && divUse.appendChild(divBack);
  299.  
  300. addEl(divUse,'img',{id: 'imgUse', border: 0,
  301. title: 'use in history\n[shift] add to history', src: imgUse},
  302. null,null);
  303.  
  304. // tp=(evt.clientY+window.pageYOffset+30)+'px';
  305. // lf=(evt.clientX+window.pageXOffset+30)+'px';
  306. body.appendChild(divUse);
  307. }catch(e){console.log('use hist\n'+e)}
  308. return;
  309. }
  310. // inside page
  311. if(!isInited) {css(-1); isInited=true; }
  312. //remove div if exists
  313. if(divLookup)
  314. killId(divLookup);
  315. //div container
  316. p = belowCursor(evt,10,10);
  317. divLookup = buildEl('div', {id:'divLookup', style: 'z-index:10000'+
  318. ';border: none;' +
  319. ';top:' + p.t +';left:' + p.l +';right:' + p.r +';bottom: auto'
  320. }, null, null);
  321.  
  322. iTo = getFlagSrc(GM_getValue('to'),'to');
  323. var iForw=buildEl('img', {'border':0, id:"imgLookForw", style: 'padding-left: 5px',
  324. src: iTo}, ['mouseover', lookup],null);
  325. var sl=GM_getValue('from','auto');
  326. iFrom = getFlagSrc(sl,'from');
  327. var iBack=buildEl('img', {'border':0, id:"imgLookBack", style: 'padding-left: 5px',
  328. src: iFrom},
  329. ['mouseover', lookup], null);
  330. if(p.r == 'auto' ){ // left half
  331. divLookup.appendChild(iForw);
  332. sl != 'auto' && divLookup.appendChild(iBack);
  333. }else{ // right half
  334. sl != 'auto' && divLookup.appendChild(iBack);
  335. divLookup.appendChild(iForw);
  336. }
  337. body.appendChild(divLookup);
  338. }
  339. function escCleanup(e){
  340. if(!e.shiftKey && !e.ctrlKey && !e.altKey && e.keyCode==27 ){
  341. cleanUp('esc');
  342. document.removeEventListener('keydown', escCleanup,false);
  343. escHnd=null;
  344. }
  345. }
  346.  
  347. function lookup(evt){
  348. var divResult = null;
  349. var divDic = getId('divDic');
  350. var divLookup = getId('divLookup');
  351. var top = divLookup.style.top;
  352. var left = divLookup.style.left;
  353. var rite = divLookup.style.right;
  354. var txtS = txtSel; // 2012-08-20
  355. if(evt) txtSel = getSelection(inTextArea? inTextArea: evt.target)+'';
  356. if(!txtSel) txtSel = txtS;
  357. if(txtSel.length>1024){
  358. return;
  359. }
  360. //exit if no text is selected
  361. if(!txtSel || txtSel==""){
  362. _log('L:notext')
  363. if(divDic) {
  364. if(!clickedInsideID(evt.target,'divDic'))
  365. killId(divDic);
  366. }
  367. killId('divLookup');
  368. killId('divDic');
  369. return;
  370. }
  371. //cleanup divs
  372. killId('divDic');
  373. killId('divLookup');
  374. //div container document.body.clientHeight/Width
  375. divDic = buildEl('div',
  376. {id:'divDic', style: 'top:'+top+';left:'+left+';right:'+rite
  377. });
  378. divDic.addEventListener('mousedown', dragHandler, false);
  379. setEscHnd();
  380. body.appendChild(divDic);
  381. // patch gmail
  382.  
  383. if(document.contentEditable)
  384. documentcontentEditable = document.contentEditable,
  385. document.contentEditable = false;
  386. if(document.designMode == 'on')
  387. documentdesignMode='on',
  388. document.designMode='off';
  389.  
  390. //div result
  391. divResult = buildEl('div',
  392. {id:'divResult'}, null, 'Loading...');
  393. divDic.appendChild(divResult);
  394. /**/
  395. // history
  396. var divBottom = buildEl('div',{id:'divBottom', align: 'bottom'},null,null);
  397. addEl(divBottom,'a',
  398. {'class':"gootransbutt gootranslink gtlPassive", id:'historyLink', title: 'Translation history',
  399. align: 'left', href:HREF_NO},
  400. ['click', history], 'History');
  401. addEl(divBottom,'a',
  402. {'class':"gootransbutt gootranslink gtlPassive", id:'sourceLink', title: 'Source', href:HREF_NO},
  403. ['click', source],'Source');
  404. //options link
  405. addEl(divBottom,'a',
  406. {'class':"gootransbutt gootranslink gtlPassive", id:'optionsLink', title: 'Settings', href:HREF_NO},
  407. ['click', options], 'Options');
  408. divDic.appendChild(divBottom);
  409. /**/
  410. //lookup
  411. gt_sl = GM_getValue('from', 'auto');
  412. GT_tl = (gt_tl = GM_getValue('to',GT_tl));
  413. if( evt && evt.target.id== 'imgLookBack' ){
  414. var t=gt_tl; gt_tl=gt_sl; gt_sl=t;
  415. }
  416. gtRequest(txtSel,gt_sl,gt_tl);
  417. }
  418.  
  419. var IFR;
  420. function eStop(e){e.preventDefault(),e.stopPropagation()}
  421. function openInFrame(url){
  422. killId('divTtsIfr');
  423. var dD=getId('divDic');
  424. var IFR=buildEl('div',{id:'divTtsIfr'},null,null);
  425. var IFH=addEl(IFR,'div',{id:'divTtsIfh'},null,null);
  426. addEl(IFH, 'span',{'class':"gootransbutt gootranslink",style: 'color:red!important;'},
  427. ['click', function(e){killId('divTtsIfr')}],'&#x2716;');
  428. addEl(IFH, 'a',{'class':"gootransbutt gootranslink", id: 'divTtsLnk',
  429. href: url, target:"_blank", title: 'play in tab'},
  430. ['click',
  431. function(e)
  432. {eStop(e);GM_openInTab(e.target.href)}
  433. ],
  434. '');
  435. addEl(IFH, 'span', {},[],deURI(url));
  436. // addEl(IFR, 'br');
  437. var BFR=
  438. addEl(IFR, 'iframe',{
  439. width: "100%", height: "48", frameborder: "0",scrolling:"auto", marginheight:"0", marginwidth:"0",
  440. style:'padding-top:3px;overflow-x:hidden;',
  441. src: 'about:blank'
  442. },
  443. null,null);
  444. insAfter(IFR,getId('divBottom'));
  445. BFR.contentWindow.location.href=url;
  446. /*
  447. */
  448. }
  449. function ttsRequest(txt,t,e){
  450. //
  451. var etxt = escAp(txt.split(' ').slice(0,19).join(' '));
  452. etxt=ttsURL + "&ie=utf-8&tl=" + t + "&tk="+ampTK+ "&q=" + etxt;
  453. _log('tts> '+etxt);
  454. if(e)
  455. GM_openInTab(etxt);
  456. else
  457. openInFrame(etxt);
  458. //GM_openInTab(etxt);
  459. // sorry, firefox' decodeAudioData() does NOT support mp3
  460. }
  461. //
  462. function gtRequest(txt,s,t){
  463. var etxt = escAp(txt);
  464. etxt=GTurl + "langpair=" + s + "|" + t + "&text=" + etxt.split(/%20|\s|\.|;|,/).slice(0,19).join('%20');
  465. if(etxt.length>1024) etxt=etxt.substr(0,1024);
  466. currentURL = etxt ;
  467. if( 1 || !((s==last_sl && t==last_tl) || (s==last_tl && t==last_sl)) || (divExtract=='')){ // !!! 015-12-17
  468. //_log(s+c+last_sl+ ' '+t+c+last_tl + ' '+ divExtract );
  469. divExtract = '';
  470. Request(etxt);
  471. }else{
  472. extractResult(null);
  473. }
  474. last_sl = s; last_tl = t;
  475. }
  476. function Request(url,cb){
  477. var Url=url, meth=(1 && cb)? 'POST': 'GET';
  478. var Data='';
  479. var Hdr= {
  480. "User-Agent": UA
  481. ,"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
  482. ,"Accept-Encoding": "gzip, deflate"
  483. //,"Host": "www.google.com"
  484. }
  485. if(1 && cb){
  486. var Q=url.split('&q=');
  487. Url=Q[0];
  488. Data='&q='+Q[1];
  489. Hdr["Content-Length"]=Data.length+'';
  490. Hdr["Content-Type"]="application/x-www-form-urlencoded; charset=UTF-8"
  491. }
  492. //console.log('R: '+Url+'\nD: "'+Data+'"');
  493. GM_xmlhttpRequest({
  494. method: meth,
  495. url: Url,
  496. data: Data,
  497. headers: Hdr,
  498. onload: function(resp) {
  499. try{
  500. if(cb)
  501. cb(resp.responseText)
  502. else
  503. extractResult(resp.responseText);
  504. }catch(e){
  505. if(getId('divResult')){
  506. getId('divResult').innerHTML =
  507. '<a id="gttpErrRef" href="#">error processing response text:</a><br>'+e;
  508. getId('gttpErrRef').href=URL.subsr(0,99);}
  509. }
  510. }
  511. });
  512. }
  513.  
  514. function quickLookup(){
  515. gt_sl=getId('optSelLangFrom').value;
  516. gt_tl=getId('optSelLangTo').value;
  517. GT_tl=gt_tl;
  518. saveIt();
  519. gtRequest(txtSel,gt_sl,gt_tl);
  520. }
  521. function histLookup(e){
  522. try{
  523. var txt=e.target.textContent, ix=-1;
  524. //.innerHTML??
  525. e.preventDefault();
  526. var ha = getTag('a',getId('divHist'));
  527. // ix=ha.indexOf(e.target);
  528. /**/
  529. for(var i=0,l=ha.length; i<l; i++)
  530. if(e.target == ha[i]){ ix=i; break; }
  531. /**/
  532. if(ix<0) return;
  533. if(e.ctrlKey && e.altKey){ //remove itemm
  534. if(ix==0) return;
  535. killId('divHist');
  536. ht.splice(ix,1);
  537. GM_setValue('hist',JSON.stringify(ht));
  538. history();
  539. return;
  540. }
  541. var lang = ht[ix][2].match(/([a-zA-Z-]+)\|([a-zA-Z-]+)/);
  542. gt_sl=lang[1]; gt_tl=lang[2];
  543. txtSel = txt;
  544. getId('divResult').innerHTML = 'Loading...'
  545. gtRequest(txtSel,gt_sl,gt_tl);
  546. } catch(e){console.log('broken history\n'+e)}
  547. }
  548.  
  549. function fastSwap(){
  550. if(gt_sl != 'auto'){
  551. var t= gt_sl; gt_sl=gt_tl; gt_tl=t;
  552. gtRequest(txtSel,gt_sl,gt_tl);
  553. }
  554. }
  555.  
  556. function badResponce(html,e){
  557. var dr=getId('divResult')
  558. dr.innerHTML = '';
  559. var br=addEl(dr,'a',{'class':'gootranslink'},null,'Bad Google response');
  560. br.href=URL.substr(0,100);
  561. var m=html.match(/\<title\>(.*?)\<\/title\>/);
  562. if(m && m[1])
  563. addEl(dr,'p',{},null,m[1]);
  564. //id="captcha"
  565. m=html.match(/(<img\s.*?\>)/);
  566. if(m && m[1])
  567. addEl(dr,'p',{},null,m[1]);
  568. //_log(html);
  569. return;
  570. }
  571. var ex_sl , ex_tl;
  572. function extractResult(html){
  573. if(html){
  574. var html2 = html.match(/\<body[^\>]*\>([\s\S]+)\<\/body\>/);//[1];//select body content
  575. if(!html2){ // too many lettters!!!11
  576. badResponce(html); return;
  577. }
  578. html2 = html2[1].replace(/\<script[^\<]+\<\/script\>/ig, '');//remove script tags...
  579. killId('divExtract');
  580. divExtract = (new DOMParser()).parseFromString(html2, "text/html");
  581.  
  582. ex_sl= gt_sl, ex_tl=gt_tl;
  583. }
  584. try{ //gather info
  585. // 2013-10-20
  586. var _sl = detectedLang(gt_sl);
  587. var _tl = detectedLang(gt_tl);
  588. /* ?!11 150415 */ _log('**',_sl+'>'+_tl)
  589. if( 1 || ex_sl !== gt_sl )
  590. gt_sl_gms = _sl, gt_tl_gms =_tl;
  591. else
  592. gt_sl_gms = _tl, gt_tl_gms = _sl; /* ?!11 */
  593. getId('divBottom').removeChild(getId('optionsLink'));
  594. var oL= buildEl('div', {id:'optionsLink', title: 'Settings', 'class':''},
  595. null, null);
  596. addEl(oL,'a',{id:'optionsFrom','class':'gootransbutt gootranslink'},
  597. ['click', options], gt_sl_gms +' ');
  598. addEl(oL,'a',{id:'optionsFast','class':'gootransbutt gootranslink',
  599. title: 'swap languages'}, ['click', fastSwap], imgSwap);
  600. addEl(oL,'a',{id:'optionsTo','class':'gootransbutt gootranslink ' + (getId('divOpt') ? 'gtlActive':'gtlPassive')},
  601. ['click', options], gt_tl_gms );
  602. getId('divBottom').appendChild(oL);
  603. }catch(e){ console.log('gather\n'+e); }
  604. // var translation = getXId("result_box").textContent;
  605. // first run: resolve tl = auto
  606. if(GT_tl == 'auto')try{
  607. GT_tl=getXId("gt-tl").value;
  608. if(GT_tl) GM_setValue('to', GT_tl);
  609. else GT_tl='en';
  610. gt_tl=GT_tl;
  611. }catch(e){console.log('auto?\n'+e)}
  612.  
  613. //parse info
  614. var dR=getId('divResult');
  615. var tx='translating..';
  616. try{
  617. tx=getXId("result_box").textContent
  618. // console.log("result:\n"+tx);
  619. }catch(e){console.log("result_box\n"+e)}
  620. dR.innerHTML = '<a class="gootranslink gootransgoo" href="#'+
  621. '" target="_blank">' + tx + '</a>'; // +'<br>&nbsp;';
  622. dR.childNodes[0].setAttribute('href',currentURL); //<a href
  623. dR.childNodes[0].setAttribute('title',deURI(currentURL,"&text="));
  624. dR.style.textAlign = rtl_langs.indexOf(GT_tl) < 0? 'left':'right';
  625. dR.style.direction = rtl_langs.indexOf(GT_tl) < 0? 'ltr' : 'rtl';
  626. dR.lang=GT_tl;
  627. // dict();
  628.  
  629. }
  630.  
  631. function getSelection(t){
  632. var txt = '';
  633. //get selected text
  634. if (window.getSelection){
  635. txt = window.getSelection();
  636. }
  637. else if (document.getSelection) {
  638. txt = document.getSelection();
  639. }
  640. else if (document.selection) {
  641. txt = document.selection.createRange().text;
  642. }
  643. inTextArea= ( t&& t.type=='textarea' ) ? t : null
  644. if(inTextArea){
  645. txt=t.value.substr(t.selectionStart,t.selectionEnd-t.selectionStart);
  646. }
  647. return trim(txt);
  648. }
  649. function swapLang(){
  650. var to=getId('optSelLangTo').value,from=getId('optSelLangFrom').value;
  651. // if(from!='auto'){
  652. getId('optSelLangTo').value = from;
  653. getId('optSelLangFrom').value = to;
  654. quickLookup();
  655. // }
  656. }
  657.  
  658. function saveIt(){
  659. var bs =getId('gtp-save');
  660. bs && (bs.className ='gootranslink goounsaved');
  661. }
  662.  
  663. function options(evt){
  664. var dO = getId('divOpt');
  665. if(!dO){//show options
  666. dO = buildEl('div', {id:'divOpt' });
  667. var oL=getId('optionsLink');
  668. oL.title='Hide settings';
  669. //
  670. var dA=getId('divHist');
  671. if(dA){
  672. insAfter(dO,dA);
  673. }else if(( dA=getId('divSourceshow')) ){
  674. insAfter(dO,dA);
  675. }else{
  676. insAfter(dO,getId('divResult'));
  677. }
  678. //from
  679. addEl(dO,'a',{'class':'gootransbutt gootranslink',
  680. target:'_blank', href:senoj, title: 'choose country flag icon'},
  681. ['click',function(e){
  682. e.preventDefault(); GM_openInTab(senoj); cleanUp(); return false;}],
  683. imgH+imgFlags['AN']+imgT);
  684. addEl(dO,'span', null, null,' From: ');
  685. var gt_slist = getXId("gt-sl");
  686. gt_slist= gt_slist ? gt_slist.innerHTML+'' : languagesGoogle;
  687. /* console.log(gt_slist) /* !!! */
  688.  
  689. var oF =dO.appendChild(buildEl('select', {id:'optSelLangFrom'}, null, gt_slist));
  690. oF.value = GM_getValue('from', "auto");
  691. oF.addEventListener('change', quickLookup, false);
  692. // swap
  693. addEl(dO,'span', null, null,'&nbsp');
  694. addEl(dO,'a', {id:'opSelectLangSwap',href:HREF_NO, 'class':"gootranslink",
  695. title:'Swap languages',}, ['click', swapLang], imgSwap);
  696. //to
  697. addEl(dO,'span', null, null,' To:');
  698. var gt_tlist = getXId("gt-tl");
  699. gt_tlist= gt_tlist ? gt_tlist.innerHTML+'' : languagesGoogle;
  700. var oT =dO.appendChild(buildEl('select', {id:'optSelLangTo'}, null, gt_tlist));
  701. oT.value = GM_getValue('to', "auto");
  702. oT.addEventListener('change', quickLookup, false);
  703. //use ctrl
  704. addEl(dO,'br');
  705. addEl(dO,'span', null, null,'Use with: ');
  706. var d=addEl(dO,'input', {id:'checkCtrl', type:'checkbox'},
  707. ['change', saveIt], null );
  708. addEl(dO,'span', null, null,' Ctrl &nbsp;&nbsp; ');
  709. d.checked = GM_getValue('ctrl',false);
  710. // use alt
  711. d=addEl(dO,'input', {id:'checkAlt', type:'checkbox',
  712. title:'using Alt is highly recommended'},
  713. ['change', saveIt], null);
  714. addEl(dO,'span', null,
  715. null,' Alt &nbsp;&nbsp;&nbsp; History:&nbsp;');
  716. d.checked = GM_getValue('alt',true);
  717. // history depth
  718. d=addEl(dO,'input', {id:'histSize', type:'textbox', maxlength: 2,
  719. style: "width:2em; ", title: "set to 0 to clear history"});
  720. addEl(dO,'span', null, null,' items &nbsp; of ');
  721. d.value = maxHT;
  722. // max # words in phrase
  723. d=addEl(dO,'input', {id:'histWc', type:'textbox', maxlength: 1,
  724. style: "width:1em; ", title: "max # of words in phrase"});
  725. addEl(dO,'span', null, null,' words');
  726. d.value = maxWC;
  727. // source box params
  728. addEl(dO,'br');
  729. addEl(dO,'span', null, null,'Source box: &nbsp;');
  730. d=addEl(dO,'input', {id:'sourceBH', type:'textbox', maxlength: 1,
  731. style: "width:1em; ", title: "box height"});
  732. d.value = sourceBH;
  733.  
  734. addEl(dO,'span', null, null,' height &nbsp; ');
  735.  
  736. d=addEl(dO,'input', {id:'sourceDP', type:'textbox', maxlength: 2,
  737. style: "width:2em; ", title: "# of lines to keep"});
  738. addEl(dO,'span', null, null,' depth &nbsp; ');
  739. d.value = sourceDP;
  740.  
  741. addEl(dO,'span', null, null," No flags:");
  742. d=addEl(dO,'input', {id:'checkNoflags', type:'checkbox',
  743. title: "don't show country flag icons"});
  744. d.checked = GM_getValue('noFlags');
  745. // colours
  746. for(var b,li=BG.C.length,ii=0;ii<li;ii++){
  747. b=addEl(dO,'span',{'class':'gtBGColor', title:BG.t[ii],
  748. style: 'background:'+ BG.C[ii]+'!important;' +
  749. (ii==0?'margin-left:6px' :'')
  750. }, null,'&nbsp;');
  751. b.paletteN=ii;
  752. b.addEventListener('click',bgClick,false);;
  753. }
  754. //save
  755. var oS=
  756. addEl(dO,'div', {id:'gtp-save', 'class':'gootranslink gootransbutt',
  757. title: "save changes"},
  758. ['click', saveOptions], 'save');
  759. if(!GM_getValue('from'))
  760. saveIt();
  761. getId('optionsTo').className='gootransbutt gootranslink gtlActive';
  762. //cancel
  763. }
  764. else{//hide options
  765. killId(dO);
  766. getId('optionsLink').title = 'Settings';
  767. var oTL = getId('optionsTo');
  768. oTL.className='gootransbutt gootranslink gtlPassive';
  769. }
  770. }
  771. function showTrans(){
  772. try{
  773. var hOs = GM_getValue('showTrans',false) !== true;
  774. var shhi = hOs?'gtp-trans gtp-block':'gtp-trans gtp-hide';
  775. var tds= document.getElementsByClassName('gtp-trans');
  776. for(var i=0, il=tds.length; i<il; i++){
  777. tds[i].className=shhi;
  778. }
  779. getId('gtp_transOnOff').innerHTML = hOs?"&laquo;&laquo;":"&raquo;&raquo;";
  780. GM_setValue('showTrans',hOs)
  781. } catch(e){console.log('showTrans\n'+e)}
  782. }
  783.  
  784. function detectedLang(da){
  785. if(!da) return '';
  786. var gt_slist = getXId("gt-sl");
  787. //console.log(gt_slist.innerHTML)
  788. gt_slist= gt_slist ? gt_slist.innerHTML+'' : languagesGoogle;
  789. var re= new RegExp('ion value="'+da+'">(.*?)<\/opt');
  790. var ma= gt_slist.match(re);
  791. if(ma && ma[1]) return ma[1]; return da;
  792. }
  793.  
  794. function extractDict(txt){
  795. //console.log('!dict\n'+txt)
  796.  
  797. try{
  798. if(!txt) return;
  799. if(txt.substr(0,1) !== '[')
  800. throw 'Bad Google responce';
  801. txt=txt.replace(/,(?=,)/g,',""');
  802. txt=txt.replace(/\[(?=,)/g,'[""');
  803. var dA=JSON.parse(txt);
  804. var dL='';
  805. //translation
  806. if( dA && dA[0] && dA[0][0] ){
  807. var dR=getId('divResult');
  808. var tr = dA[0][0][0];
  809. for(var k=1;k<99;k++) {
  810. if ( dA && dA[0] && dA[0][k] && dA[0][k][0])
  811. tr+=dA[0][k][0];
  812. else break;
  813. }
  814. if(tr) tr=tr.replace(/\s([.,?!;:])/g,"$1");
  815. dR.childNodes[0].textContent=tr;
  816. dR.style.textAlign = rtl_langs.indexOf(GT_tl) < 0? 'left':'right';
  817. dR.style.direction = rtl_langs.indexOf(GT_tl) < 0? 'ltr' : 'rtl';
  818. dR.lang=GT_tl;
  819. addHistory(txtSel,tr);
  820. } else {
  821. getId('divResult').innerHTML='Google returns nothing!'; return;
  822. }
  823. // detected lang
  824. if(gt_sl=='auto' && dA[2]){
  825. var oF = getId("optionsFrom");
  826. oF.textContent= oF.textContent+' - '+detectedLang(dA[2]) +' ';
  827. }
  828. if(dA && dA[1] && dA[1][0] ){
  829. var da=dA[1];
  830. dL=buildEl('div',{id: 'gtp_dict'});
  831. var dT=addEl(dL,'table');
  832. var dB=addEl(dT,'tbody');
  833. var showT = 'gtp-trans gtp-hide',showI = "&raquo;&raquo;"
  834. if(GM_getValue('showTrans',false) === true)
  835. showT = 'gtp-trans gtp-block', showI = "&laquo;&laquo;"
  836. for(var i=0,il=da.length; i<il; i++){
  837. var tr=addEl(dB,'tr');
  838. addEl(tr,'td',{'class': 'gtp-pos'}, null, da[i][0]);
  839. for(var j=0,jl=da[i][2].length; j<jl; j++){
  840. tr=addEl(dB,'tr');
  841. addEl(tr,'td',{'class': 'gtp-word'}, null, da[i][2][j][0]);
  842. // console.log(JSON.stringify(da[i][2][j]))
  843. da[i][2][j][1]&&
  844. addEl(tr,'td',{'class': showT}, null, da[i][2][j][1].join(', '));
  845. }
  846. }
  847. var gtdir = (getId('divResult').style.direction=='rtl') ? 'left' : 'right';
  848. addEl(dL,'a',{'class': 'gootransbutt gootranslink', id: 'gtp_transOnOff',
  849. style: 'position: absolute; top: -.5em; '+gtdir+': 1px;'
  850. },['click', showTrans],showI);
  851. killId('gtp_dict');
  852. if(dL) getId('divResult').appendChild(dL);
  853. }
  854. killId('divSourceshow');
  855. killId('divHist');
  856.  
  857. if(GM_getValue('sourceShow',true))
  858. source();
  859. if(GM_getValue('histShow',false))
  860. history();
  861. if(!GM_getValue('histWc') && !getId('divOpt')) // no settings?
  862. options(); // show options
  863. } catch(e){
  864. _log('errexDict: '+e+'\n'+txt.substr(0,100));
  865. badResponce(txt,e);
  866. }
  867. }
  868. //https://translate.google.com/translate_a/single?client=t&sl=ru&tl=en&hl=ru&
  869. //dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&dt=at&ie=UTF-8&oe=UTF-8&otf=2&trs=1&inputm=1&ssel=0&tsel=0&source=btn&kc=3&tk=899279.760886
  870. function onTimerDict(){
  871. var q = dictURL +
  872. "&hl="+ GM_getValue('to','auto') +
  873. "&sl=" + gt_sl + "&tl=" + gt_tl +
  874. "&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&dt=at&ie=UTF-8&oe=UTF-8&otf=2&trs=1&inputm=1&ssel=0&tsel=0&source=btn&kc=3"+
  875. "&tk="+ampTK+
  876. "&q="+ escAp(txtSel);
  877. //console.log('dict:'+ dictURL);
  878. _log('?dict')
  879. Request(q, extractDict);
  880. }
  881.  
  882. function dict(){
  883. var dR=getId('divResult');
  884. killId('gtp_dict');
  885. // var dD=buildEl('div',{id:"gtp_dict"},null,dict)
  886. // dR.appendChild(dD);
  887. setZeroTimeout(onTimerDict);
  888. }
  889.  
  890. function saveSource(){
  891. try{
  892. sT = getId('divSourcetext').value;
  893. GM_setValue('sourceText',JSON.stringify(sT));
  894. }catch(e){console.log('saveSource\n'+e)}
  895. }
  896.  
  897. function source(){
  898. var divSource = getId('divSourceshow');
  899. try{
  900. if(divSource){
  901. killId(divSource);
  902. var sL = getId('sourceLink');
  903. sL.innerHTML = 'Source';
  904. sL.className = 'gootransbutt gootranslink gtlPassive'
  905. sL.title = 'Show source';
  906. killId('imgSourcesave');
  907. GM_setValue('sourceShow',false);
  908. return;
  909. }
  910. GM_setValue('sourceShow',true);
  911. divSource= buildEl('form', {id:'divSourceshow'}, null, null);
  912.  
  913. if(sT){
  914. var sTa= sT.split('\n');
  915. var tS= txtSel + ' \u2192 ' + trim(getId('divResult').childNodes[0].textContent);
  916. if(tS != sTa[0]){
  917. while(sTa.length >= sourceDP) sTa.pop();
  918. sT= tS + '\n' + sTa.join('\n');
  919. }
  920. }else sT=txtSel;
  921. if(!getId('imgSourcesave'))
  922. insAfter(
  923. buildEl('img',{id: 'imgSourcesave', title: 'save source', src: imgSave,
  924. style: 'margin-bottom: -3px;'},
  925. ['click', saveSource], null)
  926. ,getId('sourceLink'));
  927. addEl(divSource,'textarea',
  928. { id:'divSourcetext', rows: sourceDP,
  929. style: "font-family: Tahoma,sans-serif !important; height:"
  930. +(sourceBH+1)+"em;"
  931. }, null, sT),
  932. getId('divBottom');
  933. var sL=getId('sourceLink');
  934. sL.innerHTML = 'Source';
  935. sL.className= 'gootransbutt gootranslink gtlActive';
  936. sL.title = 'Hide source';
  937. }catch(e){console.log('Sourceshow\n'+e)};
  938. insAfter(divSource,getId('divResult'));
  939. }
  940. // ht: [from, to, langpair, hitCount]
  941.  
  942. function history(){
  943. var divHist = getId('divHist');
  944. try{
  945. if(divHist){
  946. killId(divHist);
  947. var hL = getId('historyLink');
  948. hL.innerHTML = 'History'; hL.className= 'gootransbutt gootranslink gtlPassive';
  949. hL.title = 'Translation history';
  950. GM_setValue('histShow',false);
  951. return;
  952. }
  953. if(!maxHT) return;
  954. GM_setValue('histShow',true);
  955. divHist = buildEl('div', {id:'divHist'},['click', histLookup], null );
  956. //
  957. for(var i=0, l=ht.length; i<l; i++){
  958. var bkg = ht[i][0].indexOf(' ')>0 ? ' goohistlink' : '';
  959. addEl(divHist,'a', {href:HREF_NO, 'class': 'gootranslink'+bkg, 'titel': ht[i][1]+
  960. ((ht[i][3]>1) ? '\u00A0'+ '['+ht[i][3]+']' : '')},
  961. null, ht[i][0]);
  962. if(i < l-1)
  963. divHist.appendChild(document.createTextNode(' '));
  964. }
  965. //addEl(divHist,'span',null,null,'<br>&nbsp;');
  966. if(getId('divSourceshow'))
  967. insAfter(divHist,getId('divSourceshow'));
  968. else
  969. insAfter(divHist,getId('divResult'));
  970. var hL=getId('historyLink')
  971. // hl.textContent = 'X';
  972. hL.title= 'Hide history';
  973. hL.innerHTML = 'History'; hL.className = 'gootransbutt gootranslink gtlActive';
  974. }catch(e){console.log('hist problem\n'+e)}
  975. }
  976.  
  977. function saveOptions(evt){
  978. try{
  979. var from = getId('optSelLangFrom').value;
  980. var to = getId('optSelLangTo').value;
  981. var ctrl = getId('checkCtrl').checked;
  982. var alt = getId('checkAlt').checked;
  983. var mh = parseInt(getId('histSize').value);
  984. var wc = parseInt(getId('histWc').value);
  985. var nf = getId('checkNoflags').checked;
  986. if(0<= mh && mh <=99 && mh<maxHT){
  987. while(ht && ht.length>mh) ht.pop();
  988. GM_setValue('hist',ht? JSON.stringify(ht):'');
  989. if(getId('divHist')){
  990. killId('divHist');
  991. history();
  992. }
  993. }
  994. maxHT=mh;
  995. var bh = parseInt(getId('sourceBH').value);
  996. if( 0< bh && bh <10) sourceBH = bh;
  997. var dp = parseInt(getId('sourceDP').value);
  998. if( 0< dp && dp <100) sourceDP = dp;
  999. if(1<= wc && wc <=9) maxWC=wc;
  1000. GM_setValue('histSize',maxHT)
  1001. GM_setValue('histWc',maxWC);
  1002. GM_setValue('from', from);
  1003. GM_setValue('to', to);
  1004. GM_setValue('ctrl', ctrl);
  1005. GM_setValue('alt', alt);
  1006. GM_setValue('sourceBH', sourceBH);
  1007. GM_setValue('sourceDP', sourceDP);
  1008. GM_setValue('noFlags',nf)
  1009. getId('divDic').removeChild(getId('divOpt'));
  1010. getId('optionsLink').title='Settings';
  1011. return;
  1012. }catch(e){console.log('saveOpnions\n'+e);}
  1013. }
  1014.  
  1015. function addHistory(src,trt){
  1016. if (!maxHT) return;
  1017. try{
  1018. var hts=GM_getValue("hist");
  1019. if( !hts ){
  1020. ht=[["google translator","Der Ubersetzer","en|de",0]];
  1021. hts=JSON.stringify(ht);
  1022. }
  1023. ht=JSON.parse(hts);
  1024. var st=trim(src+''); var tt = trim(trt+'');
  1025. var wc = (st.split(' ')).length;
  1026. if(wc>maxWC) return;
  1027. var lang=currentURL.match(/langpair=([a-zA-Z-\|]+)/)[1];
  1028. var ix=-1; // find word in hist
  1029. for(var i=0, l=ht.length; i<l; i++)
  1030. if(st==ht[i][0]){ ix=i; break; }
  1031. //if(ix==0) return; // nothing to do
  1032. var hits=0;
  1033. if(ix>=0){
  1034. hits=ht[ix][3];
  1035. if( (gt_sl+'|'+gt_tl) == ht[ix][2] && tt != ht[ix][1]) {
  1036. tt = ht[ix][1]; // don't touch my translasion
  1037. }
  1038. ht.splice(ix,1);
  1039. }
  1040. // if(hits<4)
  1041. hits++; // delete it by your own hands
  1042. if (ht.length>maxHT){
  1043. var minHit=99999; // which item shoud i remove?
  1044. for(i=ht.length-1;i>0;i--)
  1045. if(minHit>ht[i][3]) minHit=ht[i][3]
  1046. ix=ht.length-1;
  1047. for(var i=ix; i>0; i--)
  1048. if(minHit==ht[i][3]){ ix=i; break; }
  1049. ht.splice(ix,1);
  1050. }
  1051. ht.unshift([st,tt,lang,hits]);
  1052. GM_setValue('hist',JSON.stringify(ht));
  1053. } catch(e){console.log('addHist\n'+e);}
  1054. }
  1055. var senFlag = '';
  1056. function selFlag(e){
  1057. if(!isInited) {css(-1); isInited=true; }
  1058. killId('divSelflag');
  1059. setEscHnd();
  1060. var p = belowCursor(e,10,10);
  1061. var dsf = buildEl('div',{id:'divSelflag', style:
  1062. ';top:'+p.t+';left:'+p.l+';right:'+p.r +';bottom: auto'});
  1063. var sel=addEl(dsf,'select',{id: 'optSelFlag'},
  1064. null,languagesGoogle);
  1065. sel.value = GM_getValue('to',' en');
  1066. addEl(dsf,'span',null,null,'<br><br>');
  1067. addEl(dsf,'a', {href:HREF_NO, style:'padding: 3px 12px; margin-right: 2em;',
  1068. 'class':'gootransbutt gootranslink', title: "use icon"},
  1069. ['click', function(){saveFlag(true)}], '<b>OK</b>');
  1070. addEl(dsf,'a', {href:HREF_NO, style:'padding: 3px 4px;',
  1071. 'class':'gootransbutt gootranslink'},
  1072. ['click', function(){saveFlag(false)}],
  1073. '<b>Cancel</b>');
  1074. //
  1075. senFlag = e.target.src+'';
  1076. var sm = senFlag.match(/.+\/(.+)\.png/);
  1077. if(sm && sm[1]) senFlag= sm[1];
  1078. _log(senFlag);
  1079. if(senFlag) body.appendChild(dsf);
  1080. }
  1081. function saveFlag(tf){
  1082. if(tf && senFlag){
  1083. var s= 'l-'+getId('optSelFlag').value;
  1084. GM_setValue(s,senFlag);
  1085. _log(s+': '+senFlag );
  1086. }else _log('cant save flags' );
  1087. killId('divSelflag'); return;
  1088. }
  1089. var fCSS;
  1090. function flagClick(e){
  1091. e.preventDefault();
  1092. if(e.target.nodeName == 'IMG'){
  1093. _log('hit on: ' + e.target.alt);
  1094. selFlag(e);
  1095. }else (killId('divSelflag'));
  1096. }
  1097. function belowCursor(evt,ho,vo,lr){
  1098. var p={t:'', l:'auto', r:'auto'};
  1099. p.t=(evt.clientY+window.pageYOffset+vo)+'px';
  1100. var l=(evt.clientX+window.pageXOffset+ho)+'px';
  1101. if(lr && lr=='r')
  1102. { p.l=l; return p; }
  1103. var w = window.innerWidth;
  1104. var r=(w-(evt.clientX+window.pageXOffset)+ho);
  1105. // Q: How to detect visibility & thickess of vertical scrollbar?
  1106. r-=8; //
  1107. if(r<0) r= w/4;
  1108. r+='px';
  1109. if(lr && lr=='l')
  1110. { p.r=r; return p; }
  1111. if(evt.clientX < w/2)
  1112. p.l=l;
  1113. else
  1114. p.r=r;
  1115. return p;
  1116. }
  1117. var flagLang;
  1118. function getFlagSrc(lng, where){
  1119. if(!where) where = 'to';
  1120. if(GM_getValue('noFlags')) return imgFlags[where];
  1121. var fl='l-'+lng;
  1122. var flag = GM_getValue(fl,'');
  1123. if(!flag){
  1124. flag=imgFlags[lng];
  1125. if(!flag) return flag = imgFlags[where];
  1126. }
  1127. if(flag.indexOf('http')==0
  1128. //flag.indexOf('file') ==0
  1129. ||flag.indexOf('data:') ==0)
  1130. return flag;
  1131. flagLang=fl;
  1132. // flag= 'http .. /Flags/Panama.png;'
  1133. flag= senop+seno+flag+senoext;
  1134. flagRequest(flag);
  1135. return flag;
  1136. }
  1137. function flagRequest(f){
  1138. _log('load '+f);
  1139. GM_xmlhttpRequest({
  1140. method: 'GET',
  1141. url: f,
  1142. //binary: true,
  1143. overrideMimeType: "text/plain; charset=x-user-defined",
  1144. headers: {
  1145. "User-Agent": UA
  1146. ,"Accept": "image/png,image/*;q=0.8,*/*;q=0.5"
  1147. ,"Accept-Encoding": "gzip, deflate"
  1148. },
  1149. onload: function(resp) {
  1150. try{
  1151. flagStore(resp.responseText,f);
  1152. }catch(e){console.log('FlagRqst\n'+e);}
  1153. }
  1154. });
  1155. }
  1156. function flagStore(r,url){
  1157. if(r.indexOf("<head")>=0)
  1158. {
  1159. console.log("Banned!\n"+url);
  1160. GM_setValue(flagLang,url);
  1161. }
  1162. else
  1163. GM_setValue(flagLang,"data:image/png;base64," + b2b64(r));
  1164. }
  1165.  
  1166. function trim(s){
  1167. return (s+'').replace(/\s+/g,' ').replace(/^\s/,'').replace(/\s$/,'');
  1168. }
  1169.  
  1170. function killId(nod){
  1171. if(!nod) return;
  1172. var n = nod;
  1173. if(typeof n == 'string'){
  1174. n= getId(nod);
  1175. }
  1176. if(!n) return;
  1177. if(n.parentNode) n.parentNode.removeChild(n);
  1178. else _log('cant kill: '+nod)
  1179. }
  1180.  
  1181. function addEl(to,type, attrArray, eL, html){
  1182. return to.appendChild(buildEl(type, attrArray, eL, html));
  1183. }
  1184.  
  1185. function buildEl(type, attrArray, eL, html)
  1186. {
  1187. var node = document.createElement(type);
  1188. for (var attr in attrArray) if (attrArray.hasOwnProperty(attr)){
  1189. node.setAttribute(attr, attrArray[attr]);
  1190. }
  1191. if(eL){
  1192. //console.log('buildEl\n'+type+'\n'+JSON.stringify(attrArray)+'\n'+eL[0])
  1193. node.addEventListener(eL[0], eL[1], eL[2]?true:false);
  1194. }
  1195. if(html)
  1196. node.innerHTML = html;
  1197. return node;
  1198. }
  1199.  
  1200. function getId(id, parent){
  1201. if(!parent)
  1202. return document.getElementById(id);
  1203. return parent.getElementById(id);
  1204. }
  1205.  
  1206. /* */
  1207. function getXId(id){
  1208. var r=divExtract.getElementById(id);
  1209. if(r) return r;
  1210. throw "Xel bug " + id;
  1211. }
  1212.  
  1213. function getTag(name, parent){
  1214. if(!parent)
  1215. return window.document.getElementsByTagName(name);
  1216. return parent.getElementsByTagName(name);
  1217. }
  1218. /*
  1219. * Drag and drop support adapted fom http://www.hunlock.com/blogs/Javascript_Drag_and_Drop
  1220. */
  1221. var savedTarget=null; // The target layer (effectively vidPane)
  1222. var orgCursor=null; // The original mouse style so we can restore it
  1223. var dragOK=false; // True if we're allowed to move the element under mouse
  1224. var dragXoffset=0; // How much we've moved the element on the horozontal
  1225. var dragYoffset=0; // How much we've moved the element on the verticle
  1226. var didDrag=false; //set to true when we do a drag
  1227. function moveHandler(e){
  1228. if (e == null) return;// { e = window.event }
  1229. if ( e.button<=1 && dragOK ){
  1230. savedTarget.style.left = e.clientX - dragXoffset + 'px';
  1231. savedTarget.style.top = e.clientY - dragYoffset + 'px';
  1232. return false;
  1233. }
  1234. }
  1235. function dragCleanup(e) {
  1236. document.removeEventListener('mousemove',moveHandler,false);
  1237. document.removeEventListener('mouseup',dragCleanup,false);
  1238. savedTarget.style.cursor=orgCursor;
  1239. dragOK=false; //its been dragged now
  1240. didDrag=true;
  1241. }
  1242. function dragHandler(e){
  1243. var htype=moz+'grabbing';
  1244. if (e == null) return;//
  1245. var target = e.target;// != null ? e.target : e.srcElement;
  1246. orgCursor=target.style.cursor;
  1247. if(target.nodeName!='DIV' )
  1248. return;
  1249. if( e.ctrlKey || e.altKey || e.shiftKey)
  1250. return; // enable selection inside
  1251. else if(clickedInsideID(target, res_dict))
  1252. return;
  1253. if (target = clickedInsideID(target, 'divDic')) {
  1254. savedTarget=target;
  1255. target.style.cursor=htype;
  1256. dragOK=true;
  1257. dragXoffset = e.clientX-target.offsetLeft;
  1258. dragYoffset = e.clientY-target.offsetTop;
  1259. //set the left before removing the right
  1260. target.style.left = e.clientX - dragXoffset + 'px';
  1261. target.style.right = null;
  1262. document.addEventListener('mousemove',moveHandler,false);
  1263. document.addEventListener('mouseup',dragCleanup,false);
  1264. return false;
  1265. }
  1266. }
  1267. function clickedInsideID(target, id) {
  1268. if (target.getAttribute('id')==id)
  1269. return target;
  1270. if (target.parentNode) {
  1271. while (target = target.parentNode) {
  1272. try{
  1273. if (target.getAttribute('id')==id)
  1274. return target;
  1275. }catch(e){}
  1276. }
  1277. }
  1278. return null;
  1279. }
  1280. //end drag code
  1281. function b2b64(inp) { // binary data --> base64
  1282. var output = [], c1, c2, c3, e1, e2, e3, e4, i = 0;
  1283. var k="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  1284. var len = inp.length;
  1285. while( i < len ){
  1286. c1 = inp.charCodeAt(i++); c2 = inp.charCodeAt(i++); c3 = inp.charCodeAt(i++);
  1287. e1 = (c1&255) >> 2;
  1288. e2 = ((c1 & 3) << 4) | ((c2&255) >> 4);
  1289. e3 = ((c2 & 15) << 2) | ((c3&255) >> 6);
  1290. e4 = c3 & 63;
  1291. if( isNaN(c3)) e4 = 64;
  1292. if( isNaN(c2)) e3 = 64;
  1293. output.push( k.charAt(e1) + k.charAt(e2) + k.charAt(e3) + k.charAt(e4));
  1294. } return output.join("");
  1295. }
  1296.  
  1297.  
  1298. function ttrans( s, ttab ){
  1299. for( var c, cc, t='', il=s.length, i=0; i<il; i++ )
  1300. t += (c=ttab[cc=s.charAt(i)]) ? c : cc;
  1301. return t;
  1302. }
  1303. //var tabUrlEsc = { '#':'%23', '%':'%25', '&':'%26', '.':'%2e', '/':'%2f', '?':'%3f' };
  1304. function escAp(s){
  1305. return encodeURI(s);
  1306. //return ttrans( s, tabUrlEsc );
  1307. }
  1308.  
  1309. function stickStyle(css){
  1310. var s=document.createElement("style"); s.type="text/css";
  1311. s.appendChild(document.createTextNode(css));
  1312. return (document.head||document.documentElement).appendChild(s);
  1313. }
  1314. function css(n){
  1315. var k,i=0;
  1316. _log('cssN:',n);
  1317. if(-1 === n){ try{
  1318. k= +(GM_getValue('backG',0));
  1319. if(0<=k && k< BG.C.length) i=k;
  1320. } catch(e){};}
  1321. else GM_setValue('backG', +(i=+n) );
  1322. try{
  1323. if(window.gttpCSS) window.gttpCSS.parentNode.removeChild(window.gttpCSS);
  1324. }catch(e){console.log('cssX:\n'+e)};
  1325. _log('cssS:'+i,BG.C[i]);
  1326. window.gttpCSS=
  1327. stickStyle((
  1328. '#divResult {overflow: auto !important; padding:3px !important; margin: 0 0 3px 0 !important; max-height: 480px !important;}'+
  1329. '#divResult table *{ line-height: 0.9 !important}'+
  1330. '#divDic, #divDic div,#divLookup, #divUse {padding: 0; margin:0; \
  1331. width: auto;height: auto; border: none; border-radius: 0; background: none;}'+
  1332. '#divDic, #divDic *, #divSelflag, #divSelflag *{\
  1333. font-family: Tahoma, sans-serif!important;\
  1334. font-size: small!important;\
  1335. font-style: normal!important;\
  1336. font-weight: normal!important;\
  1337. font-stretch: normal!important;\
  1338. letter-spacing: normal!important;\
  1339. line-height: 1.1;\
  1340. }'+
  1341. '#divDic,#divSelflag {position: absolute; background:'+BG.C[i]+'!important; color:'+FG.t[i]+
  1342. '!important; opacity: 1'+
  1343. ';padding:5px !important; margin:0; z-index:10000; border-radius:5px; border: thin solid gray'+
  1344. ';text-align: left !important;}'+
  1345. '#divDic{ max-width:50%; padding: 3px; margin: 0;}'+
  1346. '#divSelflag{ max-width: 180px; }'+
  1347. '.gootranslink, #divDic .gootranslink ,#divSelflag .gootranslink\
  1348. {color:'+FG.l[i]+'!important; text-decoration: none !important;\
  1349. font: small normal Tahoma,sans-serif !important;'+
  1350. 'cursor:pointer !important; }' +
  1351. '#divDic a.gootranslink:visited,\
  1352. #divDic a.gootranslink:hover,\
  1353. #divDic a.gootranslink:active\
  1354. {color:'+FG.l[i]+'!important; text-decoration: none !important;}' +
  1355. '#gtp_dict table{background:'+BG.C[i]+'!important;}'+
  1356. '#gtp_dict tr {background:'+BG.H[i]+'!important;line-height:1;}'+
  1357. '#gtp_dict tr>td{font-size:1em !important; line-height:1!important;\
  1358. background:transparent!important;'+
  1359. '}'+
  1360. 'a.goohistlink {background:'+BG.F[i] +';}'+
  1361. '#gtp_dict {margin: 0; position: relative;}'+
  1362. '#gtp_dict ol {padding: 0 .5em 0 0; margin-left: 0.2em;}'+
  1363. '#gtp_dict li {list-style: square inside; display: list-item;}'+
  1364. 'div#gtp_dict tr>td {padding-left: .25em; vertical-align:top; border: none; color:'+FG.t[i]+'; }'+
  1365. '#optSelLangFrom,#optSelLangTo {max-width: 150px; text-align: left !important; height: 1.5em;\
  1366. }'+
  1367. '#divDic input{vertical-align: baseline !important;}'+
  1368. '#divDic input[type="checkbox"]{vertical-align: text-bottom !important;}'+
  1369. '#divResult a.gootranslink.gootransgoo{font-size: 1em !important; line-height: 1;}'+
  1370. '#divOpt span {color:'+FG.t[i]+'!important;}'+
  1371. '#optSelLangFrom,#optSelLangTo,#divDic input[type="textbox"]{background:'+BG.E[i]+'!important;\
  1372. color:'+FG.t[i]+'!important;\
  1373. padding-bottom: 3px !important; margin-bottom: 4px!important;}'+
  1374. '#divExtract{word-spacing: normal !important;}'+
  1375. '#divBottom {position: relative; width: 100%; font-size: smaller; text-decoration:none; }'+
  1376. '#historyLink {display: inline; position: relative; font-size:smaller; text-decoration:none;}'+
  1377. '#sourceLink {display: inline; position: relative; margin-left: 1em; font-size:smaller; text-decoration:none;}'+
  1378. '#imgSourcesave {display: inline; position: relative; margin-left:2px;\
  1379. cursor:pointer;}'+
  1380. 'div#optionsLink {display: inline; position: relative; margin-left: 1.5em; font-size:smaller !important; text-decoration:none !important;}'+
  1381. '#divDic #optionsLink [id^="options"] {margin-right: 2px; padding-left: 2px;}'+
  1382. '#divOpt {position: relative; padding: 5px;'+
  1383. 'border-top: thin solid grey!important;}'+
  1384. '#divLookup, #divOpt, #divBottom,#divSourcetext,#divHist,#divuse {direction: ltr !important;}'+
  1385. 'div#divDic #divHist {background:'+BG.C[i]+'; position:relative; padding:5px; text-align:left !important;'+
  1386. 'border-top: thin solid grey!important; color:'+FG.t[i]+';}'+
  1387. 'div#divResult #gtp_dict {background:'+BG.C[i]+'; color:'+FG.t[i]+';\
  1388. padding:3px!important; border-radius:3px;'+
  1389. 'margin-bottom: .1em!important; overflow-y:auto !important; overflow-x:hidden; font-size:small;}'+
  1390. '#divOpt {background:'+BG.C[i]+'; position:relative; padding:5px; text-align:left !important;}'+
  1391. '#divLookup, #divUse {background-color:transparent !important; position:absolute;\
  1392. padding: 3px; margin: 0;}'+
  1393. 'div#divDic>#divSourceshow {\
  1394. border: none; padding: 0 0 4px 0; margin: 0;}'+
  1395. '#divSourceshow>#divSourcetext{ width:97%; height: 3em; line-height: 1.2; overflow: auto !important;\
  1396. padding: 0 0 0 4px; margin: 0; border: none; border-top: 1px solid #AAA}' +
  1397. '.gtlPassive:before{ content:"\u2193";}'+
  1398. '.gtlActive:before{ content:"\u2191" !important;}'+
  1399. '#imgUse, #divGetback, #divGetforw {margin-left: 5px !important; cursor: pointer;}'+
  1400. '#divSourcetext {background:'+BG.E[i]+'!important; color:'+FG.t[i]+'!important;}'+
  1401. '#divSelflag .gootransbutt, #divDic .gootransbutt {background:'+BG.T[i]+'!important;'+
  1402. 'border-radius: 3px; margin-top: 5px; }'+
  1403. '#divDic .goounsaved {background-color: #EF9024!important;'+
  1404. 'border-radius: 3px; margin-top: 5px; }'+
  1405. 'td.gtp-pos { color:'+FG.t[i]+'!important; font-weight: bold !important; text-align: left; }'+
  1406. 'td.gtp-pos:before{ content:"\u2666 "; color:'+FG.t[i]+'!important;}'+
  1407. 'td.gtp-word {color:'+FG.t[i]+'!important; padding-left: 5px; padding-right: 10px;'+
  1408. 'vertical-align: top; white-space: normal;}'+
  1409. 'td.gtp-trans {/*overflow-x: hidden;*/ vertical-align: top; white-space: normal;'+
  1410. ' width: 100%; color:'+FG.g[i]+'!important}'+
  1411. 'td.gtp-pos, td.gtp-word, td.gtp-trans {padding-bottom: 0px !important; padding-bottom: 1px !important;}'+
  1412. '.gtp-hide {display: none}'+
  1413. '.gtp-block {display: block}'+
  1414. '#divTtsIfr{position: relative;padding: 0!important;margin:3px 0 0 0!important;\
  1415. background:'+ BG.C[i] +'!important;}'+
  1416. '')
  1417. );
  1418.  
  1419. if(-1 !== n) return;
  1420. stickStyle(
  1421. '#divDic, #divDic textarea, #divDic iframe {resize: both !important; }'+
  1422. '#divDic *::'+(isChrome?'':moz)+'selection {background: #047 !important; color: #FC8 !important; }'+
  1423. '#divUse img, #divDic img, #divLookup img {display: inline; width: auto; height: auto; }'+
  1424. '#divTtsLnk:after{ content:url('+imgPlay+') }'+
  1425. '#divTtsLnk {padding: 0 2px; margin: 0 3px 0 5px;}'+
  1426. '#divTtsIfh {width: 100%;overflow-x:hidden;\
  1427. background-color: rgba(127,127,127,.25); padding: 3px 0;\
  1428. }'+
  1429. '#divResult, #divResult div, #divResult table, #divResult tr, #divResult tr td,\
  1430. #divResult a, #divBottom, \
  1431. #divOpt select, #divOpt input, .gootranslink\
  1432. { padding:0 0 0 0; margin: 0 0 0 0; background: none repeat scroll 0 0 transparent;\
  1433. border: none; line-height: 0.95; float: none}'+
  1434. '#divOpt {line-height: 2.3 !important;}\
  1435. div#divBottom{padding-top: 3px;}\
  1436. .gootransbutt#optionsLink{margin-top:0; padding-top: 3px; padding-bottom: 1px;}\
  1437. #divOpt .gtBGColor{ border:thin solid blue !important; cursor: pointer;\
  1438. padding-right:6px; margin-right: 2px;}\
  1439. .gootranslink[titel]{position: relative;}\
  1440. .gootranslink[titel]:after {\
  1441. color: #050;\
  1442. content: attr(titel);\
  1443. position: absolute;\
  1444. visibility: hidden;\
  1445. opacity: 0.25;\
  1446. left: 16px;\
  1447. top: 32px;\
  1448. min-width: 0px;\
  1449. width: auto;\
  1450. white-space: pre !important;\
  1451. -moz-hyphens: none !important;\
  1452. text-decoration: none !important;\
  1453. border: 1px #aaa solid;\
  1454. border-radius: 6px;\
  1455. background-color: #dfd;\
  1456. padding: 1px 4px;\
  1457. font-size: small; line-height:0.9;\
  1458. -webkit-transition: all .2s linear .2s;\
  1459. transition: all .2s linear .2s;\
  1460. z-index: 2147483647;\
  1461. }\
  1462. .gootranslink[titel]:hover:after {\
  1463. visibility: visible;\
  1464. opacity: 1;\
  1465. -webkit-transition: all .5s linear .7s;\
  1466. transition: all .5s linear .7s;\
  1467. }\
  1468. #divOpt #gtp-save{\
  1469. position: absolute; right: 2px;; bottom: -1.3em;\
  1470. font-weight: bold; cursor: pointer; z-index: 999999;\
  1471. }\
  1472. ');
  1473. }
  1474. function insAfter(n,e){
  1475. if(e.nextElementSibling){
  1476. e.parentNode.insertBefore(n,e.nextElementSibling);
  1477. }else{
  1478. e.parentNode.appendChild(n);
  1479. }
  1480. }
  1481. function insBefore(n,e){
  1482. e.parentNode.insertBefore(n,e);
  1483. }
  1484. var imgH='<img border=0 src="' , imgD='data:image/png;base64,',imgT='">';
  1485. var imgPlay=imgD+
  1486. 'iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAI1JREFUeNpj+H9h4v//D7YRh4FqGf6vsvuPF4PAnnQ4n+H/At3/WDEIgOjTvQg2EDP8ny7/HwWDAIy+sxnBvr0RzGb43y/0H45hAMR+fAQrm+F/B/t/DAASe3gQK5vhfwsDpgaQ2IP9WNkQDTBMsgaYJhgNcgqMfWUZDg3oGveUINh4NSBrnGdGggY0DAAAy70TuBaoTgAAAABJRU5ErkJggg=='
  1487. ;
  1488.  
  1489. //http://www.senojflags.com/images/national-flag-icons/Portugal-Flag.png
  1490. imgForwSrc= imgD+
  1491. 'R0lGODlhEAAQAIQfAAFYsQJkw15iWgRz3AeN0Xl8c2mBiQma5B6W1h+b3yqh4BKp+kWk0pudlDC2/0y79X+4z1fC/7q6r3DK/4rN7a3Kz8fKwc/Uyr3c5N7dzuTi1Ofl1enm2O3r3/b06////yH+EUNyZWF0ZWQgd2l0aCBHSU1QACH5BAEKAB8ALAAAAAAQABAAAAWf4OeNXmdyX6qKpNSc25p6TVEIgl1osljntxxPNrIILhrDZBl5OBaLj6mTa1CWk+YTOpXgsBEM5gFdmDLBiJrC2VCgB85lYJFcmg+MPAPnDP4aGg4ODxsVFBkPBwd/jRuDFBoQDxkVix+NHwBQSBmeFwoEHwEDAQEAAJQVDAwQFxCipqeoABkMiwcWFqKjpqgEBLjAwDIAHwoJyQkIzB8hADs=';
  1492. imgForw = imgH+imgForwSrc+imgT;
  1493.  
  1494. imgBackSrc= imgD+
  1495. 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAAXNSR0IArs4c6QAAAGBQTFRFEgAAAVixAmTDXmJaBHPcB43ReXxzaYGJCZrkHpbWH5vfKqHgEqn6RaTSm52UMLb/TLv1f7jPV8L/urqvcMr/is3trcrPx8rBz9TKvdzk3t3O5OLU5+XV6ebY7evf9vTrdcYePwAAAAF0Uk5TAEDm2GYAAAABYktHRACIBR1IAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAoklEQVQY003PWxKDIAwF0CCPYouCKIIB7f532UTttPfvnkkyE4Ar+3Ecb8pdoRGM859UY4yUxow/4CpPcM6HuCzLoxaZacV9IY1G0mWGsG0sUs4M1rnU9hRjpCt4AZZ9CyGWOauyg7UB09qC97UqpRhWDFNN3jfFAf0qiFiLcwK4g57KNAw0JUTXqY4gZ2vtgEKwMFBItL47QN/3T8oLxPnVB4gUDOnY6pKLAAAAAElFTkSuQmCC';
  1496. imgBack = imgH+imgBackSrc+imgT;
  1497.  
  1498. imgSwap = "<img border=0 style="+'"margin-bottom: -3px;"'+
  1499. "src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAQCAYAAAD52jQlAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAGFJREFUOMu1kkESwCAIAxM+7vTlevJipYKkOWeWQAB2ar2jIFMD31ABEACYBj5kLKkooX9TGTSwUqZQusbToOnd+CxbQiQxXeMccPEVrNzOA//YvkKp9SNnWQo2ZcK6PgocHMgoj3uaTsAAAAAASUVORK5CYII='>";
  1500.  
  1501. imgUse = imgD+ 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACQklEQVR42mNkoBAwgoiwykntQCoeTW7hqva8SmINeGZv7yCJLHHw4IHnQAOkCBoQXjdnJpBOI9MHsxhDa2b9z4v2xir7/z8QgyCU/gdi/GMA00CKYc7qnQyMwdUz/icGuSFp+s/w+cs3hqPHzzK8fPUGzBcVE2EwMzVk4OTkhGgG4X//GTbtPsTAGFgx5X9iiCfYFpDE+/cfGTZv28Ogr6vJ8A7ItjQ3ZLhy/Q7DxUvXGVxcHRj4+PgY/kIN2LH3IAOjX8mE//Gh3gz/oU7bu+8wg4S4CIOBnjbDlFmLGRLiIxnYWJgYzl+4wvD0+WsGSxtLhr///kPVHmBg9Cns+R8d7At32rJlaxnCw/0Y/vxjYli2dBVDaEQI2DZmoA0r12xg8A30hxgAxIcPAg3wzOv4HxrgDRb4C/TGmtXrGbx9PBmYWFgZVq9YA4wnRoa/f/4xeAf4MOzYsp3B3dcH7oVTR4FecMtq+e/r7QExAIhPnzzFwMsnwKCkqsIgwM0OVgwKnzPnrjB8/PCeQdPAEO7aCyeOMDC6pDf8d3V1AQv8BcXN758Mu3YfZJBXUmQQl5YCGszA8OzJE4ZH9+4z2DnYMPxkZAGrBYXZtbPHGBgdk2v+2zo6AQX+g21jY2FmALqZ4cyZCwxv3rwFKmZgEBYWYjAw1GP4zcDE8O3nb4gBQPFb508wMNonVv7XNzYFGwBzGgsTEwMvFwfI+8DkAzQPGDgfvn1n+PHrLzhdwMDDG5cYGK0iC/8zUABAmcmAEgMA4i8z829X6pgAAAAASUVORK5CYII=';
  1502.  
  1503. imgSave= imgD+
  1504. 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACgklEQVR42mNkAIL4tTeX/P36xnpBtCXDolN3GYS42Bn8dGUYGBkZGWBg/+0XDFOOPfzDxSOw8enZg5X729N/g8TBKuJWX/v++d0TjnVprgx2vZsY1MT4GebE2jMgg93XnzBMPnKXgYdPhOE/A8OiFRE68XADolZc+v7u+V2O7QUBDMbNyxg0JAQZlqZ6ohiw/fIDhr6DNxgEhSTB/P///9euiTFsARsQtuTs96ePb3PsLgpmOPfoJQM3GyuDgZwYigErHxQw3P/wnoGVhR2kmeH05aivt/bsFQEbELjg5PfHT+5y/Pj5i4GZiYkBG0iIqGZgYvwH5x89O4Xh1t6zCmADPGce+s7LycrBAPIdDmBuHAkM1L8IA870AQ04DzHAdere70CKgwEPcLFNAboAYcCR050Md/ZDDXCcuJMIA7IYGJmQvHCqieHugQsQA2z7tnzXEBfgEOXBbQa7VBSQRDLgdA0Dw4fDEAMsuzZ835nrxfH/zx+GP38QzvwP1DD3VjDDp7+PcZl7AWyAadua7weK/Tm+ff3G8Ov3HxQV7//eYVh8O5Xh3/+/KOL//jEzvHvBaw02wLBp+fcj5cEcL16+Y/j67QeGNZe/rmE4+XYxitj9Rw4Ml7Z9h3hBp27x95NV4RwvXmE34C/Q9lUPKhne/rkL5qsKGzIcOefLcGbXFogBmtXzvx9JUeHgYsWeiEDg1dcnDB3Xe4Bpn5GhUquUIXPzL4azB/YpMLb0T+E6+o1nryLrI2Nmhn8gEyBZEJkEhScwjX3geQMS+s//RfjfvV9Sz0x4/xszLlmyRAmUFIBYGogFgZgbmiZYgJgZFmZADMq+P4H4CxB/AOKnQHwQALc2/z+3odafAAAAAElFTkSuQmCC';
  1505.  
  1506. imgFlags= {
  1507. 'AN': imgD+
  1508. 'iVBORw0KGgoAAAANSUhEUgAAABgAAAAQCAYAAAAMJL+VAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAABANJREFUOMutlEtsVHUUh797//c10955F2hKM7QUEUgNoRAqSUGJESO6ACSyIKgJwSXGGFJ2mhijG2JE3WgiiSaCAQlVeagIhAYID4GIgKU4lGdbhs5MZ+bemft0UXGBukF/y7M4X07OOR/8T9n84eebNm3ZuvPBuvJgYcvOg8r573a0zF62uqP/zM/JUdvX8T1f1fRqV+vkQu74gXsqoaUaRlSbt2zaxby1UJs2e929WR1tSzqSdH/15RMnThw7fL+ftP7tj41hueG5eDK12GzJLp3a0vxoImaKCyNlLuWrnBvKU8oXWZoKKVoOZ4suoSyBAIQGWpSIEaFnWoLH2zOkhs9d2Lh8aed9gBh7ZuOVk+acDeVU68JEzJwUNxQ5Kgc4rk/ZsqnYNWJBnZ+eb+bZVp3V0xvoTAvSIkTyXUZqPh4SrqSQ1AQzOmdNsq/8Ovr7wOXTALJ3sX8/jkXZsig7PlU3oFGRWTA5QlRT8YRKBQULQdEDTYKeKRF6uzJ8s7yZBSkBnsvtksXVgs1vt0qse++Dd2a2t6UARFs2Gx/p6FkVeh7pRp2kJpBkyJoqm+el6Zli0Ds3jl338fwAz/MJQvDCEMsL6Z6kkxtzGbICbARJTZBpyhiPTElmDu/t6xNJr3LN6V652XJdYoZOKqKS0AS2H7B9sMqqbBQ5CHA9nyCcAIRB8OcGwdRkNnQm2X/D5nrFQ1NVTEWma1H3vKuH9v0g8oWC0/TYoqfHjUSrUASZBp2ELohrMhU/ZElLFE1iAuD7BEGA7/oTABlCwPF9xj2J4yMOViBIGAIzFiXmFg0B0JROTy1ku54kDCYAhoqpyUQViU8vV2iOSnTEBL7nI4UBvj8xRQhIEmgyHLxR5XzJpx4CqkG6fu/uZ6+99LICYFZG9ymq9pZVsynaDhUnQs0LSRgyqajgzXPjtGs+cxs87oxZxHGYGQlpMWUCwJBlTt2pQKACUaxisbC994W1lmUNCIDh3MDtzOIVr1cCWddVhUxUJxZRiGkybgDjTsipuzbbLxU5ervKj9fKhI7DyvZGnCBkz1CFHTkL3TRpvXn6THHrq2uK+ZF+IPzrk7XBk31M71lbsuqUa3UsR8cxQkxFolETxKMGRmMES5ZBM9hVrPP93hKBW8coj461DJ057p7e/8X1awPfBlD5myoy1uiRm0JdW7FrlGp1qnWXWqBiGhpNTREKnkz5yvnB6i/HLgS3ruYoDef0ejnnDudy+bHSTQfKQPCvLiod2bXbnP/iJ2XbpWg5WEInlPAv9W070r/n692DJ48esF33hqmKetn1w4cyYnPvtrO8ezSc8f6h4vxVr2yNRiJz/kmID53ZK9a/MfWpNR9FFJGduPL/nj8ActPaP8mCkKMAAAAASUVORK5CYII='
  1509. ,'en': imgD+
  1510. 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAJJSURBVHjapJNdSJNRGMd/Z3u3OTXXhx8xjRLDFWIk0jAk6WYYfaAZSUWGZkFdRNRFYAYFXhkI2gpKqISC1IsIUiKIchUEUQiuj4uiMT8m0wbNr+n2vu/p4l2K3Yn/m3Pg8Pye8/wf/kJKyWokACuQnjxXojgwowCOwPW2iS37y3k0bOfJwwHmYzFePK5n7Oxl0FRyH9zicGM3CZOFBhccypMox2tJdWZnK0Bay/AGmr+McmJvKUXbaul79hmTzYJ9x3bQdEw2C2V7XOzLUdmVZ2PWvZvm1lcAaQpg/vY9xL2NRdRMvqHUlYmzoRw9oREPjICqoic0qtIiFGVmECp20+kd4IPPD2AWQMFMcOSnxWZDavqyIcfOXARVJ7fLu9w4s4nEwgLpmzdtVQB+HW0kNcOBFo3Cv6VICWYTSEmw6hSYBOjGo7LOwdz0lHEHiMVimCciaNEpRLIWqSMUxWCpKgiBEAIJqI4M5tLtS4Cs++3kZGUlK5cUcFciEwkKBl//t3xBeHIS3KWYAEo87biruxiKWkh568N/447RWZdI3fAlMG8l5Z2PT00deOq6KfHcBjAA+YVO+p6eo8zXy/P+r9R9tCcbCQQCgIMHOuh3llFx2kNn/jjFhWuXAN6rFay/66XtZZjG9zrh0KjxVasCNgsAs9N/OHnkJq0/HLjOH+NadmjRg7jW00tnWOPKQGRxzEH/EOM7XUhNI+of4nckCEDThRaCl2qor66E/p64ABxALrBmhVmYBsYEYE4GybxCgAbExWrj/HcACIPUyGtYcDcAAAAASUVORK5CYII='
  1511. ,'fr': imgD+
  1512. 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAFESURBVHjapJM7TsNAEIa/9RqjKECEkGgoKOgoaHKCdByBc3APDsIRaHID01ASRTxEgxI5zsvetb1DkcSJCUaKMtJqZzSrb2f/nVEiwj6mgAA4Wu67mAWmPtDqdB6+f2e73ftK3L+92yJcPT2e+0CzKBzt9uW/1zVurpc1KxBh/vwC0PQBbW3BeJwyHE5rAebto/T9s1MkywC0D2CMJYpmRNG8FuBG49IvPE1u0wUMIEkMg8GMOJ5T9yn5KC59AWxiNgEJvV5GHCf1kvffS1+3Tkh9bw1I0wSRBs65ehU3cpJlpJnbBBi0PsS5+qaSFUBAihyTWwC8hYgG50ApVa6tjlvlPAVOSIxdV2CtJQiEIPDrnxAcVKoxdi2iFSmYTD4r58MwrMSvcfSntgpoARfA8Y6zMAG+FKCXg6R3BBSAVfuO888AocKXohfLXWQAAAAASUVORK5CYII='
  1513. ,'ru': imgD+
  1514. 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAADkSURBVHjapJM5TgNBEEVfzeZlQIOE5ARxClLOxC04CzFX4ArERAhZsoTEyDDurqa7SGxsIYJZKqnov9p+iZkxJQSogLN9HhIKfBZAY2abUdVFVhlQT5igzoB8AiDPAGKMg5UHTQFwc/fI6rKh/VLsz4b/u9FFXbF5b4+AnXe8rIW2C72qN8uSwtwJoHMwm5NSP0+EbyP4E8DD0z3XZUnqdr0A2XLBawjcHgBOPZYXINILYMlw6o8deFVsvoCq7AewhFf9BWg047n9GOMDFaABroDzgeIt8CZ7J1YjHBkBlanv/DMAwHdYum9dlZQAAAAASUVORK5CYII='
  1515. ,'zh-CN': imgD+
  1516. 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAFbSURBVHjapJO/SgNBEIe/vduLCSaKFhb6DCnFzs4XsMgjWlj4AD6BFhYKFqKgTSzSaBLN7f+xuJM7RSHRHywLy8w3Oz9mlIjwHymgA/TrexU54E0Dm+Pj0QSACGRADt39gLnQTZkftHd2uqOBdYmR3uGQYjfhnzPSXJHeYTCK2Lu8AquGJYC9vgFY10AupUdvTekdTYgnGvdYVQ5P0nTa+kW+vYV4D5BrgGAt9nZOmCzwDxlxkqG60D0ImCsN/msbKs+J1gKgAXww+Kcp5nKBKgQ0rA09i/Oi8iR880HAGdMATFnSuX8kzWZ8vvqHJvi7idnGBibPGkBZlvSzDJFURfj6FC1ISyl4SpcagDUWVRRISi2ngPTL8PiArUysW3AW0RqUWmqCRATjWiZaa6HbQxXFcjOYUpVTA1wU4eb15S+r4BSwCewBgxWT58BY1XZ16nsVRcCp/67zxwDGd5ld8bkQAQAAAABJRU5ErkJggg=='
  1517. ,'ar': imgD+'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAIvSURBVHjapJPNSxRxHMY/M/Ob3bXddV3DBTUh8yJdCiHwIIV0DXqB7nWLDv0NBt06Rt3q0E0PGaFBmGSGUCZKQR6ENV8wddfVfZ35zW/mN9NByd4u4nP5Hr7wgYfneYwoijiODCAGpA7uUaSAugAyN0aHCn9//TAg0BoAYZrYlv0P4cX1oZwAkjrUnMv1ABBFEX6oaU+1cibbARGsVbZZrxWxTRPDMAH4UsgDJAVg+WFATTmUZBWtNVd7L3Ktux9ZaxBvShDriTO2/InhxSlMA042NeOHAYAlADzfpyIbFBplLp/u42bnBRzHYWVjHa01bdlWrnT0sV4t8mppBmFYeL4PgAkgPUnJq9LQHpdyvbizn9koFgl8n3gsxlZ5D39+gcFsDwrNjqwiPXkIcKVHvrxJwa3SIgOcmRkCIUil0+yUSkTxOLsfpmltKHaVQ778A1d6vwMcwlBTk3W2kzaJ5VWyc/Ns1euYmWbK468xZ+cpZBJU3CphqHGls58QgJQSO2njKo+RlY8M3L3Dzq3bdHSdoimdRn9bpO3xEx5tLrDn1MidaMGX8hCgpIeIkqTsBCMLb+gebOfe2Cjm+ASh72M+uM9T1ng28ZKUnSCKQtSBhf0UlCJBREzY2Jbg4fvnTHadpX/gPKZpMLc0zOzqV2xLYBkmIRGeUr8AKtIh5fzmHy2b/v6Oyam3YIDAIi5s5H/qbAAZoBNIH3ELNWDDAKyDIVlHBGhAGced888BANVaBfgg0AbGAAAAAElFTkSuQmCC'
  1518. ,"af":"Namibia" //
  1519. ,"sq":"Albania"
  1520. //,"ar":"United-Arab-Emirates"
  1521. ,"hy":"Armenia"
  1522. ,"az":"Azerbaijan"
  1523. ,"eu":"Spain"
  1524. ,"be":"Belarus"
  1525. ,"bn":"Bangladesh"
  1526. ,"bs":"Bosnian"
  1527. ,"bg":"Bulgaria"
  1528. ,"ca":"Spain"
  1529. ,"ceb":"Philippines"
  1530. ,"ny":"Mozambique"
  1531. /* ,"zh-CN":"Chinese"*/
  1532. ,"hr":"Croatia"
  1533. ,"cs":"Czech-Republic"
  1534. ,"da":"Denmark"
  1535. ,"nl":"Netherlands"
  1536. /*, "en":"English"*/
  1537. ,"eo":"United-Nations"
  1538. ,"et":"Estonia"
  1539. ,"tl":"Philippines"
  1540. ,"fi":"Finland"
  1541. /* ,"fr":"France"*/
  1542. ,"gl":"Ukraine"
  1543. ,"ka":"Georgia"
  1544. ,"de":"Germany"
  1545. ,"el":"Greece"
  1546. ,"gu":"India"
  1547. ,"ht":"Haiti"
  1548. ,"ha":"Nigeria"
  1549. ,"iw":"Israel"
  1550. ,"hi":"India"
  1551. ,"hmn":"Laos"
  1552. ,"hu":"Hungary"
  1553. ,"is":"Iceland"
  1554. ,"ig":"Nigeria"
  1555. ,"id":"Indonezia"
  1556. ,"ga":"Ireland"
  1557. ,"it":"Italy"
  1558. ,"ja":"Japan"
  1559. ,"jw":"Japan"
  1560. ,"kn":"India"
  1561. ,"kk":"Kazakhstan"
  1562. ,"km":"Cambodia"
  1563. ,"ko":"North-Korea"
  1564. ,"lo":"Laos"
  1565. ,"la":"Vatican-City"
  1566. ,"lv":"Latvia"
  1567. ,"lt":"Lithuania"
  1568. ,"mk":"Macedonia"
  1569. ,"mg":"Madagascar"
  1570. ,"ms":"Malaysia"
  1571. ,"ml":"India"
  1572. ,"mt":"Malta"
  1573. ,"mi":"New-Zealand"
  1574. ,"mr":"India"
  1575. ,"mn":"Mongolia"
  1576. ,"my":"Burma" //absent
  1577. ,"ne":"Nepal"
  1578. ,"no":"Norway"
  1579. ,"fa":"Iran"
  1580. ,"pl":"Poland"
  1581. ,"pt":"Brazil"
  1582. ,"pa":"Pakistan"
  1583. ,"ro":"Romania"
  1584. /*, "ru":"Russia"*/
  1585. ,"sr":"Serbia"
  1586. ,"st":"Lesotho"
  1587. ,"si":"Sri-Lanka"
  1588. ,"sk":"Slovakia"
  1589. ,"sl":"Slovenia"
  1590. ,"so":"Somalia"
  1591. ,"es":"Spain"
  1592. ,"su":"Sudan"
  1593. ,"sw":"Mozambique"
  1594. ,"sv":"Sweden"
  1595. ,"tg":"Tajikistan"
  1596. ,"ta":"India"
  1597. ,"te":"India"
  1598. ,"th":"Thailand"
  1599. ,"tr":"Turkey"
  1600. ,"uk":"Ukraine"
  1601. ,"ur":"Pakistan"
  1602. ,"uz":"Uzbekistan"
  1603. ,"vi":"Viet-Nam"
  1604. ,"cy":"Wales"
  1605. ,"yi":"Israel"
  1606. ,"yo":"Nigeria"
  1607. ,"zu":"South-Africa"
  1608. };
  1609. imgFlags['zh-TW'] = imgFlags['zh-CN'];
  1610. imgFlags['to'] = imgForwSrc; imgFlags['from'] = imgBackSrc;
  1611.  
  1612. languagesGoogle = '<option value="auto">Detect language</option>\
  1613. </option><option value="af">Afrikaans</option><option value="sq">Albanian</option><option value="ar">Arabic</option><option value="hy">Armenian</option><option value="az">Azerbaijani</option><option value="eu">Basque</option><option value="be">Belarusian</option><option value="bn">Bengali</option><option value="bs">Bosnian</option><option value="bg">Bulgarian</option><option value="ca">Catalan</option><option value="ceb">Cebuano</option><option value="ny">Chichewa</option><option value="zh-CN">Chinese</option><option value="hr">Croatian</option><option value="cs">Czech</option><option value="da">Danish</option><option value="nl">Dutch</option><option value="en">English</option><option value="eo">Esperanto</option><option value="et">Estonian</option><option value="tl">Filipino</option><option value="fi">Finnish</option><option value="fr">French</option><option value="gl">Galician</option><option value="ka">Georgian</option><option value="de">German</option><option value="el">Greek</option><option value="gu">Gujarati</option><option value="ht">Haitian Creole</option><option value="ha">Hausa</option><option value="iw">Hebrew</option><option value="hi">Hindi</option><option value="hmn">Hmong</option><option value="hu">Hungarian</option><option value="is">Icelandic</option><option value="ig">Igbo</option><option value="id">Indonesian</option><option value="ga">Irish</option><option value="it">Italian</option><option value="ja">Japanese</option><option value="jw">Javanese</option><option value="kn">Kannada</option><option value="kk">Kazakh</option><option value="km">Khmer</option><option value="ko">Korean</option><option value="lo">Lao</option><option value="la">Latin</option><option value="lv">Latvian</option><option value="lt">Lithuanian</option><option value="mk">Macedonian</option><option value="mg">Malagasy</option><option value="ms">Malay</option><option value="ml">Malayalam</option><option value="mt">Maltese</option><option value="mi">Maori</option><option value="mr">Marathi</option><option value="mn">Mongolian</option><option value="my">Myanmar (Burmese)</option><option value="ne">Nepali</option><option value="no">Norwegian</option><option value="fa">Persian</option><option value="pl">Polish</option><option value="pt">Portuguese</option><option value="pa">Punjabi</option><option value="ro">Romanian</option><option value="ru">Russian</option><option value="sr">Serbian</option><option value="st">Sesotho</option><option value="si">Sinhala</option><option value="sk">Slovak</option><option value="sl">Slovenian</option><option value="so">Somali</option><option value="es">Spanish</option><option value="su">Sundanese</option><option value="sw">Swahili</option><option value="sv">Swedish</option><option value="tg">Tajik</option><option value="ta">Tamil</option><option value="te">Telugu</option><option value="th">Thai</option><option value="tr">Turkish</option><option value="uk">Ukrainian</option><option value="ur">Urdu</option><option value="uz">Uzbek</option><option value="vi">Vietnamese</option><option value="cy">Welsh</option><option value="yi">Yiddish</option><option value="yo">Yoruba</option><option value="zu">Zulu</option>\
  1614. ';
  1615.  
  1616. /* */
  1617. try{
  1618. body=
  1619. window.document.body;
  1620.  
  1621. maxHT=GM_getValue('histSize');
  1622. if(!maxHT) maxHT=20;
  1623. maxWC=GM_getValue('histWc');
  1624. if(!maxWC) maxWC=3;
  1625. sourceBH = GM_getValue('sourceBH',3);
  1626. sourceDP = GM_getValue('sourceDP',10);
  1627. if(!sourceDP) sourceDP = 10;
  1628.  
  1629. var av = GM_getValue('version');
  1630. if( av!= version ){
  1631. GM_setValue('version',version);
  1632. }
  1633. sT=GM_getValue('sourceText');
  1634. if (sT){
  1635. try{
  1636. sT=JSON.parse(sT);
  1637. }catch(e){console.log('broken source\n'+e)} ;
  1638. } else sT='';
  1639.  
  1640. // gmail spoils my timeout -- workaround
  1641. // borrowed from dbaron.org/log/20100309-faster-timeouts :
  1642. // Only add setZeroTimeout to the window object, and hide everything
  1643. // else in a closure.
  1644. // (function() {
  1645.  
  1646. var setZeroTimeout,handleMessage,
  1647. timeouts = [],
  1648. messageName = "zero-timeout-150727";
  1649. // Like setTimeout, but only takes a function argument. There's
  1650. // no time argument (always zero) and no arguments (you have to
  1651. // use a closure).
  1652. if(!isChrome){
  1653. setZeroTimeout= function (fn) {
  1654. timeouts.push(fn);
  1655. window.postMessage(messageName, "*");
  1656. },
  1657. handleMessage= function(event) {
  1658. if (event.source == window && event.data == messageName) {
  1659. event.stopPropagation();
  1660. if (timeouts.length > 0) {
  1661. var fn = timeouts.shift();
  1662. fn();
  1663. } } }
  1664. } else {
  1665. setZeroTimeout= function (fn) {
  1666. window.setTimeout(fn,1);
  1667. }
  1668. }
  1669.  
  1670. window.addEventListener("message", handleMessage, true);
  1671. // Add the one thing we want added to the window object.
  1672. //window.setZeroTimeout = setZeroTimeout;
  1673. // })();
  1674.  
  1675. document.addEventListener('mouseup', showLookupIcon, false);
  1676. document.addEventListener('mousedown', mousedownCleaning, false);
  1677. // http://www.senojflags.com/#flags16
  1678. if( location.href.indexOf(senojflags[0])>-1
  1679. ||location.href.indexOf(senojflags[1])>-1
  1680. ){try{
  1681. var f16=getId('flags16');
  1682. if(f16){
  1683. if(!fCSS) fCSS=
  1684. 'div#flags16 img {cursor: pointer !important}'+
  1685. 'div#flags48,div#flags32 {display:none; visibility: hidden}';
  1686. stickStyle(fCSS);
  1687. _log('inside\n' + location.href);
  1688. insBefore(buildEl('div',{style:'font: bold italic 100% sans-serif; color:red;',
  1689. align:'left'},null,'&nbsp;&nbsp;<u>Click on a country flag icon then choose the language</u>'),
  1690. f16);
  1691. f16.addEventListener('click',flagClick,false);
  1692. }
  1693. }catch(e){console.log('senojflags\n'+e)}
  1694. }
  1695. }catch(e){console.log('nobody\n'+e); }
  1696.  
  1697. function deURI(u,m){
  1698. if(!m) m= "&q=";
  1699. var x = u.indexOf(m);
  1700. if(x>=0) u=u.substr(x + m.length);
  1701. return decodeURIComponent(u).split(' ').slice(0,9).join(' ');
  1702. }
  1703. var uq=location.href.match(/^https:\/\/translate\.google\.[a-z]{2,3}\/translate_tts\?client\=t\&.+?(\&q\=.+)/);
  1704. if(uq && uq[1])
  1705. window.document.title=deURI(uq[1]);
  1706.  
  1707. GM_registerMenuCommand("translate.google tootip", function(){
  1708. txtSel = getSelection(null) || txtSel;
  1709. var p = {t: (pageYOffset+10)+"px",l:(window.pageXOffset+50)+"px", r:"auto" }
  1710. if(!isInited) {css(-1); isInited=true; }
  1711. var divLookup = buildEl('div', {id:'divLookup', style: 'z-index:10000'+
  1712. ';border: none;' +
  1713. ';top:' + p.t +';left:' + p.l +';right:' + p.r +';bottom: auto'
  1714. }, null, null);
  1715. if(!txtSel) txtSel="Google Translator";
  1716. body.appendChild(divLookup);
  1717. lookup();
  1718. }
  1719. );
  1720.  
  1721. }
  1722. main();
  1723. }