<|start_filename|>app/assets/javascripts/application/stats.js.coffee<|end_filename|>
$('.translation_report .datepicker').datepicker()


<|start_filename|>app/assets/javascripts/application/navbar.js.coffee<|end_filename|>
$('.navbar-toggler').click ->
  $this = $(this)
  target = $this.data('target')
  $target = $('#' + target)

  if $target.hasClass('navbar-collapse')
    $target.removeClass('navbar-collapse')
  else
    $target.addClass('navbar-collapse')

$('.dropdown-toggle').click (e) ->
  e.preventDefault()
  $this = $(this)

  $next = $this.next('.dropdown-menu')

  $('.dropdown-menu').not($next).removeClass('open')

  $next.toggleClass('open')


<|start_filename|>app/assets/javascripts/application/multi_field.js.coffee<|end_filename|>
# Copyright 2014 Square Inc.
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.

root = exports ? this

# A dynamic field that builds a list of field items (with plus and minus
# buttons) that will be serialized as an array in Rails. This allows the field
# to integrate directly with an array model value in forms.
#
# See multifield.rb to learn how to easily use this class in your forms.
#
class root.ArrayField

  # Creates a new ArrayField to render within a given element.
  #
  # @param [jQuery element] element A container element to render the field in.
  # @param [Array] value The initial value of the field.
  # @param [Object] options Additional options.
  # @option options [function] renderer A function that renders an individual
  #   array field item. By default it renders a simple text field. This function
  #   takes three parameters: the container to render the field item into, the
  #   `name` attribute of the field, and the field's value. It should render a
  #   field into the container whose `name` and `value` attributes are set
  #   accordingly.
  # @option options [Object] defaultValue (null) The value to set a new field
  #   item to, when it is added via the plus button.
  #
  constructor: (@element, @value, @options={}) ->
    @options['renderer'] ?= (container, name, value) => this.renderTextField(container, name, value)

    this.redraw()

    MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
    observer = new MutationObserver (changes) =>
      for change in changes
        do (change) =>
          if change.attributeName == 'data-name'
            @element.find('[name]').attr('name', "#{this.name()}[]")
    observer.observe @element[0], {attributes: true}

  # Removes all content under the container element and re-renders the field.
  #
  redraw: ->
    @element.empty()
    this.drawButton()
    for string in @value
      do (string) => this.addElement string

    if @value.length == 0
      this.addElement()


  # Appends a field item to the array field.
  #
  # @param [Object] value The initial value of the field item.
  #
  addElement: (value) ->
    div = $('<div/>').addClass('arrayfield-element').insertBefore(@new_element_button)

    @options.renderer div, "#{this.name()}[]", value

    $.each @element.find(".arrayfield-element"), (index, element) =>
      text_field = $(element).find("input[type='text']").unbind("keypress")
      if $(element).is(":last-of-type")
        text_field.keypress (e) =>
          if e.which == 13 || e.which == 9
            this.addElement @options.defaultValue
            $(element).next().find("input[type='text']").focus()
            return false
      else
        text_field.keypress (e) =>
          if e.which == 13 || e.which == 9
            $(element).next().find("input[type='text']").focus()
            return false
    remove = $('<a/>').addClass('fa fa-minus-circle').attr('href', '#').appendTo(div)
    remove.click =>
      div.remove()
      false

  # @private
  renderTextField: (container, name, value) ->
    text_field = $('<input/>').attr('type', 'text').attr('name', name).val(value)
    text_field.appendTo container
    return text_field

  drawButton: ->
    button_div = $('<div/>').addClass('multifield-last-element').appendTo(@element)
    @new_element_button = $("<button/>")
    @new_element_button.click (e) =>
      this.addElement()
      @element.find(".arrayfield-element").last().find("input[type='text']").focus()
      return false

    @new_element_button.appendTo(button_div)

  # @private
  name: -> @element.attr 'data-name'

# A dynamic field that builds a list of field item pairs (with plus and minus
# buttons) that will be serialized as a hash in Rails. This allows the field
# to integrate directly with an hash model value in forms.
#
# See multifield.rb to learn how to easily use this class in your forms.
#
class root.HashField

  # Creates a new HashField to render within a given element.
  #
  # @param [jQuery element] element A container element to render the field in.
  # @param [Hash] value The initial value of the field.
  # @param [Object] options Additional options.
  # @option options [function] renderer A function that renders an individual
  #   hash field item. By default it renders a simple text field pair. This
  #   function takes three parameters: the container to render the field item
  #   into, the `name` attribute of the field, and the field's value. The
  #   function should render both the key and value fields. The key field should
  #   have its `rel` attribute set to "key", and the value field should have its
  #   `rel` attribute set to "value". The fields should have their `value`
  #   attribute set to the key and value parameters respectively.
  # @option options [Object] defaultKey (null) The value to set the key field of
  #   a new field item to, when it is added via the plus button.
  # @option options [Object] defaultValue (null) The value to set the value
  #   field of a new field item to, when it is added via the plus button.
  #
  constructor: (@element, @value, @options={}) ->
    @options['renderer'] ?= (container, key, value) => this.renderTextFields(container, key, value)

    this.redraw()

    MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
    observer = new MutationObserver (changes) =>
      for change in changes
        do (change) =>
          if change.attributeName == 'name'
            @element.find('[name]').each (_, field) =>
              $(field).attr 'name', "#{this.name()}[#{this.keyFromName($(field).attr('name'))}]"
    observer.observe @element[0], {attributes: true}

  # Removes all content under the container element and re-renders the field.
  #
  redraw: ->
    @element.empty()
    this.drawButtons()
    for own name, value of @value
      do (name, value) => this.addElement name, value

    if Object.keys(@value).length == 0
      this.addElement @options.defaultKey, @options.defaultValue


  # Appends a field item to the hash field.
  #
  # @param [Object] key The initial value of the key field.
  # @param [Object] value The initial value of the value field.
  #
  addElement: (key, value) ->
    div = $('<div/>').addClass('hashfield-element').insertBefore(@element.find('>.multifield-last-element'))

    @options.renderer div, key, value, this
    key_field = div.find('.tt-input[rel=key]')
    value_field = div.find('[rel=value]')
    refreshName = (locale) =>
      new_key = key_field.val() || locale
      if new_key?.length > 0
        value_field.attr 'name', "#{this.name()}[#{new_key}]"
        value_field.attr 'data-name', "#{this.name()}[#{new_key}]"
      else
        value_field.removeAttr 'name'
        value_field.removeAttr 'data-name'
    key_field.keyup refreshName
    key_field.change refreshName
    key_field.on 'typeahead:change', (evt, locale) =>
      refreshName(locale)

    refreshName()

    remove = $('<a/>').addClass('fa fa-minus-circle').attr('href', '#').appendTo(div)
    remove.click =>
      div.remove()
      false

  # @private
  renderTextFields: (container, key, value) ->
    $('<input/>').attr('rel', 'key').val(key).appendTo container
    container.append ' '
    $('<input/>').attr('rel', 'value').val(value).appendTo container

  # @private
  drawButtons: ->
    button_div = $('<div/>').addClass('multifield-last-element').appendTo(@element)
    key_field = $('<div/>').addClass('hashfield-key').appendTo(button_div)
    value_field = $('<div/>').addClass('hashfield-multi-value').appendTo(button_div)

    @new_element_button = $("<button/>")
    @new_element_button.click (e) =>
      this.addElement @options.defaultKey, @options.defaultValue
      @element.find(".hashfield-element").last()
        .find(".hashfield-key")
        .find("input, select").last()
        .focus()
      return false

    @new_element_button.appendTo(key_field)
    @new_element_button.clone(true).appendTo(value_field)

  # @private
  name: -> @element.attr 'name'

  # @private
  keyFromName: (name) -> name.match(/\[\w+\]/g)[1..-2]

(($) ->

  # Allows you to convert a jQuery container object into an {ArrayField}.
  #
  # @param [Object] options Additional options to give to ArrayField.
  #
  $.fn.arrayField = (options={}) ->
    $(this).each (_, element) ->
      jqe = $(element)
      value = if jqe.attr('data-value') then JSON.parse(jqe.attr('data-value')) else ''
      new ArrayField(jqe, value, options)

  # Allows you to convert a jQuery container object into a {HashField}.
  #
  # @param [Object] options Additional options to give to HashField.
  #
  $.fn.hashField = (options={}) ->
    $(this).each (_, element) ->
      jqe = $(element)
      value = if jqe.attr('data-value') then JSON.parse(jqe.attr('data-value')) else ''
      new HashField(jqe, value, options)
)(jQuery)

# Converts `DIV`s with the class "array-field" into {ArrayField}s, and `DIV`s
# with the class "hash-field" into {HashField}s.

$(document).ready ->
  $('.array-field').arrayField()
  $('.hash-field').hashField()


<|start_filename|>app/assets/javascripts/application/fuzzy_matches_loader.js.coffee<|end_filename|>
# Copyright 2014 Square Inc.
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.

root = exports ? this

root.loadFuzzyMatches = ($fuzzy_matches, $copy_field, fuzzy_match_url, source_copy) ->
    $fuzzy_matches.empty()
    $fuzzy_matches.append($('<dd/>').text('Loading fuzzy matches'))

    $.ajax fuzzy_match_url,
        data:
            source_copy: source_copy
        success: (matches) =>
            $fuzzy_matches.empty()
            if matches.length == 0
                $fuzzy_matches.append($('<dd/>').text('No fuzzy matches found :('))
            else
                for match in matches
                    do (match) =>
                        match_percentage = $('<span/>').addClass("match-percentage").text("(#{match.match_percentage.toString()[0..4]}%) ")
                        match_element = $('<a/>').append($('<span/>').text("(#{match.rfc5646_locale}) "))
                                                 .append($('<span/>').text("(#{match.project_name}) "))
                                                 .append(match_percentage)
                                                 .append($('<span/>').addClass('fuzzy-matched-copy').text(match.copy))
                                                 .append($('<span/>').addClass('changed').text(source_copy).hide())
                                                 .append($('<span/>').addClass('original').text(match.source_copy).hide())

                        match_wrapper = $('<dd/>').append(match_element)
                                                  .append($('<div/>').addClass('diff'))

                        match_element.click =>
                            $copy_field.val match.copy

                        match_element.mouseenter ->
                            match_element.prettyTextDiff
                                diffContainer: match_wrapper.find('.diff')
                            match_wrapper.find('.diff').prepend($('<span/>').addClass("match-percentage").text("Source Diff: "))
                        match_element.mouseleave ->
                            match_wrapper.find('.diff').empty()

                        $fuzzy_matches.append(match_wrapper)



<|start_filename|>app/assets/javascripts/application/locale_field.js.coffee<|end_filename|>
# Copyright 2014 Square Inc.
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.

root = exports ? this

# @private
getObjectClass = (obj) ->
  if obj && obj.constructor && obj.constructor.toString
    arr = obj.constructor.toString().match(/function\s*(\w+)/)
    if arr && arr.length == 2
      return arr[1]
  return undefined

# @private
class XHash
  constructor: (@hash) ->
    @hash = @hash.hash if getObjectClass(@hash) == 'XHash'

  select: (func) ->
    result = {}
    (result[a] = b for own a, b of @hash when func(a, b))
    new XHash(result)

  reject: (func) ->
    result = {}
    (result[a] = b for own a, b of @hash when !func(a, b))
    new XHash(result)

  map: (func) ->
    result = {}
    (result[a] = func(a, b) for own a, b of @hash)
    new XHash(result)

  keys: -> new XArray(key for own key, value of @hash)

  delete: (obj) ->
    while (index = @hash.indexOf(obj)) >= 0
      @hash.splice index, 1
    this

# @private
class XArray
  constructor: (@array=null) ->
    @array ?= []
    @array = @array.array if getObjectClass(@array) == 'XArray'

  flatten: ->
    result = new XArray()
    for item in @array
      if getObjectClass(item) == 'XArray'
        result.array.push item.array...
      else if getObjectClass(item) == 'Array'
        result.array.push item...
      else
        result.array.push item
    result

  compact: -> new XArray(item for item in @array when item)
  select: (func) -> new XArray(item for item in @array when func(item))
  join: -> @array.join(arguments...)
  slice: -> new XArray(@array.slice(arguments...))
  map: (func) -> new XArray(func(item) for item in @array)
  delete: (filter) -> @array = (item for item in @array when item != filter); this

  any: (func) ->
    for item in @array
      return true if func(item)
    return false

String::startsWith = (other) -> this.indexOf(other) == 0

################################################################################

# @private Mostly a port of the Locale class in the Ruby code -- see that code
#   for comments.
class root.Locale
  constructor: (@iso639, @script, @extended_language=null, @region=null, @variants=null, @extensions=null) ->
    @iso639 = @iso639.toLowerCase()
    @region = @region.toUpperCase() if @region
    @extended_language = @extended_language.toLowerCase() if @extended_language

    @variants ?= []
    @variants = @variants.map (v) -> v.toLowerCase()
    @extensions ?= []

  rfc5646: -> new XArray([@iso639, @script, @extended_language, @region, @variants...]).compact().join('-')

  name: ->
    i18n_language = if @extended_language
      Locale.locales.extended[@iso639][@extended_language]
    else
      Locale.locales.name[@iso639]

    i18n_dialect = null
    if @variants.length > 0
      i18n_dialect = Locale.locales.variant[@iso639]
      i18n_dialect = i18n_dialect[variant] for variant in @variants
      i18n_dialect = i18n_dialect['_END_']

    i18n_script = if @script then Locale.locales.script[@script] else null
    i18n_region = if @region then Locale.locales.region[@region] else null

    if i18n_region && i18n_dialect && i18n_script
      Locale.locales.format.scripted_regional_dialectical.
        replace('%{script}', i18n_script).
        replace('%{dialect}', i18n_dialect).
        replace('%{region}', i18n_region).
        replace('%{language}', i18n_language)
    else if i18n_region && i18n_dialect
      Locale.locales.format.regional_dialectical.
        replace('%{dialect}', i18n_dialect).
        replace('%{region}', i18n_region).
        replace('%{language}', i18n_language)
    else if i18n_region && i18n_script
      Locale.locales.format.scripted_regional.
        replace('%{script}', i18n_script).
        replace('%{region}', i18n_region).
        replace('%{language}', i18n_language)
    else if i18n_dialect && i18n_script
      Locale.locales.format.scripted_dialectical.
        replace('%{script}', i18n_script).
        replace('%{dialect}', i18n_dialect).
        replace('%{language}', i18n_language)
    else if i18n_script
      Locale.locales.format.scripted.
        replace('%{script}', i18n_script).
       replace('%{language}', i18n_language)
    else if i18n_dialect
      Locale.locales.format.dialectical.
        replace('%{dialect}', i18n_dialect).
       replace('%{language}', i18n_language)
    else if i18n_region
      Locale.locales.format.regional.
        replace('%{region}', i18n_region).
        replace('%{language}', i18n_language)
    else
      i18n_language

  image: ->
    Locale.locale_countries[@region] || Locale.locale_countries[@iso639]

Locale.RFC5646_EXTLANG   = "(?<extlang>[a-zA-Z]{3})(-[a-zA-Z]{3}){0,2}"
Locale.RFC5646_ISO639    = "(?<iso639>[a-zA-Z]{2,3})(-#{Locale.RFC5646_EXTLANG})?"
Locale.RFC5646_RESERVED  = "(?<reserved>[a-zA-Z]{4})"
Locale.RFC5646_SUBTAG    = "(?<subtag>[a-zA-Z]{5,8})"
Locale.RFC5646_REGION    = "(?<region>([a-zA-Z]{2}|\\d{3}))"
Locale.RFC5646_VARIANT   = "([a-zA-Z0-9]{5,8}|\\d[a-zA-Z0-9]{3})"
Locale.RFC5646_SCRIPT    = "(?<script>[a-zA-Z]{4})"
Locale.RFC5646_EXTENSION = "([0-9A-WY-Za-wy-z](-[a-zA-Z0-9]{2,8}){1,})"
Locale.RFC5646_LOCALE  = "(#{Locale.RFC5646_ISO639}|#{Locale.RFC5646_RESERVED}|#{Locale.RFC5646_SUBTAG})"
Locale.RFC5646_PRIVATE   = "x(?<privates>(-[a-zA-Z0-9]{1,8}){1,})"
Locale.RFC5646_FORMAT    = XRegExp("^#{Locale.RFC5646_LOCALE}(-#{Locale.RFC5646_SCRIPT})?(-#{Locale.RFC5646_REGION})?(?<variants>(-#{Locale.RFC5646_VARIANT})*)(?<extensions>(-#{Locale.RFC5646_EXTENSION})*)(-#{Locale.RFC5646_PRIVATE})?$")

Locale.from_rfc5646 = (ident) ->
  return null unless (match = XRegExp.exec(ident, Locale.RFC5646_FORMAT))
  return null unless match.iso639
  if (variants = match.variants)
    variants = variants.split('-')
    variants.shift()
  if (extensions = match.extensions)
    extensions = extensions.split('-')
    extensions.shift()
  new Locale(match.iso639, match.script, match.extlang, match.region, variants || [], extensions || [])

Locale.from_rfc5646_prefix = (prefix, max=null) ->
  if prefix.indexOf('-') >= 0
    prefix_path = prefix.split('-')
    prefix = prefix_path.pop()
    parent_prefix = prefix_path.join('-')
    parent = this.from_rfc5646(parent_prefix)
    return [] unless parent

    search_paths = if parent.variants.length > 0
      #TODO subvariants
      new XArray()
    else if parent.region
      #TODO variants
      new XArray()
    else if parent.script
      new XArray(['region'])
    else
      new XArray(['region', 'script'])

    keys = search_paths.map((path) -> new XHash(Locale.locales[path]).select((k, v) -> Locale.matches_prefix(prefix, k, v)).keys()).flatten()
    keys.delete '_END_'
    keys = keys[0...max] if max
    return (Locale.from_rfc5646("#{parent_prefix}-#{key}") for key in keys.array)
  else
    keys = new XHash(Locale.locales.name).select((k, v) -> Locale.matches_prefix(prefix, k, v)).keys()
    keys = keys[0...max] if max
    return (Locale.from_rfc5646(key) for key in keys.array)

Locale.matches_prefix = (prefix, key, value) ->
  return false unless getObjectClass(value) == 'String'
  return true if key.toLowerCase().startsWith(prefix.toLowerCase())
  return true if new XArray(value.split(/\w+/)).any (word) -> word.toLowerCase().startsWith(prefix.toLowerCase())
  return false

Locale.locales = {}
Locale.locale_countries = {}

Locale.dataset = () ->
  dataset = []
  for rfc, name of Locale.locales.name
    datum =
      rfc: rfc
      name: name
      value: rfc
      flag: Locale.locale_countries[rfc]
      tokens: [rfc, name]
    dataset.push datum
  return dataset


################################################################################

# A field where a user can input one or multiple locales as RFC 5646 codes.
# The field pops up a dialog offering autocomplete suggestions and the
# translation of locale codes into English names.
#
class root.LocaleField

  # Creates a new locale field. Must be applied to an `INPUT` element with the
  # class `locale-field` (and optionally `locale-field-list` to operate as a
  # comma-delimited list.
  #
  # Attaches event listeners to the field for keyboard operation of the menu.
  #
  # @param [jQuery element] element The element to apply locale field
  #   semantics to.
  #
  constructor: (@element, @options = {}) ->
    template = "
    <div class=\"locale-field-suggestion\">
      <img src=\"{{flag}}\">
      <div class='locale-rfc'>
        <strong>{{rfc}}</strong>
      </div>
      <div class='locale-name'>
        {{name}}
      </span>
    </div>
    "
    compiled = Hogan.compile(template)
    source = new Bloodhound
      datumTokenizer: (d) -> [d.rfc, d.name]
      queryTokenizer: Bloodhound.tokenizers.whitespace
      local: Locale.dataset()

    source.initialize().done =>

      @element.wrap("<span class='locale-field-wrapper'></span>")
      @element.typeahead null, {
        name: 'locales',
        source: source.ttAdapter()
        display: 'rfc'
        templates:
          suggestion: compiled.render.bind(compiled)
      }

      @element.blur () ->
        if $(this).val() == ''
          $(this).attr("placeholder", "Locale")
        else if Locale.from_rfc5646($(this).val()) == null
          $(this).val('')
          $(this).attr("placeholder", "Invalid Locale")

      this.setFlag()
      @element.on 'keyup', (e) =>
        this.setFlag()
      @element.on "typeahead:closed", (e) =>
        this.setFlag()


  setFlag: ->
    @element.parent().find('img.locale-flag').remove()
    image = Locale.from_rfc5646(@element.val())?.image()
    if image
      img = $('<img/>').attr('src', image).addClass('locale-flag').insertAfter(@element)
      img.css('top', (img.parent().height() - 24) / 2)

$.when($.ajax("/locales.json"), $.ajax("/locales/countries.json")).done (locales_result, countries_result) ->
  Locale.locales = locales_result[0]
  Locale.locale_countries = countries_result[0]

  $('input.locale-field').each (_, field) -> new LocaleField($(field))
  $(document).trigger 'locales_loaded'
  window.localesLoaded = true


<|start_filename|>app/assets/javascripts/application/glossary_list.js.coffee<|end_filename|>
# Copyright 2016 Square Inc.
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.

root = exports ? this

# Manager class for the glossary list view.
#
class root.GlossaryList

  # Creates a new glossary list manager.
  #
  # @param [jQuery element] glossaryTable The table jQuery element that will
  #   soon contain the glossary table.
  # @param [String] glossaryUrl The URL from which we can pull all glossary
  #   entries.
  # @param [String] addSourceEntryUrl The URL to POST to that adds a new source
  #   entry to the glossary.
  # @param [String] localesUrl The URL to GET that retrieves a list of all
  #   locales along with their flags.
  # @param [Array] sourceLocale The locale of all source entries.
  # @param [Array] targetLocale The locales that we want to view translated
  #   entries in.
  # @param [jQuery element] settingsModal The jQuery element that contains an
  #   uninitialized settings modal.
  # @param [jQuery element] addEntryModal The jQuery element that contains an
  #   uninitialized add-entry modal.
  # @param [String] userRole The role of the user (monitor/translator/etc.)
  # @param [Array] approvedLocales An array of the locales the user is approved
  #   to translate in.
  #
  constructor: (
      @glossaryTable,
      @addSourceEntryUrl,
      @sourceLocale,
      @targetLocales,
      @settingsModal,
      @addEntryModal,
      @approvedLocales) ->
    if $.cookie('glossaryList_sourceLocale')?
      @sourceLocale = Locale.from_rfc5646($.cookie('glossaryList_sourceLocale'))
    else
      @sourceLocale = Locale.from_rfc5646(@sourceLocale)
    if $.cookie('glossaryList_targetLocales')?
      @targetLocales = JSON.parse($.cookie('glossaryList_targetLocales'))
    else
      @targetLocales = @approvedLocales

    setup = =>
      this.setupAddTermModal()
      this.setupSettingsFormModal()
      this.setupGlossaryRows()

    setup() if window.localesLoaded
    $(document).bind 'locales_loaded', setup

  # Flashes an error at the top of the screen.
  #
  # @param [String] message The message that will be flashed.
  #
  error: (message) ->
    new Flash('alert').text(message)

  # @private
  setupAddTermModal: =>
    @addEntryModal.find("input[name='source_glossary_entry[due_date]']").datepicker
      startDate: new Date()
      autoclose: true
      todayBtn: 'linked'

    @addEntryModal.find('form').submit () =>
      $.ajax @addSourceEntryUrl,
        type: 'POST'
        data: @addEntryModal.find('form').serialize()
        success: => this.loadGlossaryEntries()
        error: =>
          this.error("Couldn’t add new term.")
          this.loadGlossaryEntries()
      @addEntryModal.closeModal()
      window.location = 'glossary'
      return false

  # @private
  setupSettingsFormModal: =>
    @settingsModal.find("#glossary_target_locales").arrayField(
      renderer: (container, name, value) ->
        text_field = $('<input/>').attr('type', 'text')
                                  .attr('name', name)
                                  .attr('placeholder', "Locale")
                                  .addClass('locale-field')
                                  .val(value)
        text_field.appendTo container
        new LocaleField(text_field)
        return text_field
    )

    @settingsModal.find("button.save-target-locales").click =>
      @targetLocales = $.map(
        @settingsModal.find(".locale-field"),
        (field) ->
          return $(field).val()
      ).filter(
        (locale) ->
          locale != ""
      )
      window.location = 'glossary?target_locales=' + @targetLocales
      return false

  setupGlossaryRows: =>
    @animation_time = 200
    @glossaryTable.on 'click', 'tr.glossary-row-header', () ->
      $detailSection = $(@).siblings('tr.glossary-row-detail')
      $detailSectionContent = $detailSection.find('td > div')
      wasActive = $(@).hasClass('active')

      if wasActive
        $(@).removeClass('active')
        $detailSectionContent.slideUp(@animation_time, () -> $detailSection.hide())
      else
        $(@).addClass('active')
        $detailSection.show()
        $detailSectionContent.slideDown(@animation_time)

    @glossaryTable.find('.locale-section').each (i, domLocaleEntry) =>
      approveLocaleEntryUrl = $(domLocaleEntry).data('approve-url')
      rejectLocaleEntryUrl = $(domLocaleEntry).data('reject-url')

      $approveLocaleButton = $(domLocaleEntry).find('.glossary-approve-locale')
      $rejectLocaleButton = $(domLocaleEntry).find('.glossary-reject-locale')

      $approveLocaleButton.on 'click', =>
        $approveLocaleButton.prop('disabled', true)

        # Send the approve glossary entry URL request and undisable the buttons on success
        $.ajax approveLocaleEntryUrl,
          type: "PATCH"
          success: ->
            $rejectLocaleButton.prop('disabled', false)
            $(domLocaleEntry).parents('.glossary-row').find('glossary-row-header-source-entry')
              .hide().removeClass('text-info text-error').addClass('text-success').fadeIn(500)
          error: ->
            # TODO: We should add in some messaging here that it failed.
            $approveLocaleButton.prop('disabled', false)

      $rejectLocaleButton.on 'click', =>
        $rejectLocaleButton.prop('disabled', true)

        # Send the reject glossary entry URL request and undisable the buttons on success
        $.ajax rejectLocaleEntryUrl,
          type: "PATCH"
          success: ->
            $approveLocaleButton.prop('disabled', false)
            $(domLocaleEntry).parents('.glossary-row').find('glossary-row-header-source-entry')
              .hide().removeClass('text-info text-success').addClass('text-error').fadeIn(500)
          error: ->
            # TODO: We should add in some messaging here that it failed.
            $rejectLocaleButton.prop('disabled', false)