Source: lang/Goog.js

/* global google, nycTranslateInstance */
/**
 * @module nyc/lang/Goog
 */

import $ from 'jquery'

import Translate from 'nyc/lang/Translate'

/**
 * @desc Class for language translation using the Google Translate Gadget
 * @public
 * @class
 * @extends module:nyc/lang/Translate~Translate
 * @constructor
 * @fires module:nyc/lang/Translate~Translate#ready
 * @fires module:nyc/lang/Translate~Translate#change
 */
class Goog extends Translate {
  /**
   * @desc Create an instance of Goog
   * @public
   * @constructor
   * @param {module:nyc/lang/Translate~Translate.Options} options Constructor options
   */
  constructor(options) {
    super(options)
    /**
     * @private
     * @member {boolean}
     */
    this.monitoring = false
    $.getScript('https://translate.google.com/translate_a/element.js?cb=nycTranslateInstance.init')
  }
  /**
   * @desc Callback to set up Google Translate
   * @public
   * @method
   */
  init() {
    nycTranslateInstance.goog = new google.translate.TranslateElement({
      pageLanguage: 'en',
      includedLanguages: nycTranslateInstance.codes,
      layout: google.translate.TranslateElement.InlineLayout.SIMPLE,
      autoDisplay: false
    }, 'lng-goog')
    nycTranslateInstance.hack()
    nycTranslateInstance.trigger('ready', nycTranslateInstance)
  }
  /**
   * @desc Sets the chosen language and initiates Google Translation
   * @public
   * @override
   * @method
   * @param {jQuery.Event} event Event object
   */
  translate(event) {
    const choices = $('iframe.goog-te-menu-frame:first').contents().find('.goog-te-menu2-item span.text')
    clearTimeout(nycTranslateInstance.timeout)
    if (event && choices.length) {
      this.code = $(event.target).val()
      const lang = this.languages[this.code].name
      if (lang === 'English') {
        this.showOriginalText()
      } else {
        $(choices).each((_, choice) => {
          if ($(choice).text() === lang) {
            $(choice).trigger('click')
            nycTranslateInstance.monitor()
            return false
          }
        })
      }
      this.css('goog')
      this.trigger('change', this)
    } else {
      nycTranslateInstance.timeout = setTimeout(() => {
        nycTranslateInstance.translate(event)
      }, 200)
    }
  }
  /**
   * @desc Gets the google translate cookie value
   * @access protected
   * @override
   * @method
   * @return {string} Value from cookie
   */
  getCookieValue() {
    let cookie = this.getCookie()
    if (cookie) {
      cookie = cookie.split('/')
      cookie = cookie[2]
      return cookie
    }
    return ''
  }
  /**
   * @private
   * @method
   */
  monitor() {
    if (!this.monitoring) {
      this.monitoring = true
      if ('MutationObserver' in window) {
        new MutationObserver(this.hack)
          .observe(document.body, {childList: true, subtree: true})
      } else {
        setInterval(this.hack, 500)
      }
    }
  }
  /**
   * @private
   * @method
   * @override
   * @return {string} cookie
   */
  getCookie() {
    const cookies = document.cookie.split(';')
    for (let i = 0; i < cookies.length; i++) {
      let cookie = cookies[i]
      while (cookie.charAt(0) === ' ') {
        cookie = cookie.substring(1, cookie.length)
      }
      if (cookie.indexOf('googtrans=') === 0) {
        return cookie.substring(10, cookie.length)
      }
    }
  }
  /**
   * @private
   * @method
   */
  hack() {
    /*
     * google translate doesn't translate placeholder attributes
     * so we'll add a hidden span after input elements that have placeholders
     * then use the placeholder text for the span
     * then apply the translation of the span back to the placeholder
     */
    $('input[placeholder]').each(function(_, input) {
      const next = $(input).next()
      if (!next.hasClass('lng-placeholder')) {
        $(input).after(`<span class="lng-placeholder">${$(input).attr('placeholder')}</span>`)
      } else {
        let text = next.html()
        $.each(next.find('font'), (idx, font) => {
          text = $(font).html()
        })
        $(input).attr('placeholder', text)
      }
    })
    $('body').css('top', 'auto')
    $('#goog-gt-tt').remove()
  }
  /**
   * @private
   * @method
   */
  showOriginalText() {
    const googBar = $('iframe.goog-te-banner-frame:first')
    $(googBar.contents().find('.goog-te-button button')).each((_, button) => {
      if ($(button).text() === 'Show original') {
        const code = this.find('select').val()
        $(button).trigger('click')
        if (this.languages[code].name !== 'English') {
          this.find('select').val('en')
        }
        return false
      }
    })
  }
}

export default Goog