简体   繁体   中英

How to organize coffescript in better way

I have the following coffescript code:

  hideOther = -> 
   $('[class^=addition_translation]').hide()

  $('.en_addition').click ->
    hideOther()  
    $('.addition_translation_en').show()

  $('.pl_addition').click ->
    hideOther()  
    $('.addition_translation_pl').show()

  $('.de_addition').click ->
    hideOther()  
    $('.addition_translation_de').show()

  $('.fr_addition').click ->
    hideOther()  
    $('.addition_translation_fr').show()

  $('.it_addition').click ->
    hideOther()  
    $('.addition_translation_it').show()

  $('.ua_addition').click ->
    hideOther()  
    $('.addition_translation_ua').show() 

  $('.ru_addition').click ->
    hideOther()  
    $('.addition_translation_ru').show()   

Which way will be the best to write this code without this unnecessary repetitions?

Edit:

  countries = ["pl", "en"]
     for country in countries
       $(".#{country}_addition").click ->
        hideOther()  
        $(".addition_translation_#{country}").show()

I do it in this way, maybe is better way to do it?

With corrected indentation (since indentation matters in CoffeeScript), that should be just fine:

countries = ["pl", "en"]
for country in countries
  $(".#{country}_addition").click ->
    hideOther()  
    $(".addition_translation_#{country}").show()

It does set a separate function on each of the .XX_addition elements, but unless there are thousands of them or they are dynamically added, that should be fine.

Your other option is event delegation, having one function that handles all of these elements. This is (again) particularly handy when the list is dynamic.

Assuming all of these .addition_translation_XX elements are in some container (I'll call it .container ):

$(".container").on "click", "[class$=_addition]", ->
  country = this.className.substring 0, 2
  $("[class^=addition_translation]").hide()
  $(".addition_translation_#{country}").show()

There we're saying: Hook the click on the container, but only call our handler if it passes through an element matching "[class$=_addition]" (an element whose class attribute ends with _addition ). jQuery will call our handler with this referring to that element, so we get the country from the className , hide the other countries, and show that one.

Note that like your "[class^=addition_translation]" selector assumes that the XX_addition_translation class is the only (or at least last) class in those elements' class lists, the above assumes that XX_addition is the only (or at least first) class in those elements' class lists. In both cases, I wouldn't make that assumption, it's fragile; instead, I'd use a class to mark the elements without the country information (so just .addition and .addition_translation and then add a data-country attribute to them:

<span class="addition" data-country="ru">...</span>
<div class="addition_translation" data-country="ru">...</div>

Then:

$(".container").on "click", ".addition", ->
  country = this.getAttribute "data-country"
  $(".addition_translation").hide()
  $(".addition_translation[data-country=#{country}]").show()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM