// ==UserScript==
// @name translate
// @namespace https://lufei.so
// @grant GM_xmlhttpRequest
// @description 划词翻译
// @version 1.4.0
// ==/UserScript==
var sel, panel, audio, query
audio = document.createElement('audio')
audio.autoplay = true
function setStyle(el, o) {
var x, arr = []
function toLineThrough(s) {
return s.replace(/[A-Z]/g, function(c) {
return '-' + c.toLowerCase()
})
}
for (x in o) {
arr.push(toLineThrough(x) + ': ' + o[x])
}
el.setAttribute('style', arr.join(';'))
}
function play(type) {
audio.src = 'https://dict.youdao.com/dictvoice?audio=' + window.encodeURIComponent(query) + '&type=' + type
}
function htmlEntities(s) {
var o = {
'<': '<',
'>': '>',
'&': '&',
'"': '"',
"'": '''
}
return s.replace(/[<>&"]/g, function(c) {
return o[c]
})
}
function decode(o) {
// variable
var us, uk, x
// element
var header, explains, web, translation
if (o.basic) {
us = o.basic['us-phonetic'] || ''
uk = o.basic['uk-phonetic'] || ''
query = o.query || ''
header = document.createElement('div')
setStyle(header, {
borderBottom : '1px dashed #aaa',
paddingBottom : '.5rem'
})
header.innerHTML = '<span style="color: #333">' + htmlEntities(query) + '</span>' + '<span data-type="1" style="margin-left: .5rem; color: #7cbef0; cursor: pointer">uk:[' + uk + ']</span>' + '<span data-type="2" style="margin-left: .5rem; color: #7cbef0; cursor: pointer">us:[' + us + ']</span>'
panel.appendChild(header)
header.onclick = function(e) {
if (e.target.dataset.type) play(e.target.dataset.type)
}
if (o.basic.explains) {
explains = document.createElement('ul')
setStyle(explains, {
margin : 0,
padding : 0,
listStyle : 'none',
lineHeight : '1.4rem',
fontSize : '.8rem',
marginTop : '.5rem'
})
explains.innerHTML = '<li>' + o.basic.explains.join('</li><li>') + '</li>'
panel.appendChild(explains)
}
} else if (o.translation) {
translation = document.createElement('div')
translation.innerHTML = o.translation[0]
setStyle(translation, {
margin : 0,
padding : 0,
lineHeight : '1.4rem',
fontSize : '.8rem'
})
panel.appendChild(translation)
}
}
panel = document.createElement('div')
setStyle(panel, {
position : 'fixed',
lineHeight : '1.5rem',
border : '1px solid #eaeaea',
backgroundColor : '#fff',
fontSize : '.8rem',
fontFamily : 'monospace, consolas',
textAlign : 'left',
borderRadius : '.2rem',
wordBreak : 'break-all',
maxWidth : '25rem',
color : '#555',
padding : '.5rem',
boxSizing : 'border-box'
})
document.addEventListener('mousedown', function(e) {
if (e.buttons != 2) if (sel) sel.removeAllRanges()
})
document.addEventListener('mouseup', function(e) {
var text
sel = window.getSelection()
text = sel.toString()
if (e.target === panel || panel.contains(e.target)) return
panel.innerHTML = ''
if (document.body.contains(panel)) document.body.removeChild(panel)
if (/^\s*$/.test(text)) 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=' + window.encodeURIComponent(text),
onload: function(data) {
data = JSON.parse(data.responseText)
if (data.errorCode === 0) {
decode(data)
panel.style.top = e.clientY + 10 + 'px'
panel.style.left = e.clientX + 'px'
document.body.appendChild(panel)
}
}
})
})