user2158382
user2158382

Reputation: 4520

Ruby on Rails jQuery: Toggle not working

I am trying to create a button that shows/hides a div. It seems relatively easy, but whenever I click this button, it just does a refresh, and when I keep clicking it, it hides most of my page. Here is what I have so far. Also, I dont know if it matters but I am using foundation for most of the css

application.js

$(function() {
  $(document).foundation();
});

$(document).ready(function() {

    $('#message_button').click(function() {
        $("#messages").toggle();
    });

});

_userindex.html

    <div class="row">
      <div class="small-12 columns new-button">
        <%= link_to 'New Job', new_job_path, class: 'button' %>
      </div>
    </div>

    <div class="section-container auto" data-section>
      <section>
        <p class="title" data-section-title><a href="#panel1">Active Jobs</a></p>
        <div class="content" data-section-content>
          <% if @active.present? %>
            <ul>
              <% @active.each do |job| %>
                <li class='panel'>

                  <div class="row">
                    <div class="small-12 columns">
                      <div class="row">
                        <div class="large-6 columns">
                          <span id="location"><strong>location</strong>: <%= job.location %></span>
                        </div>
                        <div class="large-6 columns">
                          <span id="status"><strong>status</strong>: <%= job.status %></span>
                        </div>
                      </div>
                      <div class='light panel bottom'>
                        <strong>job: <%= link_to job.name, job %></strong><br>
                        <%= job.description %>
                      </div>
                    </div>
                  </div>

                  <div class="row job-buttons">
                    <div class="small-6 columns">
    MESSAGES BUTTON -->>>  <%= link_to 'messages', '', class: 'button small secondary', id: "message_button" %>
                    </div>
                    <div class="small-6 columns">
                      <%= link_to 'cancel', job, method: :delete, data: {confirm: 'Are you sure?'}, class: 'button small alert' %>
                    </div>
                  </div>

                  <br />


I WANT TO HIDE THIS ENTIRE DIV ---->>>>  <div id="messages">
                    <div class="row">
                      <div class="small-12 columns">
                        <div class="panel">
                          <%= form_for(@message) do |f| %>
                            <%= f.label :body, "Description" %>
                            <%= f.text_area :body %>
                            <%= f.hidden_field :job_id, value: job.id %>
                            <%= f.submit 'Create message', class: 'button small secondary' %>
                          <% end %>
                        </div>
                      </div>
                    </div>

                    <% jobs_messages = job.messages %>
                    <% if jobs_messages.present? %>
                      <ul>
                        <% jobs_messages.each do |m| %>
                        <% if m.user_id.present? %>
                          <% user = m.user %>
                        <% else %>
                          <% user = m.runner %>
                        <% end %>
                          <li class='panel'>
                            <div class='row'>
                              <div class='small-12 columns'>
                                <p> From: <%= user.login %> </p>
                                <p> Body: <%= m.body %>
                              </div>
                            </div>
                          </li>
                        <% end %>
                      </ul>
                    <% else %>
                      <div class="empty panel">
                        <p>no messages at the moment</p>
                      </div>
                    <% end %>
                  </div>

                </li>
              <% end %>
            </ul>
          <% else %>
            <div class="empty panel">
              <p>no active jobs at the moment</p>
            </div>
          <% end %>
        </div>
      </section>
      <section>
        <p class="title" data-section-title><a href="#panel2">Completed Jobs</a></p>
        <div class="content" data-section-content>
          <% if @completed.present? %>

          <% else %>
            <div class="empty panel">
              <p>no completed jobs yet</p>
            </div>
          <% end %>
        </div>
      </section>
    </div>

I am trying to an $().click action to the link_to button with id "message_button". Whenever this button/link is clicked, I want it to show/hide the "messages" div.

I am new to jQuery, rails, and foundation, so I left most of the code just in case anything was important. But I marked the message_button and the message div to help you better find it.

Upvotes: 3

Views: 2256

Answers (1)

Jace
Jace

Reputation: 3072

2 problems:

  1. It looks to me as though you have a bad case of the "multiple IDs"!
  2. You are not preventing the default behaviour of the link. (so when you click it, the page refreshes or navigates away)

Problem #2 is easy: call preventDefault() (usage example below).

Problem #1 is a little trickier...

You are creating <li> content within a loop, inside each of those <li> tags you have elements with the IDs #messages and #message_button. Multiple instances of an ID on the same page is not allowed. If you want, you can use classes instead of ids as you can have multiple instances of a class.

However, switching from IDs to Classes won't fix your problem, as if you use classes you'll just be toggling ALL messages when any message button is clicked.

Referring to this question here, you can easily get the index of the loop in your rails template:

<% @active.each do |job, index| %>
   Your template/html code here
<% end %>

This exposes a new variable, index which you can use to decorate each of your messages and buttons with an index value to then specify which message you wish to show.


Note: I'm not sure if this is the best approach, but this should work. It's been a while since I've used Rails, so there might be errors. I've included the code below just to demonstrate the possible solution:

application.js:

$(function() {
  $(document).foundation();
});

$(document).ready(function() {

    //NOTE that I am selecting on a class here
    $('.message_button').click(function(e) {
        //You also need to prevent the default behaviour of 
        //the link. That is why the page keeps refreshing.
        e.preventDefault();

        //get the index value I appended to this elements ID
        var msgButtonIndex = $(this).attr("id").replace("message_button_","");

        //select and toggle the respective message
        $("#messages_" + msgButtonIndex).toggle();
    });

});

_userindex.html:

<div class="row">
  <div class="small-12 columns new-button">
    <%= link_to 'New Job', new_job_path, class: 'button' %>
  </div>
</div>

<div class="section-container auto" data-section>
  <section>
    <p class="title" data-section-title><a href="#panel1">Active Jobs</a></p>
    <div class="content" data-section-content>
      <% if @active.present? %>
        <ul>
          <% @active.each do |job,index| %>
            <li class='panel'>

              <div class="row">
                <div class="small-12 columns">
                  <div class="row">
                    <div class="large-6 columns">
                      <span id="location"><strong>location</strong>: <%= job.location %></span>
                    </div>
                    <div class="large-6 columns">
                      <span id="status"><strong>status</strong>: <%= job.status %></span>
                    </div>
                  </div>
                  <div class='light panel bottom'>
                    <strong>job: <%= link_to job.name, job %></strong><br>
                    <%= job.description %>
                  </div>
                </div>
              </div>

              <div class="row job-buttons">
                <div class="small-6 columns">
                  <%# Adding a "message_button" class and a decorated "message_button_{index}" ID! %>
                  <%= link_to 'messages', '', class: 'button small secondary message_button', id: "message_button_" + index.to_s %>
                </div>
                <div class="small-6 columns">
                  <%= link_to 'cancel', job, method: :delete, data: {confirm: 'Are you sure?'}, class: 'button small alert' %>
                </div>
              </div>

              <br />

              <%# decorating this ID too %>
              <div id="messages_<%= index.to_s %>">
                <div class="row">
                  <div class="small-12 columns">
                    <div class="panel">
                      <%= form_for(@message) do |f| %>
                        <%= f.label :body, "Description" %>
                        <%= f.text_area :body %>
                        <%= f.hidden_field :job_id, value: job.id %>
                        <%= f.submit 'Create message', class: 'button small secondary' %>
                      <% end %>
                    </div>
                  </div>
                </div>

                <% jobs_messages = job.messages %>
                <% if jobs_messages.present? %>
                  <ul>
                    <% jobs_messages.each do |m| %>
                    <% if m.user_id.present? %>
                      <% user = m.user %>
                    <% else %>
                      <% user = m.runner %>
                    <% end %>
                      <li class='panel'>
                        <div class='row'>
                          <div class='small-12 columns'>
                            <p> From: <%= user.login %> </p>
                            <p> Body: <%= m.body %>
                          </div>
                        </div>
                      </li>
                    <% end %>
                  </ul>
                <% else %>
                  <div class="empty panel">
                    <p>no messages at the moment</p>
                  </div>
                <% end %>
              </div>

            </li>
          <% end %>
        </ul>
      <% else %>
        <div class="empty panel">
          <p>no active jobs at the moment</p>
        </div>
      <% end %>
    </div>
  </section>
  <section>
    <p class="title" data-section-title><a href="#panel2">Completed Jobs</a></p>
    <div class="content" data-section-content>
      <% if @completed.present? %>

      <% else %>
        <div class="empty panel">
          <p>no completed jobs yet</p>
        </div>
      <% end %>
    </div>
  </section>
</div>

Upvotes: 2

Related Questions