// ==UserScript==
// @name 添加有道发音
// @namespace https://github.com/nameldk/user-script
// @version 0.2.2
// @description 百度翻译页面添加有道发音
// @author nameldk
// @match https://fanyi.baidu.com/
// @grant none
// @note 2021.07.21 v0.2.2 修复不能获取最新输入内容的问题
// @note 2021.05.28 v0.2.1 添加加载中效果
// @note 2021.05.27 v0.2 手机访问时添加发音
// @downloadURL https://update.greasyfork.icu/scripts/426932/%E6%B7%BB%E5%8A%A0%E6%9C%89%E9%81%93%E5%8F%91%E9%9F%B3.user.js
// @updateURL https://update.greasyfork.icu/scripts/426932/%E6%B7%BB%E5%8A%A0%E6%9C%89%E9%81%93%E5%8F%91%E9%9F%B3.meta.js
// ==/UserScript==
(function () {
'use strict';
const fromMobile = navigator.userAgent.match(/Android|iPhone|iPad|iPod|Opera Mini|IEMobile/i);
let curAudio;
let curIcon;
let curText;
function readText(text, elIcon) {
if (!text || !elIcon)
return;
let url = 'https://dict.youdao.com/dictvoice?audio=' + text + '&le=eng';
let clsActive = 'sound-active';
let clsLoading = 'sound-load';
if (elIcon.classList.contains(clsLoading)) {
return;
}
if (curAudio) {
if (elIcon === curIcon && curText === text) {
curAudio.currentTime = 0;
curAudio.play();
return;
}
if (!curAudio.paused) {
curAudio.pause();
}
curIcon.classList.remove(clsActive);
curIcon.classList.remove(clsLoading);
}
let audio = new Audio(url);
elIcon.classList.add(clsLoading);
audio.addEventListener('canplay', () => {
elIcon.classList.remove(clsLoading);
elIcon.classList.add(clsActive);
});
audio.addEventListener('ended', () => {
elIcon.classList.remove(clsActive);
});
audio.addEventListener('canplaythrough', () => {
audio.play();
curAudio = audio;
curIcon = elIcon;
curText = text;
});
}
function queryAll(selector, parent, cb) {
if (parent && parent.querySelectorAll) {
parent.querySelectorAll(selector).forEach((el) => cb(el));
}
}
function observer(targetNode, cb) {
if (!targetNode)
return;
function callback(mutationsList, observer) {
for (const mutation of mutationsList) {
if (mutation.type === 'childList') {
if (mutation.addedNodes.length) {
mutation.addedNodes.forEach((el) => cb(el));
}
}
}
}
const config = {attributes: false, childList: true, subtree: true};
const observer = new MutationObserver(callback);
observer.observe(targetNode, config);
}
function processPc() {
let style = ``;
document.body.insertAdjacentHTML('beforeend', style);
function processIcon(elIcon, text) {
if (!elIcon)
return;
let elParent = elIcon.parentNode;
let elNext = elParent.nextElementSibling;
if (elNext && elNext.classList.contains('yd-voice') || elParent.querySelector('.yd-voice')) {
return;
}
text = text || elParent.dataset.soundText;
if (!text) {
text = elParent.parentElement.innerText;
}
if (!text) {
return;
}
let elA = document.createElement('span');
elA.className = 'icon-sound yd-voice';
elA.addEventListener('mouseover', () => {
readText(getText(text), elA);
});
elA.addEventListener('click', () => {
readText(getText(text), elA);
});
if (elNext) {
elParent.parentNode.insertBefore(elA, elNext);
} else {
elParent.parentNode.append(elA);
}
}
function getText(text) {
if (typeof text === 'function') {
return text();
}
return text;
}
queryAll('.icon-sound', document, el => {
processIcon(el)
});
observer(document.querySelector('#left-result-container'), el => {
queryAll('.icon-sound', el, el => {
processIcon(el)
});
});
setTimeout(function () {
let elWrap = document.querySelector('.trans-input-wrap');
let elInput = document.querySelector('#baidu_translate_input');
if (elWrap.querySelector('.icon-sound') && elInput) {
processIcon(elWrap.querySelector('.icon-sound'), () => {
return elInput.value;
});
}
}, 1000)
}
function processMobile() {
let style = ``;
document.body.insertAdjacentHTML('beforeend', style);
function processIcon(elIcon) {
if (!elIcon)
return;
let elParent = elIcon.parentNode;
if (!elParent)
return;
let text = elParent.innerText;
if (!text) {
return;
}
let elA = genElA(() => {
return text;
});
if (elIcon.nextElementSibling) {
let el = elIcon.nextElementSibling;
elParent.insertBefore(elA, el);
el.style.display = 'none';
} else {
elParent.parentNode.append(elA);
}
}
function genElA(cbText) {
let elA = document.createElement('a');
elA.appendChild(document.createElement('span'));
elA.className = 'yd-voice';
elA.addEventListener('click', () => {
readText(cbText(), elA);
});
return elA;
}
setTimeout(function () {
let elIcon = document.querySelector('#single-sound');
if (!elIcon || !elIcon.parentNode || !elIcon.nextElementSibling) {
return;
}
let elA = genElA(() => {
return document.querySelector('#j-textarea').value;
});
elIcon.parentNode.insertBefore(elA, elIcon.nextElementSibling);
}, 1000);
observer(document.querySelector('#j-extendOutput'), el => {
queryAll('.sound-btn', el, el => {
processIcon(el);
});
});
}
if (fromMobile) {
processMobile();
} else {
processPc();
}
})();