BigJ BigJ -4 years ago 258
CoffeeScript Question

How do I loop through multiple elements and attach a click function on each?

I am trying to loop through a number of elements in a ruby on rails app so that a div can be shown or hidden dependant on which element is selected in a dropdown (or radio buttons or whatever).

My javascript/coffescript knowledge is poor but after a couple of days hacking at it I have a working solution, although it is horribly constructed.

$(document).on "turbolinks:load", ->
if $('select[id="open_closed[1]"]').val() == "0" or $('select[id="open_closed[1]"]').val() == "1"
$('#open_close_times_1').hide()
$('select[id="open_closed[1]"]').click ->
if $('select[id="open_closed[1]"]').val() == "0"
$('#open_close_times_1').hide()
if $('select[id="open_closed[1]"]').val() == "1"
$('#open_close_times_1').hide()
if $('select[id="open_closed[1]"]').val() == "2"
$('#open_close_times_1').show()

if $('select[id="open_closed[2]"]').val() == "0" or $('select[id="open_closed[2]"]').val() == "1"
$('#open_close_times_2').hide()
$('select[id="open_closed[2]"]').click ->
if $('select[id="open_closed[2]"]').val() == "0"
$('#open_close_times_2').hide()
if $('select[id="open_closed[2]"]').val() == "1"
$('#open_close_times_2').hide()
if $('select[id="open_closed[2]"]').val() == "2"
$('#open_close_times_2').show()
.
.
.
return


This is for setting opening times for days of the week for a store so the following snippet extends up to open_closed[7]. I'm sure this should be done with a loop, rather than writing each one out. I also have a "holidays" version of this which will have an arbitrary number of days - so this solution falls down completely there, but a loop would be perfect.

I've been trying to extract this into some sort of loop to achieve the same effect (so I can do this up to 7 here and the other code up to an arbitrary max), but I can't find a tutorial or instructions which allow me to do this. This is day 4 of my hacking at this so any pointers would be gratefully received, what do I need to do to refactor this into a sensible solution?

Answer Source

In jQuery, get an array of the select items you are targeting with a less specific selector. For example you can use a starts with selector. Then loop through the results to hide the element and add an on click event.

$(document).on("turbolinks:load", function () {
  var options = $("select[id^='open_closed']");
  $.each(options, function(index, item){
    if ($(item).val() == 0 || $(item).val() == 1) {
      $(item).hide();
    }

    $(item).on("click", function() {
      var open_close_selector = "#open_close_times_" + (index + 1);
      if ($(item).val() == "0" || $(item).val() == "1"){
        $(open_close_selector).hide();
      } else {  
        if ($(item).val() == "2") {
          $(open_close_selector).show();
        }
      }
    });
  });
});

This can be cleaned up a bit, but it should give you a starting point.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download