1

I have created a view that generates posts and each post have a comments_set which produces all the comments made by user. When new comment is posted, below function is executed.

$("#comment-post-button").click(function(){ 
    var event_id = document.getElementById('event-id').value;
    var url= '/post-comments/'+event_id +'/';

    var data = {csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[0].value,
              content:document.getElementsByName('comment-post-content')[0].value
             }
    $.post(url , data, function(){
      $("#refresh-comments").load("/comments/" + event_id + '/', function(){
        $("#comment-post-content").val(""); 
      });
    });
    $("#comment-post-content").val("");  
    return false;
  });

The problem is that the page contains multiple posts and each comment submission button has the same id "comment-post-button". So the above function works only for the top post and not for the rest. I can see what the problem is but don't know how to solve this. Please help.

Here is the html markup:

{% for event in events %}
    <div class="post">
      <div class="post-right">
        <div class="post-author"><a href="/{{ event.author.username }}/">{{ event.author.first_name }}</a></div>
        <div class="post-content">{{ event.description }}</div> 
        <div class="post-bar">
          <div class="post-likes">{{ event.up_votes }}<a href="#"><img src="/site-media/static/images/like.png" /></a></div>
          <div class="post-dislikes">{{ event.down_votes }}<a href="#"><img src="/site-media/static/images/dislike.png" /></a></div> 
          <div class="post-timestamp">{{ event.pub_date }}</div>
          <a href="#" class="post-comment-link">Comment</a>
        </div>
        <div class="post-comment">
          <form method="post" action="/post-comments/{{ event.id }}/">
            {% csrf_token %}
            <input type="text" id="comment-post-content" name="comment-post-content" maxlength="200" placeholder="Add a comment..." />
            <input type="hidden" id="event-id" value="{{ event.id }}">
            <input type="submit" id="comment-post-button" class="comment-post-button" value="Post comment" />
          </form>
        </div>
        <div id="refresh-comments" class="comments">
          {% include "comments.html" %}
        </div>
      </div>
      <div class="post-left">
        <a href="#"><img src="../FestJanta/site-media/static/images/post.jpg" /></a>
      </div>
    </div>
    {% endfor %}

comments.html:

{% for comment in event.comment_set.all|slice:"3" %}
<div class="comments-right">
    <a href="/{{ name }}/" class="first_name">{{ comment.author.first_name }}</a>
    {{ comment.content }}<br>
    <div class="comment-timestamp">{{ comment.pub_date }}</div>
</div>
<div class="comments-left"><a href="#"><img src="../FestJanta/site-media/static/images/comment.jpg" /></a></div>
{% endfor %}

Final working solution:

$(".comment-post-button").click(function(){ 
    var btn = $(this);
    var currentPost = btn.parents('.post');
    var event_id = currentPost.find('.event-id').val();
    var url= '/post-comments/'+event_id +'/';
    var data = {csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[0].value,
              content:currentPost.find('input[name="comment-post-content"]').val()
             }
    $.post(url , data, function(){
      $(currentPost.find('.refresh-comments')).load("/comments/" + event_id + '/', function(){
        $(currentPost.find('.comment-post-content')).val(""); 
      });
    }); 
    return false;
  });
6
  • You can provide same class to all Post button and then access them by class Commented Nov 22, 2013 at 7:40
  • @AjinderSingh But, how is this gonna solve the problem. I need to identify a post button uniquely Commented Nov 22, 2013 at 7:42
  • @karaxuna Can you please elaborate? Commented Nov 22, 2013 at 7:43
  • @AjinderSingh I tried doing it but this leads to posting all the comments to the first event. Commented Nov 22, 2013 at 7:50
  • @Monique - You can use $(this) to access the current clicked Button Commented Nov 22, 2013 at 7:52

3 Answers 3

1

Remove id and add class:

<input type="hidden" class="event-id" value="{{ event.id }}">

Do something like this:

$('.comment-post-button').click(function(){
    var $btn = $(this);
    var $currentPost = $btn.parents('.post');
    var event_id = $currentPost.find('.event-id').val();
    //...
});

Find each element in $currentPost scope: Instead of this:

content: document.getElementsByName('comment-post-content')[0].value

Do this:

content: $currentPost.find('input[name="comment-post-content"]').val()
Sign up to request clarification or add additional context in comments.

1 Comment

Its still unable to get the 'content' input.
1

You could do the following:

  • Identify all post buttons, e.g. by a class like .comment-button
  • Use the .on() notation of jQuery
  • Pass the event and use its target property to identify the DOM element that triggered the event
  • Use traversion to get the correct DOM element of the post

The result should look something like this (untested):

Markup (I basically just got rid of the IDs; not sure how/if django handles this automatically):

{% for event in events %}
<div class="post">
  <div class="post-right">
    <div class="post-author"><a href="/{{ event.author.username }}/">{{ event.author.first_name }}</a></div>
    <div class="post-content">{{ event.description }}</div> 
    <div class="post-bar">
      <div class="post-likes">{{ event.up_votes }}<a href="#"><img src="/site-media/static/images/like.png" /></a></div>
      <div class="post-dislikes">{{ event.down_votes }}<a href="#"><img src="/site-media/static/images/dislike.png" /></a></div> 
      <div class="post-timestamp">{{ event.pub_date }}</div>
      <a href="#" class="post-comment-link">Comment</a>
    </div>
    <div class="post-comment">
      <form method="post" action="/post-comments/{{ event.id }}/">
        {% csrf_token %}
        <input type="text" name="comment-post-content" maxlength="200" placeholder="Add a comment..." />
        <input type="hidden" name="event-id" value="{{ event.id }}">
        <input type="submit" class="comment-post-button" value="Post comment" />
      </form>
    </div>
    <div class="comments">
      {% include "comments.html" %}
    </div>
  </div>
  <div class="post-left">
    <a href="#"><img src="../FestJanta/site-media/static/images/post.jpg" /></a>
  </div>
</div>
{% endfor %}

Javascript:

$("body") // Could be any ancestor, body is not the best option
.on('click', '.comment-post-button' function(ev){ 
    var clickTarget = ev.target, // The element clicked on
    postElement = $(clickTarget).closest('.post'), // the div enclosing a post
    commentSection = $(postElement).find(".comments"), // the div enclosing the comments
    commentInputField = $(clickTarget).siblings("[name='comment-post-content']"),
    event_id = $(clickTarget).siblings("[name='event-id']").val(),
    url= '/post-comments/'+event_id +'/';

    // Not sure what this token is, so I will not change that part
    var data = {csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[0].value,
          content: commentInputField.val()
         }
    $.post(url , data, function(){
        $(commentSection).load("/comments/" + event_id + '/', function(){
            $(commentInputField ).val("").prop('disabled', false); // In the callback, empty and reenable
        });
    });
    $(commentInputField ).prop('disabled', true); // I guess disabling the field makes sense
    return false;
});

An additional advantage is that you will end up with only one click handler. Note that the solution could be optimized (e.g. by improving the selectors). In addition, jslint will give some warnings.

Comments

0

to give each post & post_Comment_button a unique id, as suggested by someone, change the markup as follows:

{% for event in events %}
    <div class="post" id="post_{{forloop.counter}}">

    [...]

    <input type="submit" id="comment-post-button_{{forloop.counter}}" class="comment-post-button" value="Post comment" />

then change the js function as follows:

$("#comment-post-button").click(function(event){ 
    var buttonNr = event.target.id.replace('comment-post-button_', ''); 
    var postId = 'post_' + buttonNr;

    $("#" + postId)... --> and do whatever with it..

1 Comment

But, if I do this I'm gonna have to write a jquery function for each of it. That desn't solve it.

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.