Javascript 使用Microsoft Translator时,是否有办法删除小部件,但保留翻译?

Javascript 使用Microsoft Translator时,是否有办法删除小部件,但保留翻译?,javascript,ajax,microsoft-translator,Javascript,Ajax,Microsoft Translator,我正在使用MicrosoftTranslationWidget,我想用它来自动翻译网页,而无需用户交互 问题是,我无法摆脱不断弹出或隐藏在document.ready上的小部件,因为CSS和JS是从小部件中的Microsoft自己的脚本加载的 有人知道怎么解决这个问题吗?我到处都找了,找不到解决办法。哇,经过一段时间的努力,我终于达到了你想要的 这有点难看,因为需要一些变通办法,但它是有效的 这些步骤是: 首先,我们必须覆盖默认的addEventListener行为: var addEvent

我正在使用MicrosoftTranslationWidget,我想用它来自动翻译网页,而无需用户交互

问题是,我无法摆脱不断弹出或隐藏在document.ready上的小部件,因为CSS和JS是从小部件中的Microsoft自己的脚本加载的


有人知道怎么解决这个问题吗?我到处都找了,找不到解决办法。

哇,经过一段时间的努力,我终于达到了你想要的

这有点难看,因为需要一些变通办法,但它是有效的

这些步骤是:

  • 首先,我们必须覆盖默认的
    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
      });
    }
    
  • 然后,我们创建一个helper函数
    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);
      }
    }
    
    我们必须向该
    脚本
    添加一个
    加载
    事件侦听器,下面的代码已被完整注释:

    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
    });
    
    我创造了,展示了新的行为

    更新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';
          });
        }
      });
    });
    

    看一看。

    哇,在玩了一段时间之后,我终于实现了你想要的

    这有点难看,因为需要一些变通办法,但它是有效的

    这些步骤是:

  • 首先,我们必须覆盖默认的
    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
      });
    }
    
  • 然后,我们创建一个helper函数
    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);
      }
    }
    
    我们必须向该
    脚本
    添加一个
    加载
    事件侦听器,下面的代码已被完整注释:

    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
    });
    
    我创造了,展示了新的行为

    更新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';
          });
        }
      });
    });
    

    看看。

    对我来说,这就是解决方案: 在