// ==UserScript==
// @name translate.google tooltip
// @namespace trespassersW
// @author trespassersW
// @copyright trespassersW
// @license MIT
// @description Translates selected text into a `tooltip' via Google translate
// @include *
// about:config -> greasemonkey.fileIsGreaseable <- true
// /homepahe https://github.com/trespassersW/UserScripts/blob/master/show/translate.google_tooltip.md
// @version 19.09.16
//* This is a descendant of lazyttrick's http://userscripts.org/scripts/show/36898.
// 19.09.16 * tiny fix
// 19.09.11 * encodeURIComponent( translated_txt )
// 19.04.02 * TTS in detected language
// 18.11.30 * changes in GT API
// 18.01.15 ++ TTS buttons for source and translation
// 17.03.11 + keep text formatting
// 16.10.26 + phonetic transcription
// 16.09.01 + 'previous translation' button; [*] top of tooltip at top of client window
// 16.08.26 + option for left/right tooltip position; keeps tooltip position after dragging
// 16.08.16 + Word Definition is shown when source_language == target_language
// 16.03.09 + bookmarlets interface -- javascript:postMessage('tgtooltip/auto/fr','*')
// 16.01.17-2 *+ translation from input/textarea fields
// 16.01.16.1 + alternative translation
// 3.7.2 2015-04-20 * TTS: alt-select text inside tooltip and [ctrl/shift]-click language icon below
// * [shift] tts window in IFRAME
// * [ctrl] tts window in new tab
// 3.0.0 - national flags icons -- from www.senojflags.com
// 2.3 - new editable 'source text' field
// 2.2.2 - backward translation - select text inside tooltip and click the icon under your selection.
// 2.2.1 - Ctrl-Alt-click removes item from the history of translations
// - Ability to change translation in the history -
// select desired translation in the tooltip window using ctrl or alt -
// which one is checked in your settings - then click on the icon below the selection.
// 2.0.0c Alt key option added
// If something goes wrong:
// Tools->SQLite manager-> Database-> Connect_database->
// %YourBrowserProfile%\gm_scripts\translate.google_tooltip.db ->
// scriptvals-> alt/ctrl <- false
// 2.0.0b
// - exit by ESC
// - 1k letters limit -- don't strain your Google
//*/
// /require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// @grant GM_info
// @grant GM_getValue
// @grant GM_openInTab
// @grant GM_setValue
// @grant GM_xmlhttpRequest
// @grant GM_registerMenuCommand
// @grant GM_setClipboard
// @connect translate.google.com
// @connect cdn.rawgit.com
// @icon data:image/jpg;base64, R0lGODlhIAARALP/AAAAAP///xMYfAqf////Zv/qDuCeH8VmB8DAwAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAgALAAAAAAgABEAQASdEMlJgb00awkMKQZYjB8RBsE4AtLQvtt0sXHcEcT1pbxK0hsXRmYIGUUgA3DiQjQtssInRAjglMsa4ibtlqSGgECQymmaAwDYUhSFfKoQDQ3LdA6Hoh6qbW4sJHpFWTUAOEA3Vj1WZjF+HQU9X18oPxl0Wx4kXoFiZF1zMEJgbW8qJnAHoU4takocpW5IIISYGh1HRlh9hRZ4eIRaEQA7
//
// @downloadURL https://update.greasyfork.icu/scripts/9285/translategoogle%20tooltip.user.js
// @updateURL https://update.greasyfork.icu/scripts/9285/translategoogle%20tooltip.meta.js
// ==/UserScript==
if(document.body){
var main = function (){ "use strict";
var GTsuffix=".com"; // ".fr" ".de" ".ru" ".com"
//{[ hacks
var UA = navigator.userAgent;
0 && (UA="Mozilla/5.0 (Windows NT 5.1; rv:39.0) Gecko/20100101 Firefox/39.0");
//]}
var isChrome= (navigator.userAgent.indexOf("AppleWebKit")>0);
var moz=isChrome? "-webkit-": "-moz-";
var GTurl= "https://translate.google"+GTsuffix+"/?";
//var dictURL= "https://translate.google"+GTsuffix+"/translate_a/t?client=t";
var dictURL= "https://translate.google"+GTsuffix+"/translate_a/single?client=webapp";
var ttsURL= "https://translate.google.com/translate_tts?client=t";
var HREF_NO = 'javascript:void(0)';
var llii=1, _log = function(){ /* * /
for (var s=++llii +':', li=arguments.length, i = 0; i
1024){
return;
}
//exit if no text is selected
if(!txtSel || txtSel===""){
_log('S:notext ')
if(divDic) {
if(!clickedInsideID(evt.target,'divDic'))
cleanUp('no sel');
}
if(divLookup){
killId(divLookup);
}
return;
}
//possible cleanup
if(divDic){
if(!clickedInsideID(evt.target,'divDic'))
{cleanUp('!divdic'); return; }
// inside divDic:
var dU=getId('divUse');
if(dU){
if(!clickedInsideId('divUse')){
killId(dU);
} return;
}
try{
var p= belowCursor(evt,10,10,'r');
var divUse= buildEl('div', {id:'divUse',
style:'z-index:110000; border: none'+
';top:' + p.t +';left:' + p.l +';right:' + p.r +';bottom: auto;'
}, null, null );
var iTo = getFlagSrc(gt_tl,'to');
var divForw=buildEl('span', {id:'divGetforw', // 'class': 'gootranslink', href: HREF_NO,
//border: 0, src: iTo,
title: gt_sl_gms + '\u2192 '+gt_tl_gms +sayTip+gt_tl+')'},
null, imgH+iTo+imgT);
// ['mousedown', forwLookup], imgH+iTo+imgT);
divUse.appendChild(divForw);
var iFrom = getFlagSrc(gt_sl,'from');
var divBack=buildEl('span', {id:'divGetback', //'class': 'gootranslink', href: HREF_NO,
//border: 0, src: iFrom,
title: gt_tl_gms + '\u2192 '+gt_sl_gms +sayTip+gt_sl+')'},
null, imgH+iFrom+imgT);
// ['mousedown', backLookup], imgH+iFrom+imgT);
if(gt_sl!='auto' && gt_sl!=gt_tl) divUse.appendChild(divBack);
addEl(divUse,'img',{id: 'imgUse', border: 0,
title: 'use in history\n[shift] add to history', src: imgUse},
null,null);
body.appendChild(divUse);
}catch(e){console.log('use hist\n'+e)}
return;
}
// inside page
if(!isInited) {css(-1); isInited=true; }
//remove div if exists
if(divLookup)
killId(divLookup);
//div container
p = belowCursor(evt,10,10);
divLookup = buildEl('div', {id:'divLookup', style: 'z-index:100000'+
';border: none;' +
';top:' + p.t +';left:' + p.l +';right:' + p.r +';bottom: auto'
}, null, null);
iTo = getFlagSrc(GM_getValue('to'),'to');
var iForw=buildEl('img', {'border':0, id:"imgLookForw", style: 'padding-left: 5px',
src: iTo}, ['mouseover', lookup],null);
var sl=GM_getValue('from','auto'),tl=GM_getValue('to','auto');
iFrom = getFlagSrc(sl,'from');
var iBack=buildEl('img', {'border':0, id:"imgLookBack", style: 'padding-left: 5px',
src: iFrom},
['mouseover', lookup], null);
if(p.r == 'auto' ){ // left half
divLookup.appendChild(iForw);
if(sl != 'auto' && (sl!=tl)) divLookup.appendChild(iBack);
}else{ // right half
if(sl != 'auto' && (sl!=tl)) divLookup.appendChild(iBack);
divLookup.appendChild(iForw);
}
body.appendChild(divLookup);
}
function escCleanup(e){
if(!e.shiftKey && !e.ctrlKey && !e.altKey && e.keyCode==27 ){
cleanUp('esc');
document.removeEventListener('keydown', escCleanup,false);
escHnd=null;
}
}
function lookup(evt,aS,aT){
var divResult = null;
var divDic = getId('divDic');
var divLookup = getId('divLookup');
var top = divLookup.style.top;
var left = divLookup.style.left;
var rite = divLookup.style.right;
var txtS = txtSel; // 2012-08-20
if(evt) txtSel = getSelection(inTextArea? inTextArea: evt.target)+'';
if(!txtSel) txtSel = txtS;
if(txtSel.length>1024){
return;
}
//exit if no text is selected
if(!txtSel || txtSel==""){
_log('L:notext')
if(divDic) {
if(!clickedInsideID(evt.target,'divDic'))
killId(divDic);
}
killId('divLookup');
killId('divDic');
return;
}
//cleanup divs
killId('divDic');
killId('divLookup');
//div container document.body.clientHeight/Width
divDic = buildEl('div',
{id:'divDic', style: 'top:'+top+';left:'+left+';right:'+rite+
';position:absolute!important;z-index:110000!important;'
});
divDic.addEventListener('mousedown', dragHandler, false);
setEscHnd();
body.appendChild(divDic);
// patch gmail
if(document.contentEditable)
documentcontentEditable = document.contentEditable,
document.contentEditable = false;
if(document.designMode == 'on')
documentdesignMode='on',
document.designMode='off';
//div result
divResult = buildEl('div',
{id:'divResult'}, null, 'Loading...');
divDic.appendChild(divResult);
/**/
// history
var divBottom = buildEl('div',{id:'divBottom', align: 'bottom'},null,null);
addEl(divBottom,'a',
{'class':"gootransbutt gootranslink gtlPassive", id:'historyLink', title: 'Translation history',
align: 'left', href:HREF_NO},
['click', history], 'History');
addEl(divBottom,'a',
{'class':"gootransbutt gootranslink gtlPassive", id:'sourceLink', title: 'Source', href:HREF_NO},
['click', source],'Source');
//options link
addEl(divBottom,'a',
{'class':"gootransbutt gootranslink gtlPassive", id:'optionsLink', title: 'Settings', href:HREF_NO},
['click', options], 'Options');
divDic.appendChild(divBottom);
/**/
//lookup
gt_sl = GM_getValue('from', 'auto');
GT_tl = (gt_tl = GM_getValue('to',GT_tl));
if( evt && evt.target.id== 'imgLookBack' ){
var t=gt_tl; gt_tl=gt_sl; gt_sl=t;
}
if(aT){gt_tl=aT; gt_sl=aS;}
gtRequest(txtSel,gt_sl,gt_tl);
}
var IFR;
function eStop(e){e.preventDefault(),e.stopPropagation()}
function openInFrame(url){
killId('divTtsIfr');
var dD=getId('divDic');
var IFR=buildEl('div',{id:'divTtsIfr'},null,null);
var IFH=addEl(IFR,'div',{id:'divTtsIfh'},null,null);
addEl(IFH, 'span',{'class':"gootransbutt gootranslink",style: 'color:red!important;'},
['click', function(e){killId('divTtsIfr')}],'✖');
addEl(IFH, 'a',{'class':"gootransbutt gootranslink", id: 'divTtsLnk',
href: url, target:"_blank", title: 'play in tab'},
['click',
function(e)
{eStop(e);GM_openInTab(e.target.href)}
],
'');
addEl(IFH, 'span', {},[],deURI(url));
// addEl(IFR, 'br');
var BFR=
addEl(IFR, 'iframe',{
width: "100%", height: "48", frameborder: "0",scrolling:"auto", marginheight:"0", marginwidth:"0",
style:'padding-top:3px;overflow-x:hidden;',
src: 'about:blank'
},
null,null);
insAfter(IFR,getId('divBottom'));
BFR.contentWindow.location.href=url;
/*
*/
}
var soundSL=null,dictSL=null;
function ttsRequest(txt,t,e){
//
txt=txt.split(' ').slice(0,19).join(' ');
var tk=googleTK(txt,soundSL);
soundSL=tk.SL;
var etxt = escAp(txt);
etxt=ttsURL + "&ie=utf-8&tl=" + t + "&tk="+tk.tk+ "&q=" + etxt;
_log('tts> '+etxt);
if(e)
GM_openInTab(etxt);
else
openInFrame(etxt);
//GM_openInTab(etxt);
// sorry, firefox' decodeAudioData() does NOT support mp3
}
//
function squashTxt(t,n){
t=escAp(t); n=n || 10;
t=t.split(/%20|\s|\.|;|,/).slice(0,n).join('%20');
return t.substr(0,(n*110));
}
function stayOnTop(){ /*160901*/
var divDic = getId('divDic');
if(!divDic) return;
var yo=parseInt(divDic.style.top);
if(divDic && (yo < pageYOffset)) {
divDic.style.top=(pageYOffset+5)+'px';
}}
function gtRequest(txt,s,t){
if( !wayBack[1] || (wayBack[1].t!=s || wayBack[1].t!=t || wayBack[1].txt!=txt))
wayBack[0]=wayBack[1], wayBack[1]={txt:txt,s:s,t:t};
var etxt = squashTxt(txt);
etxt=GTurl + "#" + s + _l_ + t + _l_ + etxt;
currentURL = etxt ;
if(!divExtract){
divExtract = '';
Request(etxt);
}else{
extractResult(null);
}
last_sl = s; last_tl = t;
}
function Request(url,cb){
var Url=url, meth=(1 && cb)? 'POST': 'GET';
var Data='';
var Hdr= {
"User-Agent": UA
,"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
,"Accept-Encoding": "gzip, deflate"
//,"Host": "www.google.com"
}
if(1 && cb){
var Q=url.split('&q=');
Url=Q[0];
Data='&q='+Q[1];
Hdr["Content-Length"]=Data.length+'';
Hdr["Content-Type"]="application/x-www-form-urlencoded; charset=UTF-8"
}
GM_xmlhttpRequest({
method: meth,
url: Url,
data: Data,
headers: Hdr,
synchronous: false, /* 17.11.30 */
onload: function(resp) {
if(cb)
cb(resp.responseText)
else
extractResult(resp.responseText);
}
});
}
function quickLookup(){
gt_sl=getId('optSelLangFrom').value;
gt_tl=getId('optSelLangTo').value;
GT_tl=gt_tl;
saveIt();
gtRequest(txtSel,gt_sl,gt_tl);
}
function histLookup(e){
try{
var txt=e.target.textContent, ix=-1;
//.innerHTML??
e.preventDefault();
var ha = getTag('a',getId('divHist'));
// ix=ha.indexOf(e.target);
/**/
for(var i=0,l=ha.length; i[\s\S]*?\<\/title\>/);
if(m && m[1])
addEl(dr,'p',{},null,m[1]);
//id="captcha"
m=html.match(/(
)/);
if(m && m[1])
addEl(dr,'p',{},null,m[1]);
//_log(html);
return;
}
function goGoogle(e){
e.preventDefault(), e.stopPropagation();
var q=GTurl + "#" + last_sl + _l_ + last_tl + _l_ + squashTxt(txtSel,22);
GM_openInTab(q);
}
function toggleFormat(e){
e.preventDefault(), e.stopPropagation();
formatted= !formatted;
GM_setValue('formatted', formatted);
gtRequest(formatted?txtSelO:txtSel,gt_sl,gt_tl);
}
var wayBack =[null,null];
function goBack(e){
e.preventDefault(), e.stopPropagation();
if(wayBack[0]){
killId('divUse');
gtRequest(txtSel=wayBack[0].txt,gt_sl=wayBack[0].s,gt_tl=wayBack[0].t);
}
}
var ex_sl , ex_tl;
function extractResult(html){
if(html){
var html2 = html.match(/\]*\>([\s\S]+)\<\/body\>/);//[1];//select body content
if(!html2){ // too many lettters!!!11
badResponce(html); return;
}
//-----------------------------------------------------------------------------------
if(!TKK){
// tkk:'427857.2665959115'
// TKK='427882.1140482906'
var res = /tkk\:'(.*?)'/.exec(html);
if (!res) res=/TKK\='(.*?)'/.exec(html);
if(res && res[1]) TKK=res[1];
if (!TKK) {
/**** /
var res2 = /var a=(.*?);.*?var b=(.*?);.*?return (\d+)/i.exec(res[1].replace(/\\x3d/g, '='));
if (res2 != null) {
TKK = Number(res2[3]) + '.' + (Number(res2[1]) + Number(res2[2]));
}
/****/
/**** /
var iH=html;
iH=iH.replace(/\'+iH+'';
/****/
} }
if(!TKK) {console.log("gttp: ERROR - can't get TKK!!!"); stopScript();}
// else console.log('TKK:'+TKK);
//-----------------------------------------------------------------------------------
html2 = html2[1].replace(/\