使用 Microsoft Translator 时,有没有办法删除小部件,但保留翻译?
When using the Microsoft Translator, Is there a way to remove the widget, but retain translation?
我正在使用 Microsoft Translation Widget,我想用它来自动翻译网页而无需用户交互。
问题是,我无法摆脱在 document.ready 上不断弹出或隐藏它的小部件,因为 CSS 和 JS 是从小部件中的 Microsoft 自己的脚本加载的!
有人知道解决这个问题的方法吗?我到处都找遍了,找不到解决办法。
哇,经过一段时间的尝试,我终于实现了你想要的。
它有点难看,因为需要一些解决方法,但它确实有效,take a look at the fiddle。
步骤是:
首先,我们必须覆盖默认的 addEventListener
行为:
var addEvent = EventTarget.prototype.addEventListener;
var events = [];
EventTarget.prototype.addEventListener = function(type, listener) {
addEvent.apply(this, [].slice.call(arguments));
events.push({
element: this,
type: type,
listener: listener
});
}
然后,我们创建一个辅助函数removeEvents
。它删除元素的所有事件侦听器。
var removeEvents = function(el, type) {
var elEvents = events.filter(function(ev) {
return ev.element === el && (type ? ev.type === type : true);
});
for (var i = 0; i < elEvents.length; i++) {
el.removeEventListener(elEvents[i].type, elEvents[i].listener);
}
}
在创建 script
标签时,微软表示:
var s = d.createElement('script');
s.type = 'text/javascript';
s.charset = 'UTF-8';
s.src = ((location && location.href && location.href.indexOf('https') == 0) ? 'https://ssl.microsofttranslator.com' : 'http://www.microsofttranslator.com') + '/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&ctf=True&ui=true&settings=Manual&from=';
var p = d.getElementsByTagName('head')[0] || d.dElement;
p.insertBefore(s, p.firstChild);
我们必须向 script
添加一个 load
事件侦听器,下面的代码已完整注释:
s.addEventListener('load', function() {
// when someone changes the translation, the plugin calls the method TranslateArray
// then, we save the original method in a variable, and we override it
var translate = Microsoft.Translator.TranslateArray;
Microsoft.Translator.TranslateArray = function() {
// we call the original method
translate.apply(this, [].slice.call(arguments));
// since the translation is not immediately available
// and we don't have control when it will be
// I've created a helper function to wait for it
waitForTranslation(function() {
// as soon as it is available
// we get all the elements with an attribute lang
[].forEach.call(d.querySelectorAll('[lang]'), function(item, i) {
// and we remove all the mouseover event listeners of them
removeEvents(item, 'mouseover');
});
});
}
// this is the helper function which waits for the translation
function waitForTranslation(cb) {
// since we don't have control over the translation callback
// the workaround was to see if the Translating label is visible
// we keep calling the function, until it's hidden again
// and then we call our callback
var visible = d.getElementById('FloaterProgressBar').style.visibility;
if (visible === 'visible') {
setTimeout(function() {
waitForTranslation(cb);
}, 0);
return;
}
cb();
}
});
更新 1
重新阅读您的问题后,您似乎想要隐藏所有小部件。
因此,您必须在翻译完成后立即添加以下代码:
waitForTranslation(function() {
document.getElementById('MicrosoftTranslatorWidget').style.display = 'none';
document.getElementById('WidgetLauncher').style.display = 'none';
document.getElementById('LauncherTranslatePhrase').style.display = 'none';
document.getElementById('TranslateSpan').style.display = 'none';
document.getElementById('LauncherLogo').style.display = 'none';
document.getElementById('WidgetFloaterPanels').style.display = 'none';
// rest of the code
});
我创建了 another fiddle for you,展示了新的行为。
更新 2
您可以通过添加以下 CSS 代码完全阻止小部件显示:
#MicrosoftTranslatorWidget, #WidgetLauncher, #LauncherTranslatePhrase, #TranslateSpan, #LauncherLogo, #WidgetFloaterPanels {
opacity: 0!important;
}
您甚至可以通过默认隐藏 document.body
,然后在页面完全翻译后显示它来阻止显示之前翻译的文本:
(function(w, d) {
document.body.style.display = 'none';
/* (...) */
s.addEventListener('load', function() {
var translate = Microsoft.Translator.TranslateArray;
Microsoft.Translator.TranslateArray = function() {
translate.apply(this, [].slice.call(arguments));
waitForTranslation(function() {
/* (...) */
document.body.style.display = 'block';
});
}
});
});
对我来说,这是解决方案:
在你的
我正在使用 Microsoft Translation Widget,我想用它来自动翻译网页而无需用户交互。
问题是,我无法摆脱在 document.ready 上不断弹出或隐藏它的小部件,因为 CSS 和 JS 是从小部件中的 Microsoft 自己的脚本加载的!
有人知道解决这个问题的方法吗?我到处都找遍了,找不到解决办法。
哇,经过一段时间的尝试,我终于实现了你想要的。
它有点难看,因为需要一些解决方法,但它确实有效,take a look at the fiddle。
步骤是:
首先,我们必须覆盖默认的
addEventListener
行为:var addEvent = EventTarget.prototype.addEventListener; var events = []; EventTarget.prototype.addEventListener = function(type, listener) { addEvent.apply(this, [].slice.call(arguments)); events.push({ element: this, type: type, listener: listener }); }
然后,我们创建一个辅助函数
removeEvents
。它删除元素的所有事件侦听器。var removeEvents = function(el, type) { var elEvents = events.filter(function(ev) { return ev.element === el && (type ? ev.type === type : true); }); for (var i = 0; i < elEvents.length; i++) { el.removeEventListener(elEvents[i].type, elEvents[i].listener); } }
在创建
script
标签时,微软表示:var s = d.createElement('script'); s.type = 'text/javascript'; s.charset = 'UTF-8'; s.src = ((location && location.href && location.href.indexOf('https') == 0) ? 'https://ssl.microsofttranslator.com' : 'http://www.microsofttranslator.com') + '/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&ctf=True&ui=true&settings=Manual&from='; var p = d.getElementsByTagName('head')[0] || d.dElement; p.insertBefore(s, p.firstChild);
我们必须向
script
添加一个load
事件侦听器,下面的代码已完整注释:s.addEventListener('load', function() { // when someone changes the translation, the plugin calls the method TranslateArray // then, we save the original method in a variable, and we override it var translate = Microsoft.Translator.TranslateArray; Microsoft.Translator.TranslateArray = function() { // we call the original method translate.apply(this, [].slice.call(arguments)); // since the translation is not immediately available // and we don't have control when it will be // I've created a helper function to wait for it waitForTranslation(function() { // as soon as it is available // we get all the elements with an attribute lang [].forEach.call(d.querySelectorAll('[lang]'), function(item, i) { // and we remove all the mouseover event listeners of them removeEvents(item, 'mouseover'); }); }); } // this is the helper function which waits for the translation function waitForTranslation(cb) { // since we don't have control over the translation callback // the workaround was to see if the Translating label is visible // we keep calling the function, until it's hidden again // and then we call our callback var visible = d.getElementById('FloaterProgressBar').style.visibility; if (visible === 'visible') { setTimeout(function() { waitForTranslation(cb); }, 0); return; } cb(); } });
更新 1
重新阅读您的问题后,您似乎想要隐藏所有小部件。
因此,您必须在翻译完成后立即添加以下代码:
waitForTranslation(function() {
document.getElementById('MicrosoftTranslatorWidget').style.display = 'none';
document.getElementById('WidgetLauncher').style.display = 'none';
document.getElementById('LauncherTranslatePhrase').style.display = 'none';
document.getElementById('TranslateSpan').style.display = 'none';
document.getElementById('LauncherLogo').style.display = 'none';
document.getElementById('WidgetFloaterPanels').style.display = 'none';
// rest of the code
});
我创建了 another fiddle for you,展示了新的行为。
更新 2
您可以通过添加以下 CSS 代码完全阻止小部件显示:
#MicrosoftTranslatorWidget, #WidgetLauncher, #LauncherTranslatePhrase, #TranslateSpan, #LauncherLogo, #WidgetFloaterPanels {
opacity: 0!important;
}
您甚至可以通过默认隐藏 document.body
,然后在页面完全翻译后显示它来阻止显示之前翻译的文本:
(function(w, d) {
document.body.style.display = 'none';
/* (...) */
s.addEventListener('load', function() {
var translate = Microsoft.Translator.TranslateArray;
Microsoft.Translator.TranslateArray = function() {
translate.apply(this, [].slice.call(arguments));
waitForTranslation(function() {
/* (...) */
document.body.style.display = 'block';
});
}
});
});
对我来说,这是解决方案: 在你的