translate.google tooltip

Translates selected text into a `tooltip' via Google translate

当前为 2015-04-18 提交的版本,查看 最新版本

  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.6.1
  14. //* This is a descendant of lazyttrick's http://userscripts.org/scripts/show/36898.
  15. // 3.6.1 2015-04-17
  16. // + selectable background color
  17. // * bugfixes
  18. // 3.5.1 2015-04-15
  19. // + TTS: alt-select text inside tooltip and shift-click language icon below
  20. // * From<->To buttons fix; * err handler
  21. // 3.4.1 2015-04-09 * GT changes: GET prohibited - use POST
  22. // 3.0.0
  23. // - national flags icons -- from www.senojflags.com
  24. // 2.3
  25. // - new editable 'source text' field
  26. // 2.2.2
  27. // - backward translation - select text inside tooltip and click the icon under your selection.
  28. // 2.2.1
  29. // - Ctrl-Alt-click removes item from the history of translations
  30. // - Ability to change translation in the history -
  31. // select desired translation in the tooltip window using ctrl or alt -
  32. // which one is checked in your settings - then click on the icon below the selection.
  33. // 2.2
  34. // - history of translations
  35. // 2.1.2
  36. // - Selected text is fetched in the moment when you hover over the icon.
  37. // So, you can select a few letters, then adjust your selection using shift + arrows.
  38. // 2.0.0d
  39. // - native GT languages list
  40. // 2.0.0c
  41. // Alt key option added
  42. // If something goes wrong:
  43. // Tools->SQLite manager-> Database-> Connect_database->
  44. // %YourBrowserProfile%\gm_scripts\translate.google_tooltip.db ->
  45. // scriptvals-> alt/ctrl <- false
  46. // 2.0.0b
  47. // - exit by ESC
  48. // - 1k letters limit -- don't strain your Google
  49. //
  50. //*/
  51. // /grant GM_addStyle
  52. // @grant GM_getValue
  53. // #grant GM_log
  54. // @grant GM_openInTab
  55. // @grant GM_setValue
  56. // @grant GM_xmlhttpRequest
  57. // @icon data:image/jpg;base64, R0lGODlhIAARALP/AAAAAP///xMYfAqf////Zv/qDuCeH8VmB8DAwAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAgALAAAAAAgABEAQASdEMlJgb00awkMKQZYjB8RBsE4AtLQvtt0sXHcEcT1pbxK0hsXRmYIGUUgA3DiQjQtssInRAjglMsa4ibtlqSGgECQymmaAwDYUhSFfKoQDQ3LdA6Hoh6qbW4sJHpFWTUAOEA3Vj1WZjF+HQU9X18oPxl0Wx4kXoFiZF1zMEJgbW8qJnAHoU4takocpW5IIISYGh1HRlh9hRZ4eIRaEQA7
  58. //
  59. // ==/UserScript==
  60. if(document.body){
  61. main = function (){// "use strict";
  62. var GTsuffix=".com"; // ".fr" ".de" ".ru" ".com"
  63.  
  64. var GTurl= "https://translate.google"+GTsuffix+"/?";
  65. var dictURL= "https://translate.google"+GTsuffix+"/translate_a/t?client=t";
  66. var ttsURL= "https://translate.google.com/translate_tts?client=t";
  67. var version= 3600;
  68.  
  69. var HREF_NO = 'javascript:void(0)';
  70.  
  71. var llii=0, _log = function(){ /* * /
  72. for (var s=++llii +':', li=arguments.length, i = 0; i<li; i++)
  73. s+=' ' + arguments[i];
  74. console.log(s)
  75. /* */
  76. }
  77.  
  78. var URL='*';
  79. var GT_tl='auto';
  80. var body;
  81.  
  82. var senojflags = [
  83. "http://www.senojflags.com/?gootttp#"
  84. ];
  85. //
  86. //function GM_log(t){console.log(t);}
  87.  
  88. const res_dict='gt-res-dict'; //'gt_res_dict';
  89. var languagesGoogle, isInited=false;
  90. var rtl_langs="ar fa iw ur";
  91. var inTextArea= null;
  92. var maxHT=20, maxWC=3;
  93. var sourceBH = 3, sourceDP =10;
  94. var ht=null; // history table,
  95.  
  96. var imgForw,imgBack,imgSwap,imgUse,imgSave,imgFlags,imgForwSrc,imgBackSrc;
  97. var txtSel; // text selected
  98. var currentURL, Qtxt='***';
  99. var gt_sl_gms, gt_tl_gms, gt_sl, gt_tl;
  100.  
  101. var sT;
  102. var noMup=0;
  103. var BG={
  104. t: ["yellow" ,"grey" ,"blue" ,"green" ,"pink" ],
  105. C: ['#FFFFE1','#D1D1D1','#D3ECED','#C4FFC4','#FFE6E6' ],
  106. T: ['#DDDDAA','#A0A097','#8CCCCE','#6BEF69','#FFC6C8' ],
  107. H: ['#F9E78F','#C1C1B7','#BCD1D1','#AAEEAA','#E8D0D0' ],
  108. f: [function(){css(0)}, function(){css(1)},function(){css(2)},
  109. function(){css(3)}, function(){css(4)}]
  110. }
  111.  
  112. function mousedownCleaning(evt){
  113. var divDic = getId('divDic');
  114. var divLookup = getId('divLookup');
  115. var dU = getId('divUse');
  116. var t=evt.target;
  117. noMup=0; // patch :/
  118. if(divDic) {
  119. if(!clickedInsideID(evt.target,'divDic')){
  120. evt.preventDefault(),evt.stopPropagation();
  121. if(dU && clickedInsideID(t,'divUse')){
  122. if(clickedInsideID(t,'divGetback')) forwLookup(evt); else
  123. if(clickedInsideID(t,'divGetforw')) backLookup(evt); else
  124. if(clickedInsideID(t,'imgUse')) useClick(evt); else
  125. _log('x3 click');
  126. return;
  127. }
  128. else
  129. cleanUp('MC');
  130. } else killId(dU);
  131. }
  132. killId(divLookup);
  133. }
  134.  
  135. var documentcontentEditable=false;
  136. var documentdesignMode = '';
  137. var divExtract;
  138. function cleanUp(s){
  139. _log(s);
  140. var d=getId('divSourcetext');
  141. if(d) sT= d.value;
  142. killId('divDic');
  143. killId('divExtract');
  144. killId('divLookup');
  145. killId('divUse');
  146. killId('divBack');
  147. killId('divSelflag');
  148. //divExtract='';
  149. if(documentcontentEditable)
  150. documentcontent.Editable=documentcontentEditable,
  151. documentcontentEditable = false;
  152. if(documentdesignMode == 'on')
  153. document.designMode='on',
  154. documentdesignMode=null;
  155. }
  156.  
  157. function useClick(e){
  158. killId('divUse');
  159. if(e.shiftKey) ht[0][1] += ' '+txtSel;
  160. else ht[0][1] = txtSel;
  161. GM_setValue('hist',JSON.stringify(ht));
  162. if(getId('divHist')){
  163. killId('divHist');
  164. history();
  165. }
  166. }
  167. var last_tl, last_sl;
  168. function backLookup(e){
  169. if(e.shiftKey) {
  170. noMup=1;
  171. ttsRequest(txtSel,gt_tl);
  172. return;
  173. }
  174. killId('divUse');
  175. gtRequest(txtSel,gt_sl,gt_tl);
  176. currentURL = GTurl + "langpair=" + gt_sl + "|" + gt_tl + "&text=" + escAp(txtSel);
  177. }
  178. //GET https://translate.google.com/?langpair=en|ru&text=Varnish
  179. //POST https://translate.google.com/translate_a/t?client=t&hl=ru&sl=en&tl=ru&text=Varnish
  180. function forwLookup(e){
  181. if(e.shiftKey) {
  182. noMup=1;
  183. ttsRequest(txtSel,gt_sl);
  184. return;
  185. }
  186. killId('divUse');
  187. var t=gt_tl; gt_tl=gt_sl; gt_sl=t;
  188. gtRequest(txtSel,gt_sl,gt_tl);
  189. currentURL = GTurl + "langpair=" + gt_sl + "|" + gt_tl + "&text=" + escAp(txtSel);
  190. }
  191. var Gctrl, Galt;
  192. var sayTip="\n[shift] listen (";
  193. function showLookupIcon(evt){
  194. Gctrl=GM_getValue('ctrl',false), Galt=GM_getValue('alt',true);
  195. if((!evt.ctrlKey && Gctrl)
  196. ||(!evt.altKey && Galt)
  197. // to avoid collision
  198. ||(evt.ctrlKey && !Gctrl)
  199. ||(evt.altKey && !Galt)
  200. ) return;
  201. evt.preventDefault(),evt.stopPropagation();
  202.  
  203. var divDic = getId('divDic');
  204. var divLookup = getId('divLookup');
  205. txtSel = getSelection(evt.target)+'';
  206. if(txtSel.length>1024){
  207. return;
  208. }
  209. //exit if no text is selected
  210. if(!txtSel || txtSel===""){
  211. _log('S:notext ')
  212. if(divDic) {
  213. if(!clickedInsideID(evt.target,'divDic'))
  214. cleanUp('no sel');
  215. }
  216. if(divLookup){
  217. killId(divLookup);
  218. }
  219. return;
  220. }
  221. //possible cleanup
  222. if(divDic){
  223. if(!clickedInsideID(evt.target,'divDic'))
  224. {cleanUp('!divdic'); return; }
  225. // inside divDic:
  226. var dU=getId('divUse');
  227. if(dU){
  228. if(!clickedInsideId('divUse')){
  229. killId(dU);
  230. } return;
  231. }
  232. try{
  233. var p= belowCursor(evt,10,10,'r');
  234. var divUse= buildEl('div', {id:'divUse',
  235. style:'z-index:11000; border: none'+
  236. ';top:' + p.t +';left:' + p.l +';right:' + p.r +';bottom: auto;'
  237. }, null, null );
  238.  
  239. var iTo = getFlagSrc(gt_tl,'to');
  240. var divForw=buildEl('span', {id:'divGetforw', // 'class': 'gootranslink', href: HREF_NO,
  241. //border: 0, src: iTo,
  242. title: gt_sl_gms + '\u2192 '+gt_tl_gms +sayTip+gt_tl+')'},
  243. null, imgH+iTo+imgT);
  244. // ['mousedown', forwLookup], imgH+iTo+imgT);
  245. divUse.appendChild(divForw);
  246. var iFrom = getFlagSrc(gt_sl,'from');
  247. var divBack=buildEl('span', {id:'divGetback', //'class': 'gootranslink', href: HREF_NO,
  248. //border: 0, src: iFrom,
  249. title: gt_tl_gms + '\u2192 '+gt_sl_gms +sayTip+gt_sl+')'},
  250. null, imgH+iFrom+imgT);
  251. // ['mousedown', backLookup], imgH+iFrom+imgT);
  252. gt_sl !='auto' && divUse.appendChild(divBack);
  253.  
  254. addEl(divUse,'img',{id: 'imgUse', border: 0,
  255. title: 'use in history\n[shift] add to history', src: imgUse},
  256. null,null);
  257.  
  258. // tp=(evt.clientY+window.pageYOffset+30)+'px';
  259. // lf=(evt.clientX+window.pageXOffset+30)+'px';
  260. body.appendChild(divUse);
  261. }catch(e){console.log('use hist\n'+e)}
  262. return;
  263. }
  264. // inside page
  265. if(!isInited) {css(-1); isInited=true; }
  266. //remove div if exists
  267. if(divLookup)
  268. killId(divLookup);
  269. //div container
  270. p = belowCursor(evt,10,10);
  271. divLookup = buildEl('div', {id:'divLookup', style: 'z-index:10000'+
  272. ';border: none;' +
  273. ';top:' + p.t +';left:' + p.l +';right:' + p.r +';bottom: auto'
  274. }, null, null);
  275.  
  276. iTo = getFlagSrc(GM_getValue('to'),'to');
  277. var iForw=buildEl('img', {'border':0, id:"imgLookForw", style: 'padding-left: 5px',
  278. src: iTo}, ['mouseover', lookup],null);
  279. var sl=GM_getValue('from','auto');
  280. iFrom = getFlagSrc(sl,'from');
  281. var iBack=buildEl('img', {'border':0, id:"imgLookBack", style: 'padding-left: 5px',
  282. src: iFrom},
  283. ['mouseover', lookup], null);
  284. if(p.r == 'auto' ){ // left half
  285. divLookup.appendChild(iForw);
  286. sl != 'auto' && divLookup.appendChild(iBack);
  287. }else{ // right half
  288. sl != 'auto' && divLookup.appendChild(iBack);
  289. divLookup.appendChild(iForw);
  290. }
  291. body.appendChild(divLookup);
  292. }
  293. function escCleanup(e){
  294. if(!e.shiftKey && !e.ctrlKey && !e.altKey && e.keyCode==27 )
  295. cleanUp('esc');
  296. }
  297.  
  298. function lookup(evt){
  299. var divResult = null;
  300. var divDic = getId('divDic');
  301. var divLookup = getId('divLookup');
  302. var top = divLookup.style.top;
  303. var left = divLookup.style.left;
  304. var rite = divLookup.style.right;
  305. var txtS = txtSel; // 2012-08-20
  306. txtSel = getSelection(inTextArea? inTextArea: evt.target)+'';
  307. if(!txtSel) txtSel = txtS;
  308. if(txtSel.length>1024){
  309. return;
  310. }
  311. //exit if no text is selected
  312. if(!txtSel || txtSel==""){
  313. _log('L:notext')
  314. if(divDic) {
  315. if(!clickedInsideID(evt.target,'divDic'))
  316. killId(divDic);
  317. }
  318. killId('divLookup');
  319. killId('divDic');
  320. return;
  321. }
  322. //cleanup divs
  323. killId('divDic');
  324. killId('divLookup');
  325. //div container document.body.clientHeight/Width
  326. divDic = buildEl('div',
  327. {id:'divDic', style: 'top:'+top+';left:'+left+';right:'+rite
  328. });
  329. divDic.addEventListener('mousedown', dragHandler, false);
  330. document.addEventListener('keydown', escCleanup, false);
  331. body.appendChild(divDic);
  332. // patch gmail
  333.  
  334. if(document.contentEditable)
  335. documentcontentEditable = document.contentEditable,
  336. document.contentEditable = false;
  337. if(document.designMode == 'on')
  338. documentdesignMode='on',
  339. document.designMode='off';
  340.  
  341. //div result
  342. divResult = buildEl('div',
  343. {id:'divResult'}, null, 'Loading...');
  344. divDic.appendChild(divResult);
  345. /**/
  346. // history
  347. var divBottom = buildEl('div',{id:'divBottom', align: 'bottom'},null,null);
  348. addEl(divBottom,'a',
  349. {'class':"gootransbutt gootranslink gtlPassive", id:'historyLink', title: 'Translation history',
  350. align: 'left', href:HREF_NO},
  351. ['click', history], 'History');
  352. addEl(divBottom,'a',
  353. {'class':"gootransbutt gootranslink gtlPassive", id:'sourceLink', title: 'Source', href:HREF_NO},
  354. ['click', source],'Source');
  355. //options link
  356. addEl(divBottom,'a',
  357. {'class':"gootransbutt gootranslink gtlPassive", id:'optionsLink', title: 'Settings', href:HREF_NO},
  358. ['click', options], 'Options');
  359. divDic.appendChild(divBottom);
  360. /**/
  361. //lookup
  362. gt_sl = GM_getValue('from', 'auto');
  363. GT_tl = (gt_tl = GM_getValue('to',GT_tl));
  364. if( evt.target.id== 'imgLookBack' ){
  365. var t=gt_tl; gt_tl=gt_sl; gt_sl=t;
  366. }
  367. //"http://www.google.com/translate_t?text=" + txtSel + "&langpair=" + lang;
  368. gtRequest(txtSel,gt_sl,gt_tl);
  369. }
  370.  
  371. function ttsRequest(txt,t){
  372. var etxt = escAp(txt);
  373. etxt=ttsURL + "&tl=" + t + "&ie=utf-8&q=" + etxt.split(' ').slice(0,19).join(' ');
  374. _log('tts> '+etxt);
  375. GM_openInTab(etxt);
  376. // sorry, firefox' decodeAudioData() does NOT support mp3
  377. }
  378.  
  379. function gtRequest(txt,s,t){
  380. var etxt = escAp(txt);
  381. currentURL = GTurl + "langpair=" + s + "|" + t + "&text="+etxt ;
  382. etxt=GTurl + "langpair=" + s + "|" + t + "&text=" + etxt.split(' ').slice(0,9).join(' ');
  383. if( !((s==last_sl && t==last_tl) || (s==last_tl && t==last_sl)) || (divExtract=='')){
  384. var c=':';
  385. //_log(s+c+last_sl+ ' '+t+c+last_tl + ' '+ divExtract );
  386. divExtract = '';
  387. Request(etxt);
  388. }else{
  389. extractResult(null);
  390. }
  391. last_sl = s; last_tl = t;
  392. }
  393.  
  394. function Request(url,cb){
  395. URL=url; _log('R: '+URL);
  396. var meth=cb? 'POST': 'GET';
  397. GM_xmlhttpRequest({
  398. method: meth,
  399. url: url,
  400. headers: {
  401. "User-Agent": navigator.userAgent
  402. ,"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
  403. ,"Accept-Encoding": "gzip, deflate"
  404. //,"Host": "www.google.com"
  405. },
  406. onload: function(resp) {
  407. try{
  408. if(cb)
  409. cb(resp.responseText)
  410. else
  411. extractResult(resp.responseText);
  412. }catch(e){
  413. if(getId('divResult'))
  414. getId('divResult').innerHTML =
  415. '<a id="gttpErrRef" href="#">error processing response text:</a><br>'+e;
  416. getId('gttpErrRef').href=URL.subsr(0,99);
  417. }
  418. }
  419. });
  420. }
  421.  
  422. function quickLookup(){
  423. gt_sl=getId('optSelLangFrom').value;
  424. gt_tl=getId('optSelLangTo').value;
  425. GT_tl=gt_tl;
  426. saveIt();
  427. gtRequest(txtSel,gt_sl,gt_tl);
  428. }
  429. function histLookup(e){
  430. try{
  431. var txt=e.target.textContent, ix=-1;
  432. //.innerHTML??
  433. e.preventDefault();
  434. var ha = getTag('a',getId('divHist'));
  435. // ix=ha.indexOf(e.target);
  436. /**/
  437. for(var i=0,l=ha.length; i<l; i++)
  438. if(e.target == ha[i]){ ix=i; break; }
  439. /**/
  440. if(ix<0) return;
  441. if(e.ctrlKey && e.altKey){ //remove itemm
  442. if(ix==0) return;
  443. killId('divHist');
  444. ht.splice(ix,1);
  445. GM_setValue('hist',JSON.stringify(ht));
  446. history();
  447. return;
  448. }
  449. var lang = ht[ix][2].match(/([a-zA-Z-]+)\|([a-zA-Z-]+)/);
  450. gt_sl=lang[1]; gt_tl=lang[2];
  451. txtSel = txt;
  452. getId('divResult').innerHTML = 'Loading...'
  453. gtRequest(txtSel,gt_sl,gt_tl);
  454. } catch(e){console.log('broken history\n'+e)}
  455. }
  456.  
  457. function fastSwap(){
  458. if(gt_sl != 'auto'){
  459. var t= gt_sl; gt_sl=gt_tl; gt_tl=t;
  460. gtRequest(txtSel,gt_sl,gt_tl);
  461. }
  462. }
  463.  
  464. function badResponce(html,e){
  465. var dr=getId('divResult')
  466. dr.innerHTML = '';
  467. var br=addEl(dr,'a',{'class':'gootranslink'},null,'Bad Google response');
  468. br.href=URL.substr(0,100);
  469. var m=html.match(/\<title\>(.*?)\<\/title\>/);
  470. if(m && m[1])
  471. addEl(dr,'p',{},null,m[1]);
  472. //id="captcha"
  473. m=html.match(/(<img\s.*?\>)/);
  474. if(m && m[1])
  475. addEl(dr,'p',{},null,m[1]);
  476. _log(html);
  477. return;
  478. }
  479. var ex_sl , ex_tl;
  480. function extractResult(html){
  481. if(html){
  482. var html2 = html.match(/\<body[^\>]*\>([\s\S]+)\<\/body\>/);//[1];//select body content
  483. if(!html2){ // too many lettters!!!11
  484. badResponce(html); return;
  485. }
  486. html2 = html2[1].replace(/\<script[^\<]+\<\/script\>/ig, '');//remove script tags...
  487. //html2 = html.replace(/\<iframe[^\<]+\<\/iframe\>/ig, '');
  488. //cleanup
  489. killId('divExtract');
  490. // killId(res_dict);
  491. //append translated page as hidden frame
  492. var iframe = addEl(document.body,'iframe',
  493. {style:'visibility:hidden;'});
  494. var dX = addEl(iframe.contentWindow.document.body,'div',
  495. {id:'divExtract'}, null, html2);
  496. divExtract = document.importNode(dX, true);
  497. iframe.parentNode.removeChild(iframe);
  498. ex_sl= gt_sl, ex_tl=gt_tl;
  499. }
  500. try{ //gather info
  501. // 2013-10-20
  502. var _sl = detectedLang(gt_sl);
  503. var _tl = detectedLang(gt_tl);
  504. // var _sl = getXId("gt-sl-gms").textContent;
  505. // var _tl = getXId("gt-tl-gms").textContent;
  506. // _sl = _sl.replace(/^.*?\:\s*/,'');
  507. // _tl = _tl.replace(/^.*?\:\s*/,'');
  508. /* ?!11 150415 */ _log('**',_sl+'>'+_tl)
  509. if( 1 || ex_sl !== gt_sl )
  510. gt_sl_gms = _sl, gt_tl_gms =_tl;
  511. else
  512. gt_sl_gms = _tl, gt_tl_gms = _sl; /* ?!11 */
  513. getId('divBottom').removeChild(getId('optionsLink'));
  514. var oL= buildEl('div', {id:'optionsLink', title: 'Settings', 'class':'gootransbutt'},
  515. null, null);
  516. addEl(oL,'a',{id:'optionsFrom','class':'gootranslink'},
  517. ['click', options], gt_sl_gms +' ');
  518. addEl(oL,'a',{id:'optionsFast','class':'gootranslink',
  519. title: 'swap languages'}, ['click', fastSwap], imgSwap);
  520. addEl(oL,'a',{id:'optionsTo','class':'gootranslink ' + (getId('divOpt') ? 'gtlActive':'gtlPassive')},
  521. ['click', options], gt_tl_gms );
  522. getId('divBottom').appendChild(oL);
  523. }catch(e){ console.log('gather\n'+e); }
  524. // var translation = getXId("result_box").textContent;
  525. // first run: resolve tl = auto
  526. if(GT_tl == 'auto')try{
  527. GT_tl=getXId("gt-tl").value;
  528. if(GT_tl) GM_setValue('to', GT_tl);
  529. else GT_tl='en';
  530. gt_tl=GT_tl;
  531. }catch(e){console.log('auto?\n'+e)}
  532.  
  533.  
  534. //parse info
  535. var dR=getId('divResult');
  536. dR.innerHTML = '<a class="gootranslink" href="#'+
  537. '" target="_blank">' + 'translating..' /*translation*/ + '</a>'; // +'<br>&nbsp;';
  538. dR.childNodes[0].setAttribute('href',currentURL); //<a href
  539. dR.style.textAlign = rtl_langs.indexOf(GT_tl) < 0? 'left':'right';
  540. dR.style.direction = rtl_langs.indexOf(GT_tl) < 0? 'ltr' : 'rtl';
  541. dR.lang=GT_tl;
  542. dict();
  543.  
  544. }
  545.  
  546. function getSelection(t){
  547. var txt = '';
  548. //get selected text
  549. if (window.getSelection){
  550. txt = window.getSelection();
  551. }
  552. else if (document.getSelection) {
  553. txt = document.getSelection();
  554. }
  555. else if (document.selection) {
  556. txt = document.selection.createRange().text;
  557. }
  558. inTextArea= t.type=='textarea' ? t : null
  559. if(inTextArea){
  560. txt=t.value.substr(t.selectionStart,t.selectionEnd-t.selectionStart);
  561. }
  562. return trim(txt);
  563. }
  564. function swapLang(){
  565. var to=getId('optSelLangTo').value,from=getId('optSelLangFrom').value;
  566. // if(from!='auto'){
  567. getId('optSelLangTo').value = from;
  568. getId('optSelLangFrom').value = to;
  569. quickLookup();
  570. // }
  571. }
  572.  
  573. function saveIt(){
  574. var bs =getId('gtp-save');
  575. bs && (bs.className ='gootranslink goounsaved');
  576. }
  577.  
  578. function options(evt){
  579. var dO = getId('divOpt');
  580. if(!dO){//show options
  581. dO = buildEl('div', {id:'divOpt' });
  582. var oL=getId('optionsLink');
  583. oL.title='Hide settings';
  584. //
  585. var dA=getId('divHist');
  586. if(dA){
  587. insAfter(dO,dA);
  588. }else if(( dA=getId('divSourceshow')) ){
  589. insAfter(dO,dA);
  590. }else{
  591. insAfter(dO,getId('divResult'));
  592. }
  593. //from
  594. addEl(dO,'a',{'class':'gootransbutt gootranslink',
  595. target:'_blank', href:'http://www.senojflags.com/', title: 'choose country flag icon'},
  596. ['click',function(e){
  597. e.preventDefault(); GM_openInTab(senojflags[0]); cleanUp(); return false;}],
  598. imgH+imgFlags['AN']+imgT);
  599. addEl(dO,'span', null, null,' From: ');
  600. var gt_slist = getXId("gt-sl");
  601. gt_slist= gt_slist ? gt_slist.innerHTML+'' : languagesGoogle;
  602. /* console.log(gt_slist) /* !!! */
  603.  
  604. var oF =dO.appendChild(buildEl('select', {id:'optSelLangFrom'}, null, gt_slist));
  605. oF.value = GM_getValue('from', "auto");
  606. oF.addEventListener('change', quickLookup, false);
  607. // swap
  608. addEl(dO,'span', null, null,'&nbsp');
  609. addEl(dO,'a', {id:'opSelectLangSwap',href:HREF_NO, 'class':"gootranslink",
  610. title:'Swap languages',}, ['click', swapLang], imgSwap);
  611. //to
  612. addEl(dO,'span', null, null,' To:');
  613. var gt_tlist = getXId("gt-tl");
  614. gt_tlist= gt_tlist ? gt_tlist.innerHTML+'' : languagesGoogle;
  615. var oT =dO.appendChild(buildEl('select', {id:'optSelLangTo'}, null, gt_tlist));
  616. oT.value = GM_getValue('to', "auto");
  617. oT.addEventListener('change', quickLookup, false);
  618. //use ctrl
  619. addEl(dO,'br');
  620. addEl(dO,'span', null, null,'Use with: ');
  621. var d=addEl(dO,'input', {id:'checkCtrl', type:'checkbox'},
  622. ['change', saveIt], null );
  623. addEl(dO,'span', null, null,' Ctrl &nbsp;&nbsp; ');
  624. d.checked = GM_getValue('ctrl',false);
  625. // use alt
  626. d=addEl(dO,'input', {id:'checkAlt', type:'checkbox',
  627. title:'using Alt is highly recommended'},
  628. ['change', saveIt], null);
  629. addEl(dO,'span', null,
  630. null,' Alt &nbsp;&nbsp;&nbsp; History:&nbsp;');
  631. d.checked = GM_getValue('alt',true);
  632. // history depth
  633. d=addEl(dO,'input', {id:'histSize', type:'textbox', maxlength: 2,
  634. style: "width:2em; ", title: "set to 0 to clear history"});
  635. addEl(dO,'span', null, null,' items &nbsp; of ');
  636. d.value = maxHT;
  637. // max # words in phrase
  638. d=addEl(dO,'input', {id:'histWc', type:'textbox', maxlength: 1,
  639. style: "width:1em; ", title: "max # of words in phrase"});
  640. addEl(dO,'span', null, null,' words');
  641. d.value = maxWC;
  642. // source box params
  643. addEl(dO,'br');
  644. addEl(dO,'span', null, null,'Source box: &nbsp;');
  645. d=addEl(dO,'input', {id:'sourceBH', type:'textbox', maxlength: 1,
  646. style: "width:1em; ", title: "box height"});
  647. d.value = sourceBH;
  648.  
  649. addEl(dO,'span', null, null,' height &nbsp; ');
  650.  
  651. d=addEl(dO,'input', {id:'sourceDP', type:'textbox', maxlength: 2,
  652. style: "width:2em; ", title: "# of lines to keep"});
  653. addEl(dO,'span', null, null,' depth &nbsp; ');
  654. d.value = sourceDP;
  655.  
  656. addEl(dO,'span', null, null," No flags:");
  657. d=addEl(dO,'input', {id:'checkNoflags', type:'checkbox',
  658. title: "don't show country flag icons"});
  659. d.checked = GM_getValue('noFlags');
  660. // colours
  661. for(var b,li=BG.C.length,ii=0;ii<li;ii++){
  662. b=addEl(dO,'span',{'class':'gtBGColor', title:BG.t[ii],
  663. style: 'background-color:'+ BG.C[ii]+'!important;' +
  664. (ii==0?'margin-left:6px' :'')
  665. }, null,'&nbsp;');
  666. b.addEventListener('click',BG.f[ii]);
  667. }
  668. //save
  669. addEl(dO,'span',null,null,' &nbsp; ');
  670. var oS=
  671. addEl(dO,'a', {href:HREF_NO, id:'gtp-save', 'class':'gootranslink gootransbutt',
  672. title: "save changes"},
  673. ['click', saveOptions], '<b>save</b>');
  674. if(!GM_getValue('from'))
  675. saveIt();
  676. getId('optionsTo').className='gootransbutt gootranslink gtlActive';
  677. //cancel
  678. }
  679. else{//hide options
  680. killId(dO);
  681. getId('optionsLink').title = 'Settings';
  682. var oTL = getId('optionsTo');
  683. oTL.className='gootransbutt gootranslink gtlPassive';
  684. }
  685. }
  686. function showTrans(){
  687. try{
  688. var hOs = GM_getValue('showTrans',false) !== true;
  689. var shhi = hOs?'gtp-trans gtp-block':'gtp-trans gtp-hide';
  690. var tds= document.getElementsByClassName('gtp-trans');
  691. for(var i=0, il=tds.length; i<il; i++){
  692. tds[i].className=shhi;
  693. }
  694. getId('gtp_transOnOff').innerHTML = hOs?"&laquo;&laquo;":"&raquo;&raquo;";
  695. GM_setValue('showTrans',hOs)
  696. } catch(e){console.log('showTrans\n'+e)}
  697. }
  698.  
  699. function detectedLang(da){
  700. if(!da) return '';
  701. var gt_slist = getXId("gt-sl");
  702. //console.log(gt_slist.innerHTML)
  703. gt_slist= gt_slist ? gt_slist.innerHTML+'' : languagesGoogle;
  704. var re= new RegExp('ion value="'+da+'">(.*?)<\/opt');
  705. var ma= gt_slist.match(re);
  706. if(ma && ma[1]) return ma[1]; return da;
  707. }
  708.  
  709. function extractDict(txt){
  710. _log('!dict')
  711.  
  712. try{
  713. if(!txt) return;
  714. if(txt.substr(0,1) !== '[')
  715. throw 'Bad Google responce';
  716. txt=txt.replace(/,(?=,)/g,',""');
  717. txt=txt.replace(/\[(?=,)/g,'["asshole"');
  718. var dA=JSON.parse(txt);
  719. var dL='';
  720. //translation
  721. if( dA && dA[0] && dA[0][0] ){
  722. var dR=getId('divResult');
  723. var tr = dA[0][0][0];
  724. dR.childNodes[0].textContent=tr;
  725. dR.style.textAlign = rtl_langs.indexOf(GT_tl) < 0? 'left':'right';
  726. dR.style.direction = rtl_langs.indexOf(GT_tl) < 0? 'ltr' : 'rtl';
  727. dR.lang=GT_tl;
  728. addHistory(txtSel,tr);
  729. } else {
  730. getId('divResult').innerHTML='Google returns nothing!'; return;
  731. }
  732. // detected lang
  733. if(gt_sl=='auto' && dA[2]){
  734. var oF = getId("optionsFrom");
  735. oF.textContent= oF.textContent+' - '+detectedLang(dA[2]) +' ';
  736. }
  737. if(dA && dA[1] && dA[1][0] ){
  738. var da=dA[1];
  739. dL=buildEl('div',{id: 'gtp_dict'});
  740. var dT=addEl(dL,'table');
  741. var dB=addEl(dT,'tbody');
  742. var showT = 'gtp-trans gtp-hide',showI = "&raquo;&raquo;"
  743. if(GM_getValue('showTrans',false) === true)
  744. showT = 'gtp-trans gtp-block', showI = "&laquo;&laquo;"
  745. for(var i=0,il=da.length; i<il; i++){
  746. var tr=addEl(dB,'tr');
  747. addEl(tr,'td',{'class': 'gtp-pos'}, null, da[i][0]);
  748. for(var j=0,jl=da[i][2].length; j<jl; j++){
  749. tr=addEl(dB,'tr');
  750. addEl(tr,'td',{'class': 'gtp-word'}, null, da[i][2][j][0]);
  751. // console.log(JSON.stringify(da[i][2][j]))
  752. da[i][2][j][1]&&
  753. addEl(tr,'td',{'class': showT}, null, da[i][2][j][1].join(', '));
  754. }
  755. }
  756. var gtdir = (getId('divResult').style.direction=='rtl') ? 'left' : 'right';
  757. addEl(dL,'a',{'class': 'gootransbutt gootranslink', id: 'gtp_transOnOff',
  758. style: 'position: absolute; top: -.5em; '+gtdir+': 1px;'
  759. },['click', showTrans],showI);
  760. killId('gtp_dict');
  761. if(dL) getId('divResult').appendChild(dL);
  762. }
  763. killId('divSourceshow');
  764. killId('divHist');
  765.  
  766. if(GM_getValue('sourceShow',true))
  767. source();
  768. if(GM_getValue('histShow',false))
  769. history();
  770. if(!GM_getValue('histWc') && !getId('divOpt')) // no settings?
  771. options(); // show options
  772. } catch(e){
  773. _log('errexDict: '+e+'\n'+txt.substr(0,100));
  774. badResponce(txt,e);
  775. }
  776. }
  777.  
  778. function onTimerDict(){
  779. var q = dictURL +
  780. "&hl="+ GM_getValue('to','auto') +
  781. "&sl=" + gt_sl + "&tl=" + gt_tl + //+'&multires=1&ssel=0&tsel=0&sc=1';
  782. "&text="+ escAp(txtSel);
  783. //console.log('dict:'+ dictURL);
  784. _log('?dict')
  785. Request(q, extractDict);
  786. }
  787.  
  788. function dict(){
  789. var dR=getId('divResult');
  790. killId('gtp_dict');
  791. // var dD=buildEl('div',{id:"gtp_dict"},null,dict)
  792. // dR.appendChild(dD);
  793. window.setZeroTimeout(onTimerDict);
  794. }
  795.  
  796. function saveSource(){
  797. try{
  798. sT = getId('divSourcetext').value;
  799. GM_setValue('sourceText',JSON.stringify(sT));
  800. }catch(e){console.log('saveSource\n'+e)}
  801. }
  802.  
  803. function source(){
  804. var divSource = getId('divSourceshow');
  805. try{
  806. if(divSource){
  807. killId(divSource);
  808. var sL = getId('sourceLink');
  809. sL.innerHTML = 'Source';
  810. sL.className = 'gootransbutt gootranslink gtlPassive'
  811. sL.title = 'Show source';
  812. killId('imgSourcesave');
  813. GM_setValue('sourceShow',false);
  814. return;
  815. }
  816. GM_setValue('sourceShow',true);
  817. divSource= buildEl('form', {id:'divSourceshow', style: 'border: 0'}, null, null);
  818.  
  819. if(sT){
  820. var sTa= sT.split('\n');
  821. var tS= txtSel + ' \u2192 ' + trim(getId('divResult').childNodes[0].textContent);
  822. if(tS != sTa[0]){
  823. while(sTa.length >= sourceDP) sTa.pop();
  824. sT= tS + '\n' + sTa.join('\n');
  825. }
  826. }else sT=txtSel;
  827. if(!getId('imgSourcesave'))
  828. insAfter(
  829. buildEl('img',{id: 'imgSourcesave', title: 'save source', src: imgSave,
  830. style: 'margin-bottom: -3px;'},
  831. ['click', saveSource], null)
  832. ,getId('sourceLink'),getId('sourceLink'));
  833. addEl(divSource,'textarea', {id:'divSourcetext', rows: sourceDP,
  834. style: "font-family: sans-serif !important; height:"+(sourceBH+1)+"em;"}, null, sT),
  835. getId('divBottom');
  836. var sL=getId('sourceLink');
  837. sL.innerHTML = 'Source';
  838. sL.className= 'gootransbutt gootranslink gtlActive';
  839. sL.title = 'Hide source';
  840. }catch(e){console.log('Sourceshow\n'+e)};
  841. insAfter(divSource,getId('divResult'));
  842. }
  843. // ht: [from, to, langpair, hitCount]
  844.  
  845. function history(){
  846. var divHist = getId('divHist');
  847. try{
  848. if(divHist){
  849. killId(divHist);
  850. var hL = getId('historyLink');
  851. hL.innerHTML = 'History'; hL.className= 'gootransbutt gootranslink gtlActive';
  852. hL.title = 'Translation history';
  853. GM_setValue('histShow',false);
  854. return;
  855. }
  856. if(!maxHT) return;
  857. GM_setValue('histShow',true);
  858. divHist = buildEl('div', {id:'divHist'},['click', histLookup], null );
  859. //
  860. for(var i=0, l=ht.length; i<l; i++){
  861. var bkg = ht[i][0].indexOf(' ')>0 ? ' goohistlink' : '';
  862. addEl(divHist,'a', {href:HREF_NO, 'class': 'gootranslink'+bkg, 'titel': ht[i][1]+
  863. ((ht[i][3]>1) ? '\u00A0'+ '['+ht[i][3]+']' : '')},
  864. null, ht[i][0]);
  865. if(i < l-1)
  866. divHist.appendChild(document.createTextNode(' '));
  867. }
  868. addEl(divHist,'span',null,null,'<br>&nbsp;');
  869. if(getId('divSourceshow'))
  870. insAfter(divHist,getId('divSourceshow'));
  871. else
  872. insAfter(divHist,getId('divResult'));
  873. var hL=getId('historyLink')
  874. // hl.textContent = 'X';
  875. hL.title= 'Hide history';
  876. hL.innerHTML = 'History'; hL.className = 'gootransbutt gootranslink gtlActive';
  877. }catch(e){console.log('hist problem\n'+e)}
  878. }
  879.  
  880. function saveOptions(evt){
  881. try{
  882. var from = getId('optSelLangFrom').value;
  883. var to = getId('optSelLangTo').value;
  884. var ctrl = getId('checkCtrl').checked;
  885. var alt = getId('checkAlt').checked;
  886. var mh = parseInt(getId('histSize').value);
  887. var wc = parseInt(getId('histWc').value);
  888. var nf = getId('checkNoflags').checked;
  889. if(0<= mh && mh <=99 && mh<maxHT){
  890. while(ht && ht.length>mh) ht.pop();
  891. GM_setValue('hist',ht? JSON.stringify(ht):'');
  892. if(getId('divHist')){
  893. killId('divHist');
  894. history();
  895. }
  896. }
  897. maxHT=mh;
  898. var bh = parseInt(getId('sourceBH').value);
  899. if( 0< bh && bh <10) sourceBH = bh;
  900. var dp = parseInt(getId('sourceDP').value);
  901. if( 0< dp && dp <100) sourceDP = dp;
  902. if(1<= wc && wc <=9) maxWC=wc;
  903. GM_setValue('histSize',maxHT)
  904. GM_setValue('histWc',maxWC);
  905. GM_setValue('from', from);
  906. GM_setValue('to', to);
  907. GM_setValue('ctrl', ctrl);
  908. GM_setValue('alt', alt);
  909. GM_setValue('sourceBH', sourceBH);
  910. GM_setValue('sourceDP', sourceDP);
  911. GM_setValue('noFlags',nf)
  912. getId('divDic').removeChild(getId('divOpt'));
  913. getId('optionsLink').title='Settings';
  914. return;
  915. }catch(e){console.log('saveOpnions\n'+e);}
  916. }
  917.  
  918. function addHistory(src,trt){
  919. if (!maxHT) return;
  920. try{
  921. var hts=GM_getValue("hist");
  922. if( !hts ){
  923. ht=[["google translator","Der Ubersetzer","en|de",0]];
  924. hts=JSON.stringify(ht);
  925. }
  926. ht=JSON.parse(hts);
  927. var st=trim(src+''); var tt = trim(trt+'');
  928. var wc = (st.split(' ')).length;
  929. if(wc>maxWC) return;
  930. var lang=currentURL.match(/langpair=([a-zA-Z-\|]+)/)[1];
  931. var ix=-1; // find word in hist
  932. for(var i=0, l=ht.length; i<l; i++)
  933. if(st==ht[i][0]){ ix=i; break; }
  934. //if(ix==0) return; // nothing to do
  935. var hits=0;
  936. if(ix>=0){
  937. hits=ht[ix][3];
  938. if( (gt_sl+'|'+gt_tl) == ht[ix][2] && tt != ht[ix][1]) {
  939. tt = ht[ix][1]; // don't touch my translasion
  940. }
  941. ht.splice(ix,1);
  942. }
  943. // if(hits<4)
  944. hits++; // delete it by your own hands
  945. if (ht.length>maxHT){
  946. var minHit=99999; // which item shoud i remove?
  947. for(i=ht.length-1;i>0;i--)
  948. if(minHit>ht[i][3]) minHit=ht[i][3]
  949. ix=ht.length-1;
  950. for(var i=ix; i>0; i--)
  951. if(minHit==ht[i][3]){ ix=i; break; }
  952. ht.splice(ix,1);
  953. }
  954. ht.unshift([st,tt,lang,hits]);
  955. GM_setValue('hist',JSON.stringify(ht));
  956. } catch(e){console.log('addHist\n'+e);}
  957. }
  958. var senFlag = '';
  959. function selFlag(e){
  960. if(!isInited) {css(-1); isInited=true; }
  961. killId('divSelflag');
  962. document.addEventListener('keydown', escCleanup, false);
  963. var p = belowCursor(e,10,10);
  964. var dsf = buildEl('div',{id:'divSelflag', style:
  965. ';top:'+p.t+';left:'+p.l+';right:'+p.r +';bottom: auto'});
  966. var sel=addEl(dsf,'select',{id: 'optSelFlag'},
  967. null,languagesGoogle);
  968. sel.value = GM_getValue('to')? GM_getValue('to'): 'en';
  969. addEl(dsf,'span',null,null,'<br><br>');
  970. addEl(dsf,'a', {href:HREF_NO,
  971. 'class':'gootransbutt gootranslink', title: "use icon"},
  972. ['click', function(){saveFlag(true)}], '<b>&nbsp; OK &nbsp;</b>');
  973. addEl(dsf,'a', {href:HREF_NO,
  974. 'class':'gootransbutt gootranslink'},
  975. ['click', function(){saveFlag(false)}],
  976. '<b>&nbsp; cancel &nbsp; </b>');
  977. //http://www.senojflags.com/images/national-flag-icons/Bermuda-Flag.png
  978. senFlag = e.target.src+'';
  979. var sm = senFlag.match(/.+\/(.+)\-Flag\.png/);
  980. if(sm && sm[1]) senFlag= sm[1];
  981. _log(senFlag);
  982. if(senFlag) body.appendChild(dsf);
  983. }
  984. function saveFlag(tf){
  985. if(tf && senFlag){
  986. var s= 'l-'+getId('optSelFlag').value;
  987. GM_setValue(s,senFlag);
  988. _log(s+': '+senFlag );
  989. }else _log('cant save flags' );
  990. killId('divSelflag'); return;
  991. }
  992. var fCSS;
  993. function flagClick(e){
  994. e.preventDefault();
  995. if(e.target.nodeName == 'IMG'){
  996. _log('hit on: ' + e.target.alt);
  997. selFlag(e);
  998. }else (killId('divSelflag'));
  999. }
  1000. function belowCursor(evt,ho,vo,lr){
  1001. var p={t:'', l:'auto', r:'auto'};
  1002. p.t=(evt.clientY+window.pageYOffset+vo)+'px';
  1003. var l=(evt.clientX+window.pageXOffset+ho)+'px';
  1004. if(lr && lr=='r')
  1005. { p.l=l; return p; }
  1006. var w = window.innerWidth;
  1007. var r=(w-(evt.clientX+window.pageXOffset)+ho);
  1008. // Q: How to detect visibility & thickess of vertical scrollbar?
  1009. r-=8; //
  1010. if(r<0) r= w/4;
  1011. r+='px';
  1012. if(lr && lr=='l')
  1013. { p.r=r; return p; }
  1014. if(evt.clientX < w/2)
  1015. p.l=l;
  1016. else
  1017. p.r=r;
  1018. return p;
  1019. }
  1020. var flagLang;
  1021. function getFlagSrc(lng, where){
  1022. if(!where) where = 'to';
  1023. if(GM_getValue('noFlags')) return imgFlags[where];
  1024. var fl='l-'+lng;
  1025. var flag = GM_getValue(fl,'');
  1026. if(!flag){
  1027. flag=imgFlags[lng];
  1028. if(!flag) return flag = imgFlags[where];
  1029. }
  1030. if(flag.indexOf('http')==0
  1031. //flag.indexOf('file') ==0
  1032. ||flag.indexOf('data:') ==0)
  1033. return flag;
  1034. flagLang=fl;
  1035. flag= 'http://www.senojflags.com/images/national-flag-icons/'+flag+'-Flag.png';
  1036. flagRequest(flag);
  1037. return flag;
  1038. }
  1039. function flagRequest(f){
  1040. _log('load '+f);
  1041. GM_xmlhttpRequest({
  1042. method: 'GET',
  1043. url: f,
  1044. binary: true,
  1045. overrideMimeType: "text/plain; charset=x-user-defined",
  1046. headers: {
  1047. "User-Agent": navigator.userAgent
  1048. ,"Accept": "image/png,image/*;q=0.8,*/*;q=0.5"
  1049. ,"Accept-Encoding": "gzip, deflate"
  1050. },
  1051. onload: function(resp) {
  1052. try{
  1053. flagStore(resp.responseText,f);
  1054. }catch(e){console.log('FlagRqst\n'+e);}
  1055. }
  1056. });
  1057. }
  1058. function flagStore(r,url){
  1059. if(r.indexOf("<head")>=0)
  1060. {
  1061. console.log("Banned!\n"+url);
  1062. GM_setValue(flagLang,url);
  1063. }
  1064. else
  1065. GM_setValue(flagLang,"data:image/png;base64," + b2b64(r));
  1066. }
  1067.  
  1068. function trim(s){
  1069. return (s+'').replace(/\s+/g,' ').replace(/^\s/,'').replace(/\s$/,'');
  1070. }
  1071.  
  1072. function killId(nod){
  1073. if(!nod) return;
  1074. var n = nod;
  1075. if(typeof n == 'string'){
  1076. n= getId(nod);
  1077. }
  1078. if(!n) return;
  1079. if(n.parentNode) n.parentNode.removeChild(n);
  1080. else _log('cant kill: '+nod)
  1081. }
  1082.  
  1083. function addEl(to,type, attrArray, eL, html){
  1084. return to.appendChild(buildEl(type, attrArray, eL, html));
  1085. }
  1086.  
  1087. function buildEl(type, attrArray, eL, html)
  1088. {
  1089. var node = document.createElement(type);
  1090. for (var attr in attrArray) if (attrArray.hasOwnProperty(attr)){
  1091. node.setAttribute(attr, attrArray[attr]);
  1092. }
  1093. if(eL){
  1094. //console.log('buildEl\n'+type+'\n'+JSON.stringify(attrArray)+'\n'+eL[0])
  1095. node.addEventListener(eL[0], eL[1], eL[2]?true:false);
  1096. }
  1097. if(html)
  1098. node.innerHTML = html;
  1099. return node;
  1100. }
  1101.  
  1102. function getId(id, parent){
  1103. if(!parent)
  1104. return document.getElementById(id);
  1105. return parent.getElementById(id);
  1106. }
  1107.  
  1108. function getXId(id){
  1109. var r=Xel('.//*[@id="'+id+'"]',divExtract);
  1110. if(r) return r;
  1111. throw "Xel bug " + id;
  1112. }
  1113.  
  1114. function Xel(XPath, contextNode){
  1115. var a = document.evaluate(XPath, (contextNode || document),
  1116. null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1117. return (a.snapshotLength ? a.snapshotItem(0) : null);
  1118. }
  1119.  
  1120. /** /
  1121. function Xels(XPath, contextNode){
  1122. var ret=[], i=0;
  1123. var a = document.evaluate(XPath, (contextNode || document),
  1124. null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  1125. while(a.snapshotItem(i))
  1126. ret.push(a.snapshotItem(i++));
  1127. return ret;
  1128. }/**/
  1129. //
  1130.  
  1131. function getTag(name, parent){
  1132. if(!parent)
  1133. return window.document.getElementsByTagName(name);
  1134. return parent.getElementsByTagName(name);
  1135. }
  1136. /*
  1137. * Drag and drop support adapted fom http://www.hunlock.com/blogs/Javascript_Drag_and_Drop
  1138. */
  1139. var savedTarget=null; // The target layer (effectively vidPane)
  1140. var orgCursor=null; // The original mouse style so we can restore it
  1141. var dragOK=false; // True if we're allowed to move the element under mouse
  1142. var dragXoffset=0; // How much we've moved the element on the horozontal
  1143. var dragYoffset=0; // How much we've moved the element on the verticle
  1144. var didDrag=false; //set to true when we do a drag
  1145. function moveHandler(e){
  1146. if (e == null) return;// { e = window.event }
  1147. if ( e.button<=1 && dragOK ){
  1148. savedTarget.style.left = e.clientX - dragXoffset + 'px';
  1149. savedTarget.style.top = e.clientY - dragYoffset + 'px';
  1150. return false;
  1151. }
  1152. }
  1153. function dragCleanup(e) {
  1154. document.removeEventListener('mousemove',moveHandler,false);
  1155. document.removeEventListener('mouseup',dragCleanup,false);
  1156. savedTarget.style.cursor=orgCursor;
  1157. dragOK=false; //its been dragged now
  1158. didDrag=true;
  1159. }
  1160. function dragHandler(e){
  1161. var htype='-moz-grabbing';
  1162. if (e == null) return;//
  1163. var target = e.target;// != null ? e.target : e.srcElement;
  1164. orgCursor=target.style.cursor;
  1165. if(target.nodeName!='DIV' )
  1166. return;
  1167. if( e.ctrlKey || e.altKey || e.shiftKey)
  1168. return; // enable selection inside
  1169. else if(clickedInsideID(target, res_dict))
  1170. return;
  1171. if (target = clickedInsideID(target, 'divDic')) {
  1172. savedTarget=target;
  1173. target.style.cursor=htype;
  1174. dragOK=true;
  1175. dragXoffset = e.clientX-target.offsetLeft;
  1176. dragYoffset = e.clientY-target.offsetTop;
  1177. //set the left before removing the right
  1178. target.style.left = e.clientX - dragXoffset + 'px';
  1179. target.style.right = null;
  1180. document.addEventListener('mousemove',moveHandler,false);
  1181. document.addEventListener('mouseup',dragCleanup,false);
  1182. return false;
  1183. }
  1184. }
  1185. function clickedInsideID(target, id) {
  1186. if (target.getAttribute('id')==id)
  1187. return getId(id);
  1188. if (target.parentNode) {
  1189. while (target = target.parentNode) {
  1190. try{
  1191. if (target.getAttribute('id')==id)
  1192. return getId(id);
  1193. }catch(e){}
  1194. }
  1195. }
  1196. return null;
  1197. }
  1198. //end drag code
  1199. function b2b64(inp) { // binary data --> base64
  1200. var output = [], c1, c2, c3, e1, e2, e3, e4, i = 0;
  1201. const k="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  1202. var len = inp.length;
  1203. while( i < len ){
  1204. c1 = inp.charCodeAt(i++); c2 = inp.charCodeAt(i++); c3 = inp.charCodeAt(i++);
  1205. e1 = (c1&255) >> 2;
  1206. e2 = ((c1 & 3) << 4) | ((c2&255) >> 4);
  1207. e3 = ((c2 & 15) << 2) | ((c3&255) >> 6);
  1208. e4 = c3 & 63;
  1209. if( isNaN(c3)) e4 = 64;
  1210. if( isNaN(c2)) e3 = 64;
  1211. output.push( k.charAt(e1) + k.charAt(e2) + k.charAt(e3) + k.charAt(e4));
  1212. } return output.join("");
  1213. }
  1214.  
  1215.  
  1216. function ttrans( s, ttab ){
  1217. for( var c, cc, t='', il=s.length, i=0; i<il; i++ )
  1218. t += (c=ttab[cc=s.charAt(i)]) ? c : cc;
  1219. return t;
  1220. }
  1221. const tabUrlEsc = {
  1222. '#':'%23', '%':'%25', '&':'%26', '.':'%2e', '/':'%2f', '?':'%3f'
  1223. };
  1224. function escAp(s){
  1225. return ttrans( s, tabUrlEsc );
  1226. }
  1227.  
  1228. function stickStyle(css){
  1229. var s=document.createElement("style"); s.type="text/css";
  1230. s.appendChild(document.createTextNode(css));
  1231. return (document.head||document.documentElement).appendChild(s);
  1232. }
  1233.  
  1234. function css(n){
  1235. var k,i=0;
  1236. _log('cssN:',n);
  1237. if(-1 === n){ try{
  1238. k= +(GM_getValue('backG',0));
  1239. if(0<=k && k< BG.C.length) i=k;
  1240. } catch(e){};}
  1241. else GM_setValue('backG', +(i=+n) );
  1242. try{
  1243. if(window.gttpCSS) window.gttpCSS.parentNode.removeChild(window.gttpCSS);
  1244. }catch(e){console.log('cssX:\n'+e)};
  1245. _log('cssS:'+i,BG.C[i]);
  1246. window.gttpCSS=
  1247. stickStyle((
  1248. '#divResult {overflow: auto; padding:3px; margin-bottom: 3px; max-height: 480px !important;}'+
  1249. '#divResult table *{ line-height: .85em !important}'+
  1250. '#divDic, #divDic *, #divSelflag, divSelflag * {font: small normal Tahoma,Verdana,Arial sans-serif !important; }'+
  1251. '#divDic,#divSelflag {position: absolute; background-color:BG_COLOR !important; color:#000000 !important; opacity: .95'+
  1252. ';padding:5px ;z-index:10000; border-radius:3px; border: solid thin grey'+
  1253. ';text-align: left !important;}'+
  1254. '#divDic{/*min-width: 340px !important; min-height:50px;*/ max-width:50%; padding: 3px; margin: 0;}'+
  1255. '#divSelflag{ max-width: 180px; }'+
  1256. '.gootranslink, a.gootranslink '+
  1257. '{color: #047 !important; text-decoration: none !important; font: small normal sans-serif !important;'+
  1258. 'cursor:pointer !important; }' +
  1259. 'a.gootranslink:visited {color: #047 !important; text-decoration: none !important;}'+
  1260. 'a.gootranslink:hover {color: #047 !important; text-decoration: underline !important;}' +
  1261. 'a.gootranslink:active {color: #047 !important; text-decoration: underline !important;}' +
  1262. '#gtp_dict td {font-size:14px; line-height:.8em; margin-left:5px; border:0px; background-color:BG_COLOR; color:black;}'+
  1263. 'a.goohistlink {background-color: BH_COLOR;}'+
  1264. '#gtp_dict {margin: 0; position: relative;}'+
  1265. '#gtp_dict ol {padding: 0 .5em 0 0; margin-left: 0.2em;}'+
  1266. '#gtp_dict li {list-style: square inside; display: list-item;}'+
  1267. '#gtp_dict td {padding-left: .25em; vertical-align:top; border:0px; color:black; background-color:BG_COLOR;}'+
  1268. '#optSelLangFrom,#optSelLangTo {max-width: 150px; text-align: left !important; }'+
  1269. '#divExtract{word-spacing: normal !important;}'+
  1270. '#divBottom {position: relative; width: 100%; font-size: smaller; text-decoration:none; }'+
  1271. '#historyLink {display: inline; position: relative; font-size:smaller; text-decoration:none;}'+
  1272. '#sourceLink {display: inline; position: relative; margin-left: 2em; font-size:smaller; text-decoration:none;}'+
  1273. '#imgSourcesave {display: inline; position: relative; margin-left:2px;}'+
  1274. '#optionsLink {display: inline; position: relative; margin-left: 2em; font-size:smaller !important; text-decoration:none !important;}'+
  1275. '#divOpt {position: relative; padding: 5px;'+
  1276. 'border-top: thin solid grey;}'+
  1277. '#divLookup, #divOpt, #divBottom,#divSourcetext,#divHist,#divuse {direction: ltr !important;}'+
  1278. '#divHist {background-color:BG_COLOR; position:relative; padding:5px; text-align:left !important;'+
  1279. 'border-top: thin solid grey;}'+
  1280. '#gtp_dict {background-color:BG_COLOR; color:#000000; opacity: .95; padding:1px; border-radius:3px;'+
  1281. 'margin-bottom: .1em; overflow-y:auto; overflow-x:hidden; font-size:small;}'+
  1282. '#divOpt {background-color:BG_COLOR; position:relative; padding:5px; text-align:left !important;}'+
  1283. '#divLookup, #divUse {background-color:transparent; color:#000000; position:absolute; padding: 3px;}'+
  1284. '#divSourceshow {border:0;padding: 0 0 2px 0; margin: 0;}'+
  1285. '#divSourcetext{ width:100%; height: 3em; line-height: .85em; overflow: auto !important;}' +
  1286. '.gtlPassive:before{ content:"\u2193";}'+
  1287. '.gtlActive:before{ content:"\u2191" !important;}'+
  1288. '#imgUse, #divGetback, #divGetforw {margin-left: 5px !important; cursor: pointer;}'+
  1289. '#divSourcetext {background: #EEE !important; color: black !important;}'+
  1290. '.gootransbutt {background-color: BT_COLOR;'+
  1291. 'border-radius: 3px; margin-top: 5px; }'+
  1292. '.goounsaved {background-color: #EF9024;'+
  1293. 'border-radius: 3px; margin-top: 5px; }'+
  1294. 'td.gtp-pos { color: #000000 !important; font-weight: bold !important; text-align: left; }'+
  1295. 'td.gtp-pos:before{ content:"\u2666 ";}'+
  1296. 'td.gtp-word {color: #000000 !important; padding-left: 5px; padding-right: 10px;'+
  1297. 'vertical-align: top; white-space: normal;}'+
  1298. 'td.gtp-trans {/*overflow-x: hidden;*/ vertical-align: top; white-space: normal;'+
  1299. ' width: 100%; color: #404040 !important}'+
  1300. 'td.gtp-pos, td.gtp-word, td.gtp-trans {padding-top: 1px !important; padding-bottom: 0 !important;}'+
  1301. '.gtp-hide {display: none}'+
  1302. '.gtp-block {display: block}'+
  1303. '').
  1304. replace(/BG_COLOR/g,BG.C[i]).
  1305. replace(/BH_COLOR/g,BG.H[i]).
  1306. replace(/BT_COLOR/g,BG.T[i])
  1307. );
  1308. if(-1 !== n) return;
  1309. stickStyle('\
  1310. .gtBGColor{border:thin solid blue !important; cursor: pointer;\
  1311. padding-right:6px; margin-right: 2px;}\
  1312. .gootranslink[titel]{position: relative;}\
  1313. .gootranslink[titel]:after {\
  1314. color: #050;\
  1315. content: attr(titel);\
  1316. position: absolute;\
  1317. visibility: hidden;\
  1318. opacity: 0.25;\
  1319. left: 16px;\
  1320. top: 32px;\
  1321. min-width: 0px;\
  1322. width: auto;\
  1323. white-space: normal !important;\
  1324. -moz-hyphens: none !important;\
  1325. text-decoration: none !important;\
  1326. border: 1px #aaa solid;\
  1327. border-radius: 6px;\
  1328. background-color: #dfd;\
  1329. padding: 1px 4px;\
  1330. font-size: 14px;\
  1331. -webkit-transition: all .2s linear .2s;\
  1332. transition: all .2s linear .2s;\
  1333. z-index: 2147483647;\
  1334. }\
  1335. .gootranslink[titel]:hover:after {\
  1336. visibility: visible;\
  1337. opacity: 1;\
  1338. -webkit-transition: all .5s linear .7s;\
  1339. transition: all .5s linear .7s;\
  1340. }\
  1341. ');
  1342. }
  1343. function insAfter(n,e){
  1344. if(e.nextElementSibling){
  1345. e.parentNode.insertBefore(n,e.nextElementSibling);
  1346. }else{
  1347. e.parentNode.appendChild(n);
  1348. }
  1349. }
  1350. function insBefore(n,e){
  1351. e.parentNode.insertBefore(n,e);
  1352. }
  1353. var imgH='<img border=0 src="' , imgD='data:image/png;base64,',imgT='">';
  1354.  
  1355. //http://www.senojflags.com/images/national-flag-icons/Portugal-Flag.png
  1356. imgForwSrc= imgD+
  1357. 'R0lGODlhEAAQAIQfAAFYsQJkw15iWgRz3AeN0Xl8c2mBiQma5B6W1h+b3yqh4BKp+kWk0pudlDC2/0y79X+4z1fC/7q6r3DK/4rN7a3Kz8fKwc/Uyr3c5N7dzuTi1Ofl1enm2O3r3/b06////yH+EUNyZWF0ZWQgd2l0aCBHSU1QACH5BAEKAB8ALAAAAAAQABAAAAWf4OeNXmdyX6qKpNSc25p6TVEIgl1osljntxxPNrIILhrDZBl5OBaLj6mTa1CWk+YTOpXgsBEM5gFdmDLBiJrC2VCgB85lYJFcmg+MPAPnDP4aGg4ODxsVFBkPBwd/jRuDFBoQDxkVix+NHwBQSBmeFwoEHwEDAQEAAJQVDAwQFxCipqeoABkMiwcWFqKjpqgEBLjAwDIAHwoJyQkIzB8hADs=';
  1358. imgForw = imgH+imgForwSrc+imgT;
  1359.  
  1360. imgBackSrc= imgD+
  1361. 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAAXNSR0IArs4c6QAAAGBQTFRFEgAAAVixAmTDXmJaBHPcB43ReXxzaYGJCZrkHpbWH5vfKqHgEqn6RaTSm52UMLb/TLv1f7jPV8L/urqvcMr/is3trcrPx8rBz9TKvdzk3t3O5OLU5+XV6ebY7evf9vTrdcYePwAAAAF0Uk5TAEDm2GYAAAABYktHRACIBR1IAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAoklEQVQY003PWxKDIAwF0CCPYouCKIIB7f532UTttPfvnkkyE4Ar+3Ecb8pdoRGM859UY4yUxow/4CpPcM6HuCzLoxaZacV9IY1G0mWGsG0sUs4M1rnU9hRjpCt4AZZ9CyGWOauyg7UB09qC97UqpRhWDFNN3jfFAf0qiFiLcwK4g57KNAw0JUTXqY4gZ2vtgEKwMFBItL47QN/3T8oLxPnVB4gUDOnY6pKLAAAAAElFTkSuQmCC';
  1362. imgBack = imgH+imgBackSrc+imgT;
  1363.  
  1364. imgSwap = "<img border=0 style="+'"margin-bottom: -3px;"'+
  1365. "src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAQCAYAAAD52jQlAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAGFJREFUOMu1kkESwCAIAxM+7vTlevJipYKkOWeWQAB2ar2jIFMD31ABEACYBj5kLKkooX9TGTSwUqZQusbToOnd+CxbQiQxXeMccPEVrNzOA//YvkKp9SNnWQo2ZcK6PgocHMgoj3uaTsAAAAAASUVORK5CYII='>";
  1366.  
  1367. 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=';
  1368.  
  1369. imgSave= imgD+
  1370. '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';
  1371.  
  1372. imgFlags= {
  1373. 'AN': imgD+
  1374. '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='
  1375. ,'en': imgD+
  1376. '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='
  1377. ,'ru': imgD+
  1378. 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAADkSURBVHjapJM5TgNBEEVfzeZlQIOE5ARxClLOxC04CzFX4ArERAhZsoTEyDDurqa7SGxsIYJZKqnov9p+iZkxJQSogLN9HhIKfBZAY2abUdVFVhlQT5igzoB8AiDPAGKMg5UHTQFwc/fI6rKh/VLsz4b/u9FFXbF5b4+AnXe8rIW2C72qN8uSwtwJoHMwm5NSP0+EbyP4E8DD0z3XZUnqdr0A2XLBawjcHgBOPZYXINILYMlw6o8deFVsvoCq7AewhFf9BWg047n9GOMDFaABroDzgeIt8CZ7J1YjHBkBlanv/DMAwHdYum9dlZQAAAAASUVORK5CYII='
  1379. ,'zh-CN': imgD+
  1380. 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAFbSURBVHjapJO/SgNBEIe/vduLCSaKFhb6DCnFzs4XsMgjWlj4AD6BFhYKFqKgTSzSaBLN7f+xuJM7RSHRHywLy8w3Oz9mlIjwHymgA/TrexU54E0Dm+Pj0QSACGRADt39gLnQTZkftHd2uqOBdYmR3uGQYjfhnzPSXJHeYTCK2Lu8AquGJYC9vgFY10AupUdvTekdTYgnGvdYVQ5P0nTa+kW+vYV4D5BrgGAt9nZOmCzwDxlxkqG60D0ImCsN/msbKs+J1gKgAXww+Kcp5nKBKgQ0rA09i/Oi8iR880HAGdMATFnSuX8kzWZ8vvqHJvi7idnGBibPGkBZlvSzDJFURfj6FC1ISyl4SpcagDUWVRRISi2ngPTL8PiArUysW3AW0RqUWmqCRATjWiZaa6HbQxXFcjOYUpVTA1wU4eb15S+r4BSwCewBgxWT58BY1XZ16nsVRcCp/67zxwDGd5ld8bkQAQAAAABJRU5ErkJggg=='
  1381. ,"af":"Namibia" //
  1382. ,"sq":"Albania"
  1383. ,"ar":"United-Arab-Emirates"
  1384. ,"hy":"Armenia"
  1385. ,"az":"Azerbaijan"
  1386. ,"eu":"Spain"
  1387. ,"be":"Belarus"
  1388. ,"bn":"Bangladesh"
  1389. ,"bs":"Bosnian"
  1390. ,"bg":"Bulgaria"
  1391. ,"ca":"Spain"
  1392. ,"ceb":"Philippines"
  1393. ,"ny":"Mozambique"
  1394. /* ,"zh-CN":"Chinese"*/
  1395. ,"hr":"Croatia"
  1396. ,"cs":"Czech-Republic"
  1397. ,"da":"Denmark"
  1398. ,"nl":"Netherlands"
  1399. /*, "en":"English"*/
  1400. ,"eo":"United-Nations"
  1401. ,"et":"Estonia"
  1402. ,"tl":"Philippines"
  1403. ,"fi":"Finland"
  1404. ,"fr":"France"
  1405. ,"gl":"Ukraine"
  1406. ,"ka":"Georgia"
  1407. ,"de":"Germany"
  1408. ,"el":"Greece"
  1409. ,"gu":"India"
  1410. ,"ht":"Haiti"
  1411. ,"ha":"Nigeria"
  1412. ,"iw":"Israel"
  1413. ,"hi":"India"
  1414. ,"hmn":"Laos"
  1415. ,"hu":"Hungary"
  1416. ,"is":"Iceland"
  1417. ,"ig":"Nigeria"
  1418. ,"id":"Indonezia"
  1419. ,"ga":"Ireland"
  1420. ,"it":"Italy"
  1421. ,"ja":"Japan"
  1422. ,"jw":"Japan"
  1423. ,"kn":"India"
  1424. ,"kk":"Kazakhstan"
  1425. ,"km":"Cambodia"
  1426. ,"ko":"North-Korea"
  1427. ,"lo":"Laos"
  1428. ,"la":"Vatican-City"
  1429. ,"lv":"Latvia"
  1430. ,"lt":"Lithuania"
  1431. ,"mk":"Macedonia"
  1432. ,"mg":"Madagascar"
  1433. ,"ms":"Malaysia"
  1434. ,"ml":"India"
  1435. ,"mt":"Malta"
  1436. ,"mi":"New-Zealand"
  1437. ,"mr":"India"
  1438. ,"mn":"Mongolia"
  1439. ,"my":"Burma" //absent
  1440. ,"ne":"Nepal"
  1441. ,"no":"Norway"
  1442. ,"fa":"Iran"
  1443. ,"pl":"Poland"
  1444. ,"pt":"Brazil"
  1445. ,"pa":"Pakistan"
  1446. ,"ro":"Romania"
  1447. /*, "ru":"Russia"*/
  1448. ,"sr":"Serbia"
  1449. ,"st":"Lesotho"
  1450. ,"si":"Sri-Lanka"
  1451. ,"sk":"Slovakia"
  1452. ,"sl":"Slovenia"
  1453. ,"so":"Somalia"
  1454. ,"es":"Spain"
  1455. ,"su":"Sudan"
  1456. ,"sw":"Mozambique"
  1457. ,"sv":"Sweden"
  1458. ,"tg":"Tajikistan"
  1459. ,"ta":"India"
  1460. ,"te":"India"
  1461. ,"th":"Thailand"
  1462. ,"tr":"Turkey"
  1463. ,"uk":"Ukraine"
  1464. ,"ur":"Pakistan"
  1465. ,"uz":"Uzbekistan"
  1466. ,"vi":"Viet-Nam"
  1467. ,"cy":"Wales"
  1468. ,"yi":"Israel"
  1469. ,"yo":"Nigeria"
  1470. ,"zu":"South-Africa"
  1471. };
  1472. imgFlags['zh-TW'] = imgFlags['zh-CN'];
  1473. imgFlags['to'] = imgForwSrc; imgFlags['from'] = imgBackSrc;
  1474.  
  1475. languagesGoogle = '<option value="auto">Detect language</option>\
  1476. </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>\
  1477. ';
  1478.  
  1479. /* */
  1480. try{
  1481. //body = window;
  1482. //while(body.parent && body.parent != body) body=body.parent;
  1483. //body = body.document.body;
  1484. body=//document.documentElement.appendChild(document.createElement('section'));
  1485. window.document.body;
  1486.  
  1487. maxHT=GM_getValue('histSize');
  1488. if(!maxHT) maxHT=20;
  1489. maxWC=GM_getValue('histWc');
  1490. if(!maxWC) maxWC=3;
  1491. sourceBH = GM_getValue('sourceBH',3);
  1492. sourceDP = GM_getValue('sourceDP',10);
  1493. if(!sourceDP) sourceDP = 10;
  1494.  
  1495. var av = GM_getValue('version');
  1496. if( av!= version ){
  1497. GM_setValue('version',version);
  1498. }
  1499. sT=GM_getValue('sourceText');
  1500. if (sT){
  1501. try{
  1502. sT=JSON.parse(sT);
  1503. }catch(e){console.log('broken source\n'+e)} ;
  1504. } else sT='';
  1505.  
  1506. // gmail spoils my timeout -- workaround
  1507. // borrowed from dbaron.org/log/20100309-faster-timeouts :
  1508. // Only add setZeroTimeout to the window object, and hide everything
  1509. // else in a closure.
  1510. (function() {
  1511. var timeouts = [];
  1512. var messageName = "zero-timeout-130613";
  1513. // Like setTimeout, but only takes a function argument. There's
  1514. // no time argument (always zero) and no arguments (you have to
  1515. // use a closure).
  1516. function setZeroTimeout(fn) {
  1517. timeouts.push(fn);
  1518. window.postMessage(messageName, "*");
  1519. }
  1520. function handleMessage(event) {
  1521. if (event.source == window && event.data == messageName) {
  1522. event.stopPropagation();
  1523. if (timeouts.length > 0) {
  1524. var fn = timeouts.shift();
  1525. fn();
  1526. } } }
  1527. window.addEventListener("message", handleMessage, true);
  1528. // Add the one thing we want added to the window object.
  1529. window.setZeroTimeout = setZeroTimeout;
  1530. })();
  1531.  
  1532. document.addEventListener('mouseup', showLookupIcon, false);
  1533. document.addEventListener('mousedown', mousedownCleaning, false);
  1534. // http://www.senojflags.com/#flags16
  1535. if( location.href == senojflags[0]
  1536. //|location.href == senojflags[1]
  1537. ){try{
  1538. if(!fCSS) fCSS=
  1539. 'div#flags16 img {cursor: pointer !important}'+
  1540. 'div#flags48,div#flags32 {display:none; visibility: hidden}'
  1541. stickStyle(fCSS);
  1542. _log('inside\n' + location.href);
  1543. insBefore(buildEl('p',{style:'font: bold italic 90% sans-serif; color:red;',
  1544. align:'left'},null,'&nbsp;&nbsp;<u>Click on a country flag icon then choose the language</u>'),
  1545. getId('flags16').childNodes[0]);
  1546. getId('flags16').addEventListener('click',flagClick,false)
  1547. }catch(e){console.log('senojflags\n'+e)}
  1548. }
  1549. }catch(e){console.log('nobody\n'+e); }
  1550. }
  1551. main();
  1552. }
  1553. //