'use strict';
// ==UserScript==
// @name translator
// @namespace https://lufei.so
// @supportURL https://github.com/intellilab/translator.user.js
// @description 划词翻译
// @version 1.5.8
// @run-at document-start
// @grant GM_addStyle
// @grant GM_xmlhttpRequest
// @downloadURL none
// ==/UserScript==
var styles = {"container":"_container_qygl2_1","panel":"_panel_qygl2_6","body":"_body_qygl2_11","header":"_header_qygl2_24","detail":"_detail_qygl2_35"};
GM_addStyle("._container_qygl2_1 {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n._panel_qygl2_6 {\n position: fixed;\n max-width: 300px;\n z-index: 10000;\n}\n._body_qygl2_11 {\n position: relative;\n padding: 8px;\n border-radius: 4px;\n border: 1px solid #eaeaea;\n line-height: 24px;\n color: #555;\n background-color: #fff;\n font-family: monospace, consolas;\n font-size: 14px;\n text-align: left;\n word-break: break-all;\n}\n._header_qygl2_24 {\n padding: 0 0 8px;\n border-bottom: 1px dashed #aaa;\n color: #333;\n}\n._header_qygl2_24 > [data-type] {\n margin-left: 8px;\n color: #7cbef0;\n cursor: pointer;\n font-size: 13px;\n}\n._detail_qygl2_35 {\n margin: 8px 0 0;\n line-height: 22px;\n list-style: none;\n font-size: 13px;\n}\n._detail_qygl2_35 > li {\n font-size: 13px;\n line-height: 26px;\n}\n");
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,
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 nosm = '♥';
var header = document.createElement('div');
header.className = styles.header;
header.innerHTML = [`${htmlEntities(query)}`, `uk:[${uk || nosm}]`, `us:[${us || nosm}]`].join('');
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 = styles.detail;
for (var i = 0; i < explains.length; i += 1) {
var li = document.createElement('li');
li.innerHTML = explains[i];
ul.appendChild(li);
}
body.appendChild(ul);
}
} else if (translation) {
var div = document.createElement('div');
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 audio = document.createElement('audio');
audio.autoplay = true;
var panel = document.createElement('div');
panel.className = styles.panel;
var panelBody = document.createElement('div');
panelBody.className = styles.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);
return {
audio,
panel,
body: panelBody
};
}