// ==UserScript==
// @name translate.google tooltip
// @namespace trespassersW
// @author trespassersW
// @copyright trespassersW
// @license MIT
// @description Translates selected text into a `tooltip' via Google translate
// @include http://*
// @include https://*
// @include file://*
// about:config -> greasemonkey.fileIsGreaseable <- true
// @homepageURL https://openuserjs.org/scripts/trespassersW/translate.google_tooltip
// @version 16.01.20.1
//* This is a descendant of lazyttrick's http://userscripts.org/scripts/show/36898.
// 16.01.20.0 * a bunch of small hotfixes
// 16.01.17-2 *+ translation from input/textarea fields
// 16.01.16.1 + alternative translation
// 4.1.02 2016-01-03 * left-click only
// 4.1.01 2015-12-17 * changes in translate.google API
// 3.9.50 2015-10-17 + multi-sentence; GM_menu item
// 3.9.10 2015-07-29 * fix for Ff39; + now works in chrome
// 3.7.96 2015-05-10 * TTS in ff37; * DOMparser instead of IFRAME; * bugfixes
// 3.7.8.2 2015-04-26 + new country flags host
// 3.7.2 2015-04-20 * TTS: alt-select text inside tooltip and [ctrl/shift]-click language icon below
// * [shift] tts window in IFRAME (: only works on google.* and file://* :(
// * [ctrl] tts window in new tab
// 3.6.2.2 2015-04-19 * gray gradient background
// 3.5.1 2015-04-15
// + TTS: alt-select text inside tooltip and shift-click language icon below
// * From<->To buttons fix; * err handler
// 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.2 - history of translations
// 2.1.2 - Selected text is fetched in the moment when you hover over the icon.
// So, you can select a few letters, then adjust your selection using shift + arrows.
// 2.0.0d - native GT languages list
// 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
//*/
// /grant GM_addStyle
// @grant GM_getValue
// #grant GM_log
// @grant GM_openInTab
// @grant GM_setValue
// @grant GM_xmlhttpRequest
// @grant GM_registerMenuCommand
// @grant GM_setClipboard
// @connect-src translate.google.com
// @connect-src cdn.rawgit.com
// @icon data:image/jpg;base64, R0lGODlhIAARALP/AAAAAP///xMYfAqf////Zv/qDuCeH8VmB8DAwAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAgALAAAAAAgABEAQASdEMlJgb00awkMKQZYjB8RBsE4AtLQvtt0sXHcEcT1pbxK0hsXRmYIGUUgA3DiQjQtssInRAjglMsa4ibtlqSGgECQymmaAwDYUhSFfKoQDQ3LdA6Hoh6qbW4sJHpFWTUAOEA3Vj1WZjF+HQU9X18oPxl0Wx4kXoFiZF1zMEJgbW8qJnAHoU4takocpW5IIISYGh1HRlh9hRZ4eIRaEQA7
//
// @downloadURL none
// ==/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=t";
var ttsURL= "https://translate.google.com/translate_tts?client=t";
var version= 3790;
var HREF_NO = 'javascript:void(0)';
var llii=0, _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);
gt_sl !='auto' && divUse.appendChild(divBack);
addEl(divUse,'img',{id: 'imgUse', border: 0,
title: 'use in history\n[shift] add to history', src: imgUse},
null,null);
// tp=(evt.clientY+window.pageYOffset+30)+'px';
// lf=(evt.clientX+window.pageXOffset+30)+'px';
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');
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);
sl != 'auto' && divLookup.appendChild(iBack);
}else{ // right half
sl != 'auto' && 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){
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;
}
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 gtRequest(txt,s,t){
var etxt = squashTxt(txt);
// !!! 015-12-17
etxt=GTurl + "#" + s + _l_ + t + _l_ + etxt;
currentURL = etxt ;
// if( 0 || !((s==last_sl && t==last_tl) || (s==last_tl && t==last_sl)) || (divExtract=='')){ // !!! 015-12-17
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"
}
//console.log('R: '+Url+'\nD: "'+Data+'"');
GM_xmlhttpRequest({
method: meth,
url: Url,
data: Data,
headers: Hdr,
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 + "langpair=" + last_sl + "|" + last_tl + "&text=" + squashTxt(txtSel,12);
var q=GTurl + "#" + last_sl + _l_ + last_tl + _l_ + squashTxt(txtSel,22);
GM_openInTab(q);
}
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;
}
html2 = html2[1].replace(/\