0

This is the edited code: I tried with 'name' instead of 'latitude', and I still get a blank alert window. I also added <script src="//code.jquery.com/jquery-2.1.1.min.js"></script> inside the <head> in app/views/layouts/application.html.erb

    <% @clients.each do |client| %>
          <tr class = "client">
            <td class = "name"><%= client.name %></td>
            <td class = "phone"><%= client.phone %></td>
            <td class = "address"><%= client.address %></td>
            <td class = "pay"><%= client.pay %></td>
            <td class = "latitude"><%= client.latitude %></td>
            <td class = "longitude"><%= client.longitude %></td>
            <td><form><input class = "route" type="checkbox" name = "chkboxRoute"></form></td>
          </tr>
        <% end %>

<script>
$(function() {
  $(".client input.route").bind("change", function(element) {
    var clatitude = [];
    var clongitude = [];

    $(".client input.route:checked").each(function(element) {
      element = $(element);

      var clientLatitude = $(element).closest('.client').find('.latitude');
      clatitude.push(clientLatitude.text());

      var clientLongitude = $(element).closest('.client').find('.longitude');
      clongitude.push(clientLongitude.text());
    });
        window.alert(clatitude[0]);
  })
});
</script>
1
  • Don't you have your </tr> and <% end %> backwards? Do you have jQuery available? Commented Nov 16, 2014 at 6:41

2 Answers 2

2

You should include the JQuery library to help you out. In your layout.html.erb file, add this inside the <head>:

<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>

JQuery has the eq function to select based on index docs.

There is also the siblings function that will return the nodes nested within the same parent element (in this case <tr>. You can also include a selector to further pare down results.

Example excerpt from app/views/clients/index.erb:

<% @clients.each do |client| %>
  <tr class="client">
    <td class="name"><%= client.name %></td>
    <td class="phone"><%= client.phone %></td>
    <td class="address"><%= client.address %></td>
    <td class="pay"><%= client.pay %></td>
    <td class="latitude"><%= client.latitude %></td>
    <td class="longitude"><%= client.longitude %></td>
    <td><form><input class="route" type="checkbox" name = "chkboxRoute"></form></td>
  </tr>
<% end %>

And the Javascript:

// $ is the jQuery global object
// Passing it a function will wait to execute that code until
// the entire HTML document is ready
$(function() {
  // Select every input with the "route" class that is checked
  var names = [];
  $(".client input.route:checked").each(function(index, element) {
    // Wrap the element in jQuery so we get access to all of its functions
    element = $(element);

    // Find the closest element with class "client",
    // then find an element nested inside of it with class "name"
    var clientName = $(element).closest('.client').find('.name');

    // Add the text from that element to the array
    names.push(clientName.text());
  });

  // At this point, names will hold all of the names of the clients
  // with a checked route input
});

Note that this will only run at the time the page loads. If you want it to run any time one of those changes, you can bind the function to the change event:

$(function() {
  $(".client input.route:checked").bind("change", function(element) {
    var names = [];
    $(".client input.route:checked").each(function(element) {
      element = $(element);
      var clientName = $(element).closest('.client').find('.name');
      names.push(clientName.text());
    });
  })
});

This will run through all of them every time a checkbox is changed. Not the best for performance, but that should get you started.

Sign up to request clarification or add additional context in comments.

3 Comments

I'd probably use $(element).closest('.client').find('.name') to be a little less dependent on the specific HTML but that's just nitpicking.
I think I've managed to get it working, but I wanted to test it out by adding a window.alert(names[0]) right after the first }); but all I get is a blank window. I really appreciate your help.
can you console.log(element.closest(".client").html()) after the line element = $(element)? Or update your question with your HTML
1

Add some data - your client.id if nothing else, to the checkbox in some way. It'll make your life easier. You can do that in a couple of ways, but the easiest is as part of the name:

<input type="checkbox" name = "chkboxRoute_<%= client.id %>">

or

<input type="checkbox" name = "chkboxRoute[]" value="<%= client.id %>">

With HTML5 you can use a separate "data-client-id" attribute or something like that.

Do you want to access the data from javascript or back in Rails? If you want the name or something else just stick it in the value or other attribute of the checkbox.

The "" stuff is extraneous, particularly if you want to just access this via javascript.

Revision based on comment below:

I would modify the html as such:

<% @clients.each do |client| %>
  <tr class="client">
    <td class="client_<%= client.id %> name"><%= client.name %></td>
    <td class="client_<%= client.id %>phone"><%= client.phone %></td>
    <td class="client_<%= client.id %>address"><%= client.address %></td>
    <td class="client_<%= client.id %>pay"><%= client.pay %></td>
    <td class="client_<%= client.id %>latitude"><%= client.latitude %></td>
    <td class="client_<%= client.id %>longitude"><%= client.longitude %></td>
    <td><input class="route" type="checkbox" name = "chkboxRoute" value="client_<%= client.id %>"></td>
  </tr>
<% end %>

That makes your html a little more complex but the javascript is then simplified. Again, Chris code is solid so I won't replicate everything he's done. With the html changed thusly you can directly grab the values that you want:

$(".client input.route:checked").each(function(element) {
  var client_class = $(element).val();
  var client_name = $("." + client_class + " name").text();
  var client_phone = $("." + client_class + " phone").text();
  ...
});

I just like doing something like that because it doesn't rely so much on the structure of the html.

Now, if you want to really go for the gold here's the way I would do it:

<% @clients.each do |client| %>
  <tr class="client">
    <td><%= client.name %></td>
    <td><%= client.phone %></td>
    <td><%= client.address %></td>
    <td><%= client.pay %></td>
    <td><%= client.latitude %></td>
    <td><%= client.longitude %></td>
    <td><input class="route" type="checkbox" name = "chkboxRoute" value="<%= client.id %>"></td>
  </tr>
<% end %>

<script type="text/javascript">
  var clients = [];
  <% @clients.each do |client| %>
    clients[<%= client.id %>] = {
      name: "<%= j(client.name) %>",
      phone: "<%= j(client.phone) %>",
      ....
    };
  <% end %>
</script>

Then, getting the values is simply a matter of this:

$(".client input.route:checked").each(function() {
  var client_id = parseInt($(this).val());
  var client_name = clients[client_id].name;
  var client_phone = clients[client_id].phone;
  ...
});

You can even use a json template to put the array together if you like. Anyway, that should give you plenty to chew on.

4 Comments

Thanks for the response. I would like to access the data from Javascript. By doing what you say how could I then access each clients info (name, telephone, etc.) ?
If you want to access all of it via javascript then Chris' answer is probably the route you want to go - and his answer is correct. I am going to revise my answer to show how I would do it.
I tried your answer and it works right up to var client_id = parseInt($(element).val()); I added a window.alert(client_id) , and I get a NaN :/
UPDATE: Managed to get it working by replacing element with this. THANK YOU SOOO MUCH!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.