Greasy Fork is available in English.
划词翻译
当前为
(function () {
'use strict';
// ==UserScript==
// @name translator
// @namespace https://lufei.so
// @supportURL https://github.com/intellilab/translator.user.js
// @description 划词翻译
// @version 1.5.7
// @run-at document-start
// @grant GM_addStyle
// @grant GM_xmlhttpRequest
// ==/UserScript==
var translator = initialize();
var entities = {
'<': '<',
'&': '&'
};
function htmlEntities(str) {
return str && str.replace(/[<&]/g, function (char) {
return entities[char];
});
}
function render(data) {
var body = translator.body,
randKey = translator.randKey,
audio = translator.audio;
body.innerHTML = '';
var basic = data.basic,
query = data.query,
translation = data.translation;
if (basic) {
var us = basic['us-phonetic'],
uk = basic['uk-phonetic'],
explains = basic.explains;
var header = document.createElement('div');
header.className = `${randKey} ${randKey}-header`;
header.innerHTML = `\
<span>${htmlEntities(query)}</span>\
<span data-type="1">uk:[${uk}]</span>\
<span data-type="2">us:[${us}]</span>`;
body.appendChild(header);
header.addEventListener('click', function (e) {
var type = e.target.dataset.type;
if (type) {
audio.src = `https://dict.youdao.com/dictvoice?audio=${encodeURIComponent(query)}&type=${type}`;
}
});
if (explains) {
var ul = document.createElement('ul');
ul.className = `${randKey} ${randKey}-detail`;
for (var i = 0; i < explains.length; i += 1) {
var li = document.createElement('li');
li.className = randKey;
li.innerHTML = explains[i];
ul.appendChild(li);
}
body.appendChild(ul);
}
} else if (translation) {
var div = document.createElement('div');
div.className = randKey;
div.innerHTML = translation[0];
body.appendChild(div);
}
}
function translate(e) {
var sel = window.getSelection();
var text = sel.toString();
if (/^\s*$/.test(text)) return;
var _document = document,
activeElement = _document.activeElement;
if (['input', 'textarea'].indexOf(activeElement.tagName.toLowerCase()) < 0 && !activeElement.contains(sel.getRangeAt(0).startContainer)) return;
GM_xmlhttpRequest({
method: 'GET',
url: `https://fanyi.youdao.com/openapi.do?relatedUrl=http%3A%2F%2Ffanyi.youdao.com%2Fopenapi%3Fpath%3Dweb-mode&keyfrom=test&key=null&type=data&doctype=json&version=1.1&q=${encodeURIComponent(text)}`,
onload(res) {
var data = JSON.parse(res.responseText);
if (!data.errorCode) {
render(data);
var panel = translator.panel;
var _window = window,
innerWidth = _window.innerWidth,
innerHeight = _window.innerHeight;
if (e.clientY > innerHeight * 0.5) {
panel.style.top = 'auto';
panel.style.bottom = `${innerHeight - e.clientY + 10}px`;
} else {
panel.style.top = `${e.clientY + 10}px`;
panel.style.bottom = 'auto';
}
if (e.clientX > innerWidth * 0.5) {
panel.style.left = 'auto';
panel.style.right = `${innerWidth - e.clientX}px`;
} else {
panel.style.left = `${e.clientX}px`;
panel.style.right = 'auto';
}
document.body.appendChild(panel);
}
}
});
}
function debounce(func, delay) {
var timer = void 0;
function exec() {
timer = null;
func.apply(undefined, arguments);
}
return function () {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
if (timer) clearTimeout(timer);
timer = setTimeout.apply(undefined, [exec, delay].concat(args));
};
}
function initialize() {
var randKey = `it-${Math.random().toString(16).slice(2, 8)}`;
var audio = document.createElement('audio');
audio.autoplay = true;
var panel = document.createElement('div');
panel.className = `${randKey} ${randKey}-panel`;
var panelBody = document.createElement('div');
panelBody.className = `${randKey} ${randKey}-body`;
panel.appendChild(panelBody);
var debouncedTranslate = debounce(translate);
var isSelecting = void 0;
document.addEventListener('mousedown', function (e) {
isSelecting = false;
if (panel.contains(e.target)) return;
if (panel.parentNode) panel.parentNode.removeChild(panel);
panelBody.innerHTML = '';
}, true);
document.addEventListener('mousemove', function () {
isSelecting = true;
}, true);
document.addEventListener('mouseup', function (e) {
if (panel.contains(e.target) || !isSelecting) return;
debouncedTranslate(e);
}, true);
document.addEventListener('dblclick', function (e) {
if (panel.contains(e.target)) return;
debouncedTranslate(e);
}, true);
GM_addStyle(`\
.${randKey} {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.${randKey}-panel {
position: fixed;
max-width: 300px;
z-index: 10000;
}
.${randKey}-body {
position: relative;
padding: 8px;
border-radius: 4px;
border: 1px solid #eaeaea;
line-height: 24px;
color: #555;
background-color: #fff;
font-family: monospace, consolas;
font-size: 14px;
text-align: left;
word-break: break-all;
}
.${randKey}-header {
padding: 0 0 8px;
border-bottom: 1px dashed #aaa;
color: #333;
}
.${randKey}-header > [data-type] {
margin-left: 8px;
color: #7cbef0;
cursor: pointer;
font-size: 13px;
}
.${randKey}-detail {
margin: 8px 0 0;
line-height: 22px;
list-style: none;
font-size: 13px;
}
.${randKey}-detail > li {
font-size: 13px;
line-height: 26px;
}`);
return {
randKey,
audio,
panel,
body: panelBody
};
}
}());