Search code examples
jqueryparent-childparentsiblings

Parents / siblings / children: struggling to select relevant element


I'm creating a blog and am trying to toggle an edit comments form using JQuery.

Here's the full code for the comments display section:

<!--================== COMMENTS DISPLAY SECTION     ====================================================================-->
<div id="comments">
    <% blog.comments.forEach(function(comment){ %>
    <div class="jumbotron comment">
        <div class="row">
            <div class="col-md-1">
                <img class="comment-ico" src = "<%=comment.author.image%>">
            </div>

            <div class="col-md-7">
                <h4><%=comment.author.username%></h4>
            </div>
            <div class="col-md-4 date">
                 <%= comment.created.toDateString()%>
            </div>
        </div>
    </div>
        <div><p><%=comment.text%></p></div>

<!--=================EDIT COMMENT FORM =========================================================================-->
   <form class="edit-comment-form" action = "/blogs/<%= blog._id %>/comments" method = "POST" id="newComment">
        <textarea class = "form-control" rows="4" placeholder = "Type comment here..." name = "comment[text]"></textarea>
        <button class = "btn btn-lg btn-primary btn-block">Submit</button>
    </form>
<!--    ==================================================================================================================-->
<!--=================COMMENT OPTIONS (visible if user = author) =====================================================-->

    <% if(currentUser && currentUser.username == comment.author.username) { %>
        <div class="row">
            <div class="col-md-1 choice">
                <a class="edit">Edit</a>
            </div>
            <div class="col-md-1">
                <form id = "delete-form" action = "/blogs/<%= blog._id %>/comments/<%=comment._id%>?_method=DELETE" method = "POST">
                <input type = "submit" class = "button-delete" value = "Delete"></form>
            </div>
        </div>
    <% } %>
    <hr class = "style-three">
    <% }) %>
</div>
</div>
<!--====================================================================================================================-->
<!--======================ADD COMMENT FORM ================================================================================    -->
<% if(currentUser){ %>
<div class = "container form">
   <form action = "/blogs/<%= blog._id %>/comments" method = "POST"  id="newComment">
    <div class="row">
        <div class="col-md-2">
            <img class="newComment-ico" src = "<%=currentUser.image%>">
        </div>
        <div class="col-md-10">
            <label for="comment">Add comment</label>
        </div>
    </div>
        <textarea class = "form-control" rows="4" placeholder = "Type comment here..." name = "comment[text]"></textarea>
        <button class = "btn btn-lg btn-primary btn-block">Submit</button>
    </form>
</div>

<% } %>

My JS is as follows:

$('#comments').on('click', '.edit', function(){
$(this).parents().siblings('.edit-comment-form').toggle();
})

However, this is selecting ALL dynamically displayed items (comments) so that when I click on the '.edit' element, all comments reveal their edit box. I know this is to do with how I am selecting them in terms of parent/sibling etc. but cannot work out what it should be!


Solution

  • @Satpal comment is perfect and credits to him, with his mercy though, I'll try to dive a bit deeper into the logics:

    $('#comments').on('click', '.edit', function() {
        $(this).closest('.row').prev('.edit-comment-form').toggle();
    });
    

    Since .edit is inside of .row and .edit-comment-form before it (.row), basically you are impacting the previous .edit-comment-form of the closest .row's clicked .edit.

    On simpler words, the closest row is the same as the clicked edit and it's previous textarea (.edit-comment-form) will be toggled.

    Here's a generic example of both prev() & closest() jQuery methods:

    • Also notes why find() didn't work, because it toggles all .edit-comment-form nested in #comments.

    var selected = $("#start");
    selected.css("background", "gainsboro");
    
    //prev() - Will select previous element disregarding tag name
    $(".prev").on('click', function() {
      selected = selected.prev();
      $("div").css("background", "");
      $("nav").css("background", "");
      $("section").css("background", "");
      $("span").css("background", "")
      selected.css("background", "gainsboro");
    });
    
    //closest() - Will highlight red only if selected element is a div
    $(".closest").on('click', function() {
      selected.closest('div').css("background", "red");
    });
    
    //find() - Will only highlight when span element is child 
    $(".find").on('click', function() {
      selected.find('span').css("background", "red");
    });
    
    //Reset
    $(".reset").on('click', function() {
      $("div").css("background", "");
      $("nav").css("background", "");
      $("section").css("background", "");
      $("span").css("background", "");
      selected = $("#start");
      selected.css("background", "gainsboro");
    });
    div {
      width: 40px;
      height: 40px;
      margin: 10px;
      float: left;
      border: 2px lightgray solid;
      padding: 2px;
    }
    
    .inline {
      float: left;
      margin: 10px;
      width: 48px;
      text-align: center;
      line-height: 48px;
    }
    
    #row {
      width: 100%;
      border: none;
      padding: 0;
      margin: 0;
      height: 60px;
    }
    
    section {
      width: 40px;
      height: 40px;
      margin: 10px;
      float: left;
      border: 2px lightgray solid;
      padding: 2px;
    }
    
    nav {
      width: 40px;
      height: 40px;
      margin: 10px;
      float: left;
      border: 2px lightgray solid;
      padding: 2px;
    }
    
    span {
      font-size: 14px;
      word-wrap: break-word;
    }
    
    button {
      margin: 10px;
      padding: 10px;
      background: transparent;
      border: 2px solid gray;
      border-radius: 3px;
      color: gray;
      font-size: 12px;
    }
    
    button:hover {
      background: gray;
      color: white;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <section id="row">
      <div></div>
      <div class="find"></div>
      <span class="inline">span</span>
      <div><span>find() here</span></div>
      <section></section>
      <nav></nav>
      <div id="start"></div>
    </section>
    <button class="prev">test prev()</button>
    <button class="closest">test closest()</button>
    <button class="find">test find()</button>
    <button class="reset">reset</button>