// ==UserScript==
// @namespace ATGT
// @name bing-dict
// @name:zh-CN 必应词典
// @description Select any word in any web to show it's definition from Bing Dict.
// @description:zh-CN 划词翻译,使用必应词典
// @version 1.2
// @match http://*/*
// @match https://*/*
// -match https://github.com/*
// @grant GM.xmlHttpRequest
// @run-at document-end
// ==/UserScript==
/*
Change Log:
v1.2:
14 Jan 2018, Escape search word and result.
v1.1:
13 Jan 2018, Reset style for result div.
v1.0:
12 Jan 2018, Initial version.
*/
//alert("hello");
console.log("!!!!!!!!!!!!!!!!!!!!!bing-dict!!!!!!!!!!!!!!!!!!!!!!!!");
(function () {
(function addStyleSheet() {
var style = document.createElement("STYLE");
style.type = "text/css";
var css = `
div#ATGT-bing-dict-result-wrapper-reset {
all: initial;
* {
all: initial;
}
}
div#ATGT-bing-dict-result-wrapper {
display: block;
position: fixed;
left: 2px;
bottom: 2px;
max-width: 30%;
z-index: 2100000000;
padding: 0;
margin: 0;
color: black;
background-color: rgba(255,255,255,0.9);
font-size: small;
font-family: sans-serif;
}
div#ATGT-bing-dict-result-wrapper .headword {
font-weight: bold;
font-size: medium;
}
div#ATGT-bing-dict-result-wrapper a:link {
color: #37a;
text-decoration: none;
}
div#ATGT-bing-dict-result-wrapper a:hover {
color: white;
background-color: #37a;
}
div#ATGT-bing-dict-result-wrapper .headsentence {
}
div#ATGT-bing-dict-result-wrapper ul {
list-style-type: none;
padding: 1px;
margin: 0px;
}
div#ATGT-bing-dict-result-wrapper ul li{
margin-top: 1px;
}
div#ATGT-bing-dict-result-wrapper ul li span {
float:left;
color: white;
background-color: gray;
text-align: center;
padding: 0 2px;
margin-right: 3px;
}
`;
style.appendChild(document.createTextNode(css));
document.head.appendChild(style);
})();
var dictResultDiv = (function createDictResultDiv() {
var div_wrapper_reset = document.createElement("DIV");
div_wrapper_reset.id = "ATGT-bing-dict-result-wrapper-reset";
var div = document.createElement("DIV");
div.id = "ATGT-bing-dict-result-wrapper";
div_wrapper_reset.appendChild(div);
/*
div.style.position = "fixed";
div.style.left = "5px";
div.style.bottom = "5px";
div.style.textAlign = "left";
div.style.fontSize = "small";
div.style.maxWidth = "30%";
div.innerHTML = "";
div.style.backgroundColor = "rgba(255,255,255,0.95)";
div.style.color = "rgb(0,0,0)";
*/
document.body.appendChild(div_wrapper_reset);
return div;
})();
var dictCache = {};
var lastSearchWord = "";
var entityMap = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'/': '/',
'`': '`',
'=': '='
};
function escapeHtml (string) {
return String(string).replace(/[&<>"'`=\/]/g, function (s) {
return entityMap[s];
});
}
function parseDictResultDefinition(qdef, url) {
//console.log("parseDictResultDefinition");
//console.log("qdef ", qdef);
var hd_area = qdef.childNodes[0];
try {
var headword = escapeHtml(hd_area.querySelector("#headword").innerText);
} catch (e) {
var headword = "";
}
var hd_pr = "";
try { /* en to cn */
hd_pr = escapeHtml(hd_area.querySelector(".hd_prUS").innerText)
+ " "+escapeHtml(hd_area.querySelector(".hd_pr").innerText);
} catch (e) {
}
try {
if (!hd_pr) /* cn to en */
hd_pr = escapeHtml(hd_area.querySelector(".hd_tf_lh").innerText);
} catch (e) {
}
headword = "<div class='headword'>"
+ "<a href='"+url+"' target='_blank'>" + headword + "</a>"
+ "</div>";
hd_pr = "<div style='color: gray;'>" + hd_pr + "</div>";
try {
var def_area = qdef.childNodes[1];
var def_list = def_area.querySelectorAll("li");
var defs = "<ul>";
for (var def of def_list) {
defs += "<li><span>"
+ escapeHtml(def.childNodes[0].innerText) + "</span>" + escapeHtml(def.childNodes[1].innerText) + "</li>";
}
defs += "</ul>";
} catch (e) {
var defs = "";
}
return headword + hd_pr + defs;
}
function parseDictResultMachineTranslation(page, url) {
//console.log("parseDictResultMachineTranslation");
var trans_area = page.querySelector(".lf_area").childNodes[0];
var smt_hw = trans_area.querySelector(".smt_hw");
var headword = smt_hw.nextElementSibling;
var trans_result = headword.nextElementSibling;
smt_hw = "<div style='font-style: italic; font-size: x-small;'>" + escapeHtml(smt_hw.innerText) + "</div>";
headword = "<div class='headsentence'>"
+"<a href='"+url+"' target='_blank'>" + escapeHtml(headword.innerText) + "</a>"
+"</div>";
trans_result = "<div style='color: gray;'>" + escapeHtml(trans_result.innerText) + "</div>";
return smt_hw + headword + trans_result;
}
function parseDictResult(page, url) {
//console.log("page ", page);
var qdef = page.querySelector(".qdef");
//console.log("qdef ", qdef);
if (qdef)
return parseDictResultDefinition(qdef, url);
else if (!page.querySelector(".no_results"))
return parseDictResultMachineTranslation(page, url);
else
return "";
}
function searchBingDict(word) {
word = word.replace(/^\s*|\s*$/, "");
if (word.length == 0) { /* !/\w+/.test(word) */
dictResultDiv.innerHTML = "";
lastSearchWord = "";
return;
}
if (word in dictCache) {
console.log("cache hit ", word, " lastSearchWord ", lastSearchWord);
if (lastSearchWord != word) {
console.log("show");
dictResultDiv.innerHTML = dictCache[word];
lastSearchWord = word;
}
return;
} else {
console.log("cache miss");
dictResultDiv.innerHTML = "Searching \"" + escapeHtml(word) + "\"";
}
var url = "http://www.bing.com/dict/search?q="+encodeURIComponent(word);
var fallback_message = "Try <a href='https://www.bing.com/translator' target=_blank>Microsoft Translator</a>.";
console.log(url);
GM.xmlHttpRequest({
url : url,
method : "GET",
onload : function (response) {
//console.log("search dict ok", response);
try {
var parser = new DOMParser();
var doc = parser.parseFromString(response.responseText, "text/html");
var defs = parseDictResult(doc, url);
} catch (e){
var defs = "";
}
dictCache[word] = defs;
if (defs)
dictResultDiv.innerHTML = defs;
else
dictResultDiv.innerHTML = "<span style='color: red;'>Error</span> parsing result of \"" + escapeHtml(word) + "\"<br />" + fallback_message;
},
onerror : function (response) {
console.log("search dict fail");
dictResultDiv.innerHTML = "<span style='color: red;'>Error</span> searching \"" + escapeHtml(word) + "\"<br />" + fallback_message;
}
});
}
document.addEventListener("mouseup", function (event) {
var divRect = dictResultDiv.getBoundingClientRect();
//console.log("mouseup event ", event);
//console.log("result div x ", divRect.left, " - ", divRect.right, ", y ", divRect.top, " - ", divRect.bottom);
if (event.clientX >= divRect.left && event.clientX <= divRect.right &&
event.clientY >= divRect.top && event.clientY <= divRect.bottom) {
// Mouse is inside element.
return;
}
var sel = window.getSelection().toString();
console.log("selected: \"", sel, "\"");
searchBingDict(sel);
});
})();
console.log("!!!!!!!!!!!!!!!!!!!!!/bing-dict!!!!!!!!!!!!!!!!!!!!!!!!");