Why querySelectorAll is not working on my forms? - javascript

I am very new to javascript. I was working on a Django project. In the project, multiple forms are created by Django. I used event listener to all of the forms. Here is my javascript code:
document.addEventListener("DOMContentLoaded",function(){
document.querySelectorAll(`#likeform${posts_id}`).forEach(e =>{
e.addEventListener('submit',(event) => {
event.preventDefault();
like_function();
// return false;
});
});
})
function like_function(){
fetch(`/like/${posts_id}`,{
method:"POST",
body : JSON.stringify({
"is_like" : is_like,
"num_like" : num_like,
})
})
.then(response => response.json())
.then(result => {
if(result.is_like){
console.log("function is liked");
console.log(`${result.is_like} for post ${posts_id}`);
let num_like = result.num_like;
console.log(`Number of posts : ${num_like}`);
document.querySelector(`#likebtn${posts_id}`).innerHTML = "Unlike";
num_like = num_like + 1;
console.log(`Number of posts : ${num_like}`);
document.querySelector(`#num_of_likes_${posts_id}`).innerHTML = `${num_like} `
// location.replace("http://127.0.0.1:8000")
}
else{
console.log("function is unliked, back off!");
console.log(`${result.is_like} for post ${posts_id}`);
let num_like = result.num_like;
console.log(`Number of posts : ${num_like}`);
document.querySelector(`#likebtn${posts_id}`).innerHTML = "Like";
num_like = num_like - 1;
console.log(`Number of posts : ${num_like}`);
document.querySelector(`#num_of_likes_${posts_id}`).innerHTML = `${num_like} `
// location.replace("http://127.0.0.1:8000")
}
})
}
I used querySelectorAll so that all forms work nicely. Unfortunately, only one form works. What goes wrong here?
As everyone is asking where I've defined posts_id in the comments, I'm editing my question and sharing my templates.html file.
templates.html
{% load static %}
<div id="likeapost{{posts.id}}" class="card-footer">
{% if request.user in posts.likepost.all %}
<form action="{% url 'likepost' posts_id=posts.id %}" id="likeform{{posts.id}}" method="POST" style="display: inline;">
<!-- {% csrf_token %} -->
<button id="likebtn{{posts.id}}" class="btn btn-link" type="submit">Unlike</button>
</form>
{% else %}
<form action="{% url 'likepost' posts_id=posts.id %}" id="likeform{{posts.id}}" method="POST" style="display: inline;">
<!-- {% csrf_token %} -->
<button id="likebtn{{posts.id}}" class="btn btn-link" type="submit">Like</button>
</form>
{% endif %}
<small id="num_of_likes_{{posts.id}}" class="num_of_likes">{{ posts.likepost.all.count }}</small>
{% block script %}
<script>
posts_id = "{{ posts.id }}";
is_like = "{{is_like}}";
num_like = "{{ posts.likepost.all.count }}";
</script>
<script src="{% static 'network/controller.js' %}"></script>
{% endblock %}
<button class="btn btn-link" style="text-decoration: none;">Comment</button>
View Post
{% if request.user.id is posts.user.id %}
Edit
{% endif %}
<!-- <div class="likepost"></div> -->
</div>
If I need to share more pieces of code please tell me.

If you want to get all the elements with an id that starts with something, use the following :
document.querySelectorAll('[id^="likeform"]').forEach((e=>{ // ...

Related

Why html buttons dynamically created by django cannot access my javascript function?

My Django application makes divs dynamically. Each div is a post of a blog post and also I have a like button on each div. Each button will automatically turn into unlike when a user clicks on it without reloading using javascript. I wrote a javascript function for this. Unfortunately, my javascript function works only the last post on a page (As I have pagination property).
document.addEventListener("DOMContentLoaded",function(){
// const colon = document.createElement('div');
// colon.setAttribute('id','colon')
// e.preventDefault()
// const likebtn = document.createElement('button');
// likebtn.setAttribute('class','likebtn btn btn-primary');
// likebtn.setAttribute('class','likebtn');
// document.querySelector('.card-footer').appendChild(likebtn);
// document.querySelector('.likebtn').innerHTML = "Like";
document.querySelector(`#likeform${posts_id}`).addEventListener('submit',(event) => {
event.preventDefault();
like_function();
// return false;
})
// document.querySelector('.likepost').addEventListener('click', ()=> like_function('likepost'));
})
// let is_like = "{{is_like}}";
// let num_like = "{{num_like}}";
function like_function(){
// document.createElement('button').innerHTML = "Love";
// console.log("Updated!")
fetch(`/like/${posts_id}`,{
method:"POST",
body : JSON.stringify({
"is_like" : is_like,
"num_like" : num_like,
})
})
.then(response => response.json())
.then(result => {
if(result.is_like){
console.log("function is liked");
console.log(`${result.is_like} for post ${posts_id}`);
let num_like = result.num_like;
console.log(`Number of posts : ${num_like}`);
document.querySelector(`#likebtn${posts_id}`).innerHTML = "Unlike";
num_like = num_like + 1;
console.log(`Number of posts : ${num_like}`);
document.querySelector(`#num_of_likes_${posts_id}`).innerHTML = `${num_like} `
// location.replace("http://127.0.0.1:8000")
}
else{
console.log("function is unliked, back off!");
console.log(`${result.is_like} for post ${posts_id}`);
let num_like = result.num_like;
console.log(`Number of posts : ${num_like}`);
document.querySelector(`#likebtn${posts_id}`).innerHTML = "Like";
num_like = num_like - 1;
console.log(`Number of posts : ${num_like}`);
document.querySelector(`#num_of_likes_${posts_id}`).innerHTML = `${num_like} `
// location.replace("http://127.0.0.1:8000")
}
})
}
// function like_function(){
// if (document.querySelector("#like").style.color == "blue"){
// document.querySelector("#like").style.color = "red";
// }else{
// document.querySelector("#like").style.color = "blue";
// }
// }
This is my full javascript code. Here I'm sharing my HTML template,
<div id="posts" class="card">
<ul class="card-body">
{% for posts in page_view %}
<li class="card">
<div class="card-header bg-success">
<h5 class="card-title"><a class="text-light" style="text-decoration: none;" href="{% url 'profile' posts.user.id %}">{{ posts.user }}</a></h5>
<h6 class="card-subtitle text-light">{{ posts.timestamp }}</h6>
</div>
<div class="card-body">
<h3 class="card-text">{{ posts.post }}</h3>
</div>
<div id="likeapost{{posts.id}}" class="card-footer">
{% if request.user in posts.likepost.all %}
<form action="{% url 'likepost' posts_id=posts.id %}" id="likeform{{posts.id}}" method="POST" style="display: inline;">
<!-- {% csrf_token %} -->
<button id="likebtn{{posts.id}}" class="btn btn-link" type="submit">Unlike</button>
</form>
{% else %}
<form action="{% url 'likepost' posts_id=posts.id %}" id="likeform{{posts.id}}" method="POST" style="display: inline;">
<!-- {% csrf_token %} -->
<button id="likebtn{{posts.id}}" class="btn btn-link" type="submit">Like</button>
</form>
{% endif %}
<small id="num_of_likes_{{posts.id}}" class="num_of_likes">{{ posts.likepost.all.count }}</small>
{% block script %}
<script>
posts_id = "{{ posts.id }}";
is_like = "{{is_like}}";
num_like = "{{ posts.likepost.all.count }}";
</script>
<script src="{% static 'network/controller.js' %}"></script>
{% endblock %}
<button class="btn btn-link" style="text-decoration: none;">Comment</button>
View Post
{% if request.user.id is posts.user.id %}
Edit
{% endif %}
<!-- <div class="likepost"></div> -->
</div>
</li>
{% empty %}
<h6>No post availabel 😔</h6>
{% endfor %}
</ul>
</div>
This is my HTML template. All the buttons should work like this,
Only this one button works perfectly, but others do not. This is what happening.
What should I do? I am about 90% done. Please help.

infinite scroll working but not doing things as it should

in my web site i want to show the user ratings for that i used the infinite scroll but i am facing one problem.
when it first loads the data before calling the <a class="infinite-more-link" href="?page={{ ratings.next_page_number }}"></a> it is showing the star with the count of vote,but when after calling the <a class="infinite-more-link" href="?page={{ ratings.next_page_number }}"></a> it is not showing the star.
my views.py
#login_required
def ratings_user(request,pk):
ratings = VoteUser.objects.filter(the_user_id=pk).order_by('-pk')
paginator = Paginator(ratings, 1)
page = request.GET.get('page')
try:
posts = paginator.page(page)
except PageNotAnInteger:
posts = paginator.page(1)
except EmptyPage:
posts = paginator.page(paginator.num_pages)
return render(request,request.session['is_mobile']+'profile/ratings.html',{'ratings':posts})
html
{% extends 'mobile/profile/base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% load get_companion %}
{% load cache %}
{% block title %}
Ratings
{% endblock %}
{% block leftcontent %}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" rel="stylesheet">
{% endblock %}
{% block middlecontent %}
<div class="infinite-container">
{% for i in ratings %}
<div class="infinite-item">
<div class="w3-container w3-card w3-white w3-round w3-margin">
<img src="{{ i.the_user.profile.avatar.url }}" alt="Avatar" class="w3-left w3-circle w3-margin-right" style="width:40px;height:40px;border-radius:50%;">
{% with user=i.the_user.profile %}{{ user.prenom|title|truncatewords:2 }} {{ user.nom|title|truncatewords:1 }}{% endwith %}
<br>
<span class="stars" data-rating="{{ i.vote.vote }}" data-num-stars="5" ></span>
<hr class="w3-clear">
<p>
{{ i.commentaire|linebreaksbr }}
</p>
<span class="glyphicon glyphicon-user"></span> {% with user=i.the_sender.profile %}{{ user.prenom|title|truncatewords:2 }} {{ user.nom|title|truncatewords:1 }}{% endwith %}
</div>
</div>
{% endfor %}
</div>
{% if ratings.has_next %}
<a class="infinite-more-link" href="?page={{ ratings.next_page_number }}"></a>
{% endif %}
{% endblock %}
{% block rightcontent %}
{% endblock %}
{% block js %}
<script>
var infinite = new Waypoint.Infinite({
element: $('.infinite-container')[0]
});
</script>
<script>
//ES5
$.fn.stars = function() {
return $(this).each(function() {
var rating = $(this).data("rating");
var fullStar = new Array(Math.floor(rating + 1)).join('<i class="fas fa-star"></i>');
var halfStar = ((rating%1) !== 0) ? '<i class="fas fa-star-half-alt"></i>': '';
var noStar = new Array(Math.floor($(this).data("numStars") + 1 - rating)).join('<i class="far fa-star"></i>');
$(this).html(fullStar + halfStar + noStar);
});
}
//ES6
$.fn.stars = function() {
return $(this).each(function() {
const rating = $(this).data("rating");
const numStars = $(this).data("numStars");
const fullStar = '<i class="fas fa-star"></i>'.repeat(Math.floor(rating));
const halfStar = (rating%1!== 0) ? '<i class="fas fa-star-half-alt"></i>': '';
const noStar = '<i class="far fa-star"></i>'.repeat(Math.floor(numStars-rating));
$(this).html(`${fullStar}${halfStar}${noStar}`);
});
}
</script>
<script>
$(function(){
$('.stars').stars();
});
</script>
{% endblock %}
i have tried to put the <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" rel="stylesheet"> inside the class="infinite-item" but it does not help.what might be the reason for that ? Thanks.
It doesn't look like .stars() will look for new elements being added to the DOM. You should look for a callback function configuration option within Waypoint.Infinite that you can call .stars() on the new elements.

Ajax like button not showing increment in count or else

I wanted to add like heart button with like count. I want to use ajax for changing likes count and color change. but when I tried to do that it won't work.
HTML
<div id="posts">
{% for post in page_obj %}
<div><a >{{ post.userp }}</a></div>
<div>{{ post.content }}</div>
<div>{{ post.timestamp }}</div>
<div id="post_name">
{% if request.user in post.userl.all %}
<a class="likeu" style="cursor: pointer"><span id="{{ post.id }}" class="likeu1" style="font-size:24px;color:red">♥</span></a>
{% else %}
<a class="likeu" style="cursor: pointer"><span id="{{ post.id }}" class="likeu1" style="font-size:24px;color:grey">♥</span></a>
{% endif %}
<p id="{{ post.id }}l">{{ post.userl.all.count }}</p>
</div>
<hr>
{% endfor %}
</div>
and JAVASCRIPT
document.querySelectorAll('.likeu1').forEach(element => element.addEventListener('click', change_like));
function change_like(){
post_id = this.id
console.log(post_id)
fetch('/likes', {
method: 'POST',
body: JSON.stringify({
post_id : post_id,
})
})
.then(response => response.json())
.then(result => {
value = result["is_liked"];
console.log(value);
console.log(this);
if (value == 'true'){
this.style.color = 'red';
console.log('red');
}
else{
this.style.color = 'grey';
console.log('grey');
}
})
}
It is updating when I refresh but I want it without refresh.
I don't know what I am doing wrong. please help!

Django 1.10 - Ajax - order of operations?

I am using Ajax with Django 1.10 to implement a like functionality ( a user likes an image posted by another user) on my website. I have the following code :
The views file :
#ajax_required
#login_required
#require_POST
def image_like(request):
image_id = request.POST.get('id')
action = request.POST.get('action')
if image_id and action:
try:
image = Image.objects.get(id=image_id)
if action == 'like':
image.users_like.add(request.user)
else:
image.users_like.remove(request.user)
return JsonResponse({'status':'ok'})
except:
pass
return JsonResponse({'status':'ko'})
def image_detail(request, id, slug):
image = get_object_or_404(Image, id=id, slug=slug)
return render(request,
'images/image/detail.html',
{'section': 'images',
'image': image})
In base.html :
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src=" http://cdn.jsdelivr.net/jquery.cookie/1.4.1/jquery.cookie.min.js "></script>
<script>
var csrftoken = $.cookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
$(document).ready(function(){
{% block domready %}
{% endblock %}
});
</script>
And finnaly in the detail.html :
{% extends "base.html" %}
{% block title %}{{ image.title }}{% endblock %}
{% block content %}
...
{% with total_likes=image.users_like.count users_like=image.users_like.all %}
<div class="image-info">
<div>
<span class="count">
<span class="total">{{ total_likes }}</span>
like{{ total_likes|pluralize }}
</span>
<a href="#" data-id="{{ image.id }}" data-action="{% if request.user in users_like %}un{% endif %}like" class="like button">
{% if request.user not in users_like %}
Like
{% else %}
Unlike
{% endif %}
</a>
</div>
{{ image.description|linebreaks }}
</div>
<p> Image liked by :</p>
<div class="image-likes">
{% for user in image.users_like.all %}
<div>
<p>{{ user.last_name }}</p>
</div>
{% empty %}
Nobody likes this image yet.
{% endfor %}
</div>
{% endwith %}
{% endblock %}
{% block domready %}
$('a.like').click(function(e){
e.preventDefault();
$.post('{% url "images:like" %}',
{
id: $(this).data('id'),
action: $(this).data('action')
},
function(data){
if (data['status'] == 'ok')
{
var previous_action = $('a.like').data('action');
// toggle data-action
$('a.like').data('action', previous_action == 'like' ?
'unlike' : 'like');
// toggle link text
$('a.like').text(previous_action == 'like' ? 'Unlike' :
'Like');// update total likes
var previous_likes = parseInt($('span.count .total').text());
$('span.count .total').text(previous_action == 'like' ?
previous_likes + 1 : previous_likes - 1);
}
}
);
});
{% endblock %}
While I mostly understand the code itself, I need help understanding in what orders the requests, the callback functions and everything else is executed ... something like : ,users clicks the like button, that information is passed to the server , it is being manipulated, data-base modified , sent back, the page changes ...
Tell me if any extra code ( models, urls etc. ) is needed. Could't post everything.

Add Like button with Django + Ajax

Hi I create my first project like stackoverflow(question-answer). I used this guid from Tango with Django http://www.tangowithdjango.com/book17/chapters/ajax.html to add like button with ajax. And nothing hapened. Don't see any request in console. I'm noob in Django, and it's my first encounter with jquery.
apps/questions/models:
class Answer(models.Model):
text = models.TextField()
date = models.DateTimeField(default=datetime.datetime.now)
likes = models.IntegerField(default=0)
resolve = models.IntegerField(default=0)
author = models.ForeignKey(CustomUser)
question = models.ForeignKey(Question)
apps/questions/views:
#login_required
def add_like(request):
ans_id = None
if request.method == 'GET':
ans_id = request.GET['answer_pk']
likes = 0
if ans_id:
ans = Answer.objects.get(id=(int(ans_id)))
if ans:
likes = ans.likes + 1
ans.likes = likes
ans.save()
return HttpResponse(likes)
apps/questions/ulrs:
url:
url(r'add_like/$', views.add_like, name='add_like'),
question.html:
{% for answer in answers %}
<div class="container-fluid no-padding">
{{ answer.text }}
</div>
<div class="container-fluid author-question">
<p>posted: {{ answer.date.day|stringformat:"02d" }}.{{ answer.date.month|stringformat:"02d"}}.{{ answer.date.year}}</p>
<p>by: {{ answer.author.username }}</p>
</div>
{% if user.is_authenticated %}
<button class="btn btn-default" type="button" id="likes" data-ansid="{{ answer.id }}">
like | <strong id="like_count">{{ answer.likes }}</strong>
</button>
{% endif %}
js/ajax.js:
$('#likes').click(function(){
var ansid;
ansid = $(this).attr("data-ansid");
$.get('/questions/add_like/', {answer_id: ansid}, function(data){
$('#like_count').html(data);
$('#likes').hide();
});
});
Since you are creating buttons in a for loop, and naming them the same way, you have multiple elements on the page with the same id. Because of this you get unpredictable results. You should either give each button its own id, or change the jQuery selector to select the buttons based on the appropriate class.
For example, you could have:
{% for answer in answers %}
<div class="container-fluid no-padding">
{{ answer.text }}
</div>
<div class="container-fluid author-question">
<p>posted: {{ answer.date.day|stringformat:"02d" }}.{{ answer.date.month|stringformat:"02d"}}.{{ answer.date.year}}</p>
<p>by: {{ answer.author.username }}</p>
</div>
{% if user.is_authenticated %}
<button class="btn btn-default likes-button" type="button" data-ansid="{{ answer.id }}">
like | <strong id="like_count">{{ answer.likes }}</strong>
</button>
{% endif %}
{% endfor %}
And then for the javascript
$('.likes-button').click(function(){
var ansid;
ansid = $(this).attr("data-ansid");
$.get('/questions/add_like/', {answer_id: ansid}, function(data){
$('#like_count').html(data);
$('#likes').hide();
});
});

Categories

Resources