Last active
September 14, 2016 04:16
-
-
Save creamidea/c13b2deae88c1906e43eff8e205815af to your computer and use it in GitHub Desktop.
Improve the experience of the Youdao Dictionary. Thank you: dict.youdao.com && etymonline.com :D
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Youdao Dictionary Enhancer | |
// @namespace http://tampermonkey.net/ | |
// @version 1.1 | |
// @description search words Celerity | |
// @author creamidea | |
// @match http://dict.youdao.com/* | |
// @require http://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.js | |
// @resource nprogress_css http://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css | |
// @resource etymoline_css http://www.etymonline.com/style.css | |
// @resource etymoline_font http://fonts.googleapis.com/css?family=Slabo+27px:400&lang=en | |
// @grant GM_setValue | |
// @grant GM_getValue | |
// @grant GM_addStyle | |
// @grant GM_getResourceText | |
// @grant GM_xmlhttpRequest | |
// @connect www.etymonline.com | |
// @updateURL | |
// ==/UserScript== | |
// changelog: | |
// version 1.1 add you translation icon | |
// version 1.0 initial release | |
GM_addStyle (GM_getResourceText("nprogress_css")); | |
GM_addStyle (".youdao-trans-icon {position: absolute;border-radius: 5px;padding: 3px; background-color: rgb(245, 245, 245);box-sizing: content-box;cursor: pointer;height: 18px;width: 18px;z-index: 2147483647;border: 1px solid rgb(220, 220, 220);color: rgb(51, 51, 51);}"); | |
GM_addStyle (".etymoline .hint {text-align: center;font-size: 24px;margin: 24px 0;color: rebeccapurple;}"); | |
(function() { | |
'use strict'; | |
if (NProgress === undefined) | |
NProgress = { | |
set: function (){}, | |
start: function (){}, | |
inc: function (){}, | |
done: function (){}, | |
configure: function (){}, | |
}; | |
var ETYMONLINEHTTP = 'http://www.etymonline.com'; | |
var YOUDAOHTTP = 'http://dict.youdao.com'; | |
var $scontainer = $('#scontainer'); | |
var $query = $('#query'); | |
var $topImgAd = $('#topImgAd'); | |
var $webTrans = $('#webTrans'); | |
var injectEtymolineName = 'creamidea' + makeId(9); // make the name of injecting function is unique | |
var openURLFunName = 'openurl' + makeId(9); | |
var proxySelection = 'proxySelection' + makeId(9); | |
var sltContainerName = 'selectionContainer' + makeId(9); | |
var youdaoSearchButtonId = 'youdaoSearchButton' + makeId(9); | |
// window global function. It is the callback in the iframe | |
window[injectEtymolineName] = function (event) { | |
// open the next page in the etymoline.com iframe | |
event.preventDefault(); | |
var target = event.target; | |
request(ETYMONLINEHTTP+target.attributes.href.value); | |
}; | |
window[openURLFunName] = function (event) { | |
event.preventDefault(); | |
location.href = event.target.attributes.href.value; | |
}; | |
window[proxySelection] = function (event) { | |
var sel = window.getSelection(); | |
var range = document.createRange(); | |
var targetSel = this.getSelection(); | |
var $sltContainer = $('#'+sltContainerName); | |
var selectionText = targetSel.toString(); | |
var $youdaoSearchButton = $('#'+youdaoSearchButtonId); | |
if ($sltContainer.length === 0) | |
$sltContainer = $('<div id='+sltContainerName+' />').appendTo('body'); | |
if ($youdaoSearchButton.length === 0) | |
$youdaoSearchButton = $('<butotn id='+youdaoSearchButtonId+' class="youdao-trans-icon">').append('<a href="javascript: void(0)"><img src="http://shared.ydstatic.com/images/favicon.ico"></a>').appendTo('body'); | |
if (selectionText === "") { | |
$youdaoSearchButton.css({display: 'none'}); | |
return; | |
} | |
$sltContainer.css({position: "absolute",zIndex: -1,top: "-1000px"}).text(selectionText); | |
setTimeout(function () { | |
$youdaoSearchButton.find('a').attr('href', YOUDAOHTTP + '/w/'+selectionText+'/') | |
.end().css({left: $('#'+injectEtymolineName).data('click-x'), top: $('#'+injectEtymolineName).data('click-y'), display: 'block'}); | |
}, 24); | |
range.selectNode($sltContainer[0]); | |
sel.removeAllRanges(); | |
sel.addRange(range); | |
// range.setStart(targetSel.anchorNode, targetSel.anchorOffset); | |
// range.setEnd(targetSel.focusNode, targetSel.focusOffset); | |
// sel.removeAllRanges(); | |
// sel.empty(); | |
// sel.setBaseAndExtent(targetSel.anchorNode, targetSel.anchorOffset, targetSel.focusNode, targetSel.focusOffset); | |
// window.getSelection().anchorNode.textContent.substring(this.getSelection().extentOffset, this.getSelection().anchorOffset); | |
}; | |
// create the frame wrapper | |
var $frameWrapper = | |
$('<div id='+injectEtymolineName+'-wrapper class="etymoline"/>').css({border:0, width: '100%'}).html( | |
'<div class="hint">Etymoline.com ...</div>'); | |
if ($webTrans.length === 0) return; // maybe no result :) | |
$frameWrapper.insertBefore($webTrans); | |
// set NProgress | |
NProgress.configure({parent: '#' + injectEtymolineName + '-wrapper'}); | |
NProgress.set(0.7); | |
NProgress.inc(0.2); | |
// request the etymoline.com page | |
request(ETYMONLINEHTTP+'/index.php?term='+encodeURIComponent($query.val())); | |
// remove the ad | |
$topImgAd.remove(); | |
$('#baidu-adv').remove(); | |
$('#follow').remove(); | |
$('#webTrans .tabs a').each(function (i, link) { | |
if (link.innerText === '英英释义') | |
link.click(); | |
}); | |
// from: http://stackoverflow.com/a/12444641/1925954 | |
var keys = {}; | |
function test_key(selkey){ | |
var alias = { | |
"Ctrl": 17, | |
"Shift": 16, | |
"/": 191, | |
"a": 65, | |
"e": 69 | |
}; | |
return keys[selkey] || keys[alias[selkey]]; | |
} | |
function test_keys(){ | |
var i, | |
keylist = arguments, | |
status = true; | |
for(i = 0; i < keylist.length; i++){ | |
if(!test_key(keylist[i])){ | |
// status = false; | |
return false; | |
} | |
} | |
return status; | |
} | |
$(document).keydown(function (event) { | |
var keyCode = event.keyCode; | |
keys[keyCode] = event.type === 'keydown'; | |
if (test_keys('Shift', 'e')) { | |
if ($('.baav .voice-js')[0]) $('.baav .voice-js')[0].click(); | |
keys = {}; | |
return false; | |
} else if (test_keys('Shift', 'a')) { | |
if ($('.baav .voice-js')[1]) $('.baav .voice-js')[1].click(); | |
keys = {}; | |
return false; | |
} else if (test_keys('Shift', '/')) { | |
// ? => help | |
toggleHelp(); | |
keys = {}; | |
return false; | |
} else if (test_keys('/')) { | |
$query.focus().select(); | |
keys = {}; | |
return false; // to avoid input '/' in inputbox. | |
} | |
}).keyup(function (event) { | |
var keyCode = event.keyCode; | |
keys[keyCode] = false; | |
}); | |
// adjust the youdao css | |
// move xxx | |
$('#container').css({width: "1000px"}); | |
$('#results').css({width: "680px"}); | |
$('#ads').css({width: "320px"}); | |
var transformToggle = []; | |
$('#eTransform .tabs').children().each(function(index, elt){ | |
transformToggle.push(elt.innerText); | |
}); | |
$('#transformToggle').children().each(function(index, elt){ | |
if(elt.id === 'wordGroup') return; | |
var $clone = $(elt).clone(); | |
$clone.addClass('follow').removeClass('hide').css({display: 'block'}).prepend('<p class="hd">'+transformToggle[index]+'</p>').next().css({marginTop: "8px"}); | |
$clone.appendTo('#ads'); | |
});//.end().parent().remove(); | |
$('#doc>.c-topbar-wrapper').css({height: "81px", top: "-42px"}).find('.c-subtopbar').remove(); | |
$scontainer.css({marginTop: "42px"}); | |
function request (url) { | |
NProgress.start(); | |
var xhr = new GM_xmlhttpRequest({ | |
method: 'GET', | |
url: url, | |
// anonymous: true, | |
onreadystatechange: onreadystatechange, | |
}); | |
} | |
function onreadystatechange (resp) { | |
var readyState = resp.readyState; | |
if (readyState === 0) { | |
// Client has been created. open() not called yet. | |
} else if (readyState === 1) { | |
// open() has been called. | |
} else if (readyState === 2) { | |
// send() has been called, and headers and status are available. | |
} else if (readyState === 3) { | |
// Downloading; responseText holds partial data. | |
} else if (readyState === 4) { | |
switch(resp.status) { | |
case 200: | |
etymolineHandler(resp.responseText); | |
break; | |
default: | |
GM_log(['Ger Error: ', '\nState: ', resp.readyState, '\nMessage: ', resp.responseText].join('')); | |
} | |
NProgress.done(); | |
} | |
} | |
function etymolineHandler (responseText) { | |
var domParser = new DOMParser(); | |
var doc = domParser.parseFromString(responseText, 'text/html'); | |
var $dictionary = doc.querySelector('#dictionary'); | |
$dictionary.style.border = 0; | |
$dictionary.style.marginBottom = 0; | |
var $frame = $('#'+injectEtymolineName); | |
if ($frame.length === 0) { | |
$frame = $('<iframe id="'+injectEtymolineName+'" />').css({border:0, width: '100%', maxHeight: '600px'}); | |
$frameWrapper.append($frame); | |
$frameWrapper.find('.hint').remove(); // remove the hint. | |
$frame.contents().find("head") | |
.append('<style>'+GM_getResourceText("etymoline_css")+'</style>') | |
.append('<style>'+GM_getResourceText("etymoline_font")+'</style>') | |
.append('<style>' + | |
'.etymoline-footer {border: 0px;color: wheat;text-align: right;}' + | |
'</style>'); | |
// $frame.contents().on('selectionchange', function () {debugger}); | |
$frame.contents() | |
.on('selectionchange', parent[proxySelection]) | |
.on('mousemove', function (event) { $frame.data('click-x', $frame.offset().left + event.pageX); $frame.data('click-y', $frame.offset().top + event.pageY - 30); }); | |
} | |
$frame.contents().find("body") | |
.html($dictionary) | |
.append('<footer class="etymoline-footer">From: <a href="http://www.etymonline.com/index.php" style="color: wheat;" target="_blank">The Online Etymology Dictionary</a></footer>'); | |
// Some fix | |
$frame.ready(function () { | |
$frame.css({height: $frame.contents().find("html").height() }); | |
$frame.contents().find("body img").map(function (index, img) { | |
// the resource path of dictionary png | |
img.src = ETYMONLINEHTTP+'/graphics/dictionary.gif'; | |
return img; | |
}); | |
$frame.contents().find("body a.dictionary").map(function (index, link) { | |
// click the png | |
link.target = '_blank'; | |
return link; | |
}); | |
$frame.contents().find("body #dictionary dl a").not('.dictionary').map(function (index, link) { | |
// click the word | |
// link.onclick = parent[injectEtymolineName]; | |
var oLink = new URL(link.href); | |
var term = oLink.search.slice(1).split('&').map(function(v){var _v = v.split('=');return {key: _v[0], value: _v[1]};}).filter(function(v){if(v.key==='term')return v;})[0]; | |
link.href = YOUDAOHTTP+'/w/'+term.value+'/'; | |
link.onclick = parent[openURLFunName]; | |
//link.href = link.href.replace(new RegExp(YOUDAOHTTP), ETYMONLINEHTTP); | |
//link.target = '_blank'; | |
// link.href = 'javascript:void(0);'; | |
// link.style.cursor = 'default'; | |
return link; | |
}); | |
$frame.contents().find("body .paging a").map(function (index, link) { | |
// The code below is just for fun :P | |
// var oLink = new URL(link.href); | |
// var p = oLink.search.slice(1).split('&').map(function(v){var _v = v.split('=');return {key: _v[0], value: _v[1]}}).filter(function(v){if(v.key==='p')return v;})[0].value | |
link.onclick = parent[injectEtymolineName]; | |
return link; | |
}); | |
}); | |
} | |
function makeId(len) { | |
if(isNaN(parseInt(len))) len = 8; | |
var text = ""; | |
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | |
for( var i=0; i < len; i++ ) | |
text += possible.charAt(Math.floor(Math.random() * possible.length)); | |
return text; | |
} | |
function toggleHelp () { | |
console.log('Message for help. Comming soon...'); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Reference: