how do I use a button to display <div> in django template? - javascript

results.html
{%if searched_user %}
{{searched_user}}
<button id=likedsongsbutton>View liked songs</button>
<div>
{% for each_searched_user in searched_user %}
<br id="likedsongs"/>{% for liked_songs in each_searched_user.liked_songs.all %}{{liked_songs}}
<br/>
{% endfor %}
{% endfor %}
{% endif %}
{% endblock %}
</div>
<script>
document.querySelector("#likedsongsbutton").addEventListener(onclick, )
</script>
views.py
def results(request):
if request.method == "GET":
search_query = request.GET.get("username")
searched_user = UserProfile.objects.filter(
user__username__contains=search_query
)
return render(
request, "results.html", {
"searched_user":searched_user
})
My question is how do I make the <div> show only when the button is clicked? I do not know what function to pass in the EventListener

If you give your change you div to have an id of myDiv and set the display to be None, you can pass the following lambda in as the second parameter.
() => {document.getElementById("myDiv").style.display = ""}
While the div looks like:
<div id="myDiv" style="display: none"></div>
I also think you should change it from onclick, to "click". Here is a complete example:
<button id=likedsongsbutton>View liked songs</button>
<div id="myDiv" style="display: none; background: blue; height: 100px; width: 100px;"></div>
<script>
document.querySelector("#likedsongsbutton").addEventListener("click", () => {
document.getElementById("myDiv").style.display = ""
});
</script>

Related

Scrolldown after clicking button javascript

For my website, i would like to scrolldown automatically to an article when the user click on a button category.
Here is my twig code.
`
{% if category is not null and category|length > 0 %}
{% for categorie in category %}
<li class="nav-item category-link">
<button class="nav-link active" categoryId="{{categorie.id}}">{{categorie.name}}</button>
</li>
{% endfor %}
{% endif %}
</ul>
</div>
</div>
</nav>
<div class="">
{% for content in contents %}
<div contentId="{{content.id}}">
<h2 class="text-center">{{content.title}}</h2>
</div>`
And this is my JS part.
var contentId = document.querySelector('div').getAttribute('contentId');
var categoryId = document.querySelector("button").getAttribute('categoryId');
if(categoryId){
categoryId.addEventListener('click', function() {
if (contentId === categoryId){
window.scrollTo(contentId);
}
});
}```
For information, actually in my database contentId related to categoryId have the same value. But for future they may not have the same value.
Thanks a lot for your help.
How about a non-JS solution?
To do this with JS you would have to do a querySelectorAll on all of the buttons and add an event listener on each, then query the respective contentId div then scroll to it.
A non-JS solution can be like this:
{% if category is not null and category|length > 0 %}
{% for categorie in category %}
<li class="nav-item category-link">
{{categorie.name}}
</li>
{% endfor %}
{% endif %}
</ul>
</div>
</div>
</nav>
<div class="">
{% for content in contents %}
<div id="{{content.id}}" contentId="{{content.id}}">
<h2 class="text-center">{{content.title}}</h2>
</div>
const contents = document.querySelectorAll('div[contentId]')
const categories = document.querySelectorAll("button[categoryId]")
categories.forEach(category => {
category.addEventListener('click', function() {
const categoryId = category.getAttribute('categoryId');
const content = Array.from(contents).find(content => content.getAttribute('contentId') === categoryId)
if (content){
content.scrollIntoView({ behavior: "smooth" });
}
)}
});

JavaScript: unable to disable/enable an input button

I'm building a web app using the Django framework. I'm attempting to use some JavaScript to disable a button that users can press to submit a text-based review.
The JavaScript in the listing.js file looks as follows:
document.addEventListener('DOMContentLoaded', function () {
hide_submit_review_button();
});
// Hide the 'Submit Review'button until the user begins typing a review
// Prevent the user from typing more than 100 characters
function hide_submit_review_button() {
var submit_review_button = document.getElementById('submit-review-button');
if (submit_review_button !== null) {
document.getElementById('submit-review-button').disabled = true;
document.getElementById('review-contents').onkeyup = () => {
if ((document.getElementById('review-contents').value.length > 0 &&
document.getElementById('review-contents').value.length <= 100 )) {
document.getElementById('submit-review-button').disabled = false;
} else {
document.getElementById('submit-review-button').disabled = true;
}
};
}
}
In my listing.html file, I identify the review-contents and submit-review-button. Here's the code:
{% extends "layout.html" %}
{% load static %}
{% block body %}
{% if user.is_authenticated %}
<form action="{% url 'review' listing.id %}" method="POST">
{% csrf_token %}
<input type="text" class="form-control" name="review" id="review-contents" placeholder="Write a review...">
<input class="btn btn-primary mt-1" type="submit" id="submit-review-button" value="Submit Review">
</form>
{% endif %}
{% endblock %}
{% block script %}
{% if user.is_authenticated %}
{{ block.super }}
<script src="{% static 'listing.js' %}"></script>
{% endif %}
{% endblock %}
An example of a page where the button appears is: http://127.0.0.1:8000/listings/7
And, here is what the urls.py file looks like (if it matters):
urlpatterns = [
path('', views.index, name='index'),
path('listings/<int:listing_id>', views.listing, name='listing'),
]
Can anyone see why this button doesn't disable?
Thanks!
The problem resulted from not having the following in the header tag in the layout.html file:
{% block script %}
{% endblock %}

How can you change Django loop body using javascript?

i was wondering if there is a way i can change the body of for loop in django using javascript each time i press a button.
in my case i want to display matches this week and when i press next i want to change the list using javascript and then pass it django template in the regroup part, i want to change the matches list.
i know how to write the code to make the new list and the previous and next buttons using javascript but i don't know how to pass it to django template
or maybe another way could be to write django code in javascript, anyone can help with either way?
in views.py , matches return a list of dictionaries from today to 6 days later
def home(request):
start = datetime.now().date()
end = today + timedelta(6)
matches = request_games(today, after_week)
return render(request, "sporty/home.html",{
"matches": matches,
"start" : start,
"end": end
})
in home.html
{% extends "sporty/layout.html" %}
{% load static %}
{% block body %}
<div class="box">
{{start}},{{end}}
{% regroup matches by date as date_list %}
{% for date in date_list %}
<div class="the_date">
{{date.grouper}}
</div>
{% for match in date.list %}
<div class="match_container">
<div class="status">
{% if match.status_code == 1%}
{{match.minute}}'
{% elif match.status_code == 11%}
HT
{% elif match.status_code == 3 %}
Finished
{% endif %}
</div>
<div class="match">
<div class="home">
{{match.home_name}} <img src="{{match.home_logo}}">
</div>
<div class="score">
{% if match.status_code == 0 %}
{{match.time}}
{% elif match.status_code == 17 %}
TBD
{% elif match.status_code == 1%}
{{match.home_score}} : {{match.away_score}}
{% elif match.staus_code == 11%}
{{match.home_score}} : {{match.away_score}}
{% elif match.status_code == 3 %}
{{match.home_score}} : {{match.away_score}}
{% endif %}
</div>
<div class="away">
<img src="{{match.away_logo}}">
{{match.away_name}}
</div>
</div>
</div>
{% endfor %}
{% endfor %}
</div>
{% endblock %}
def request_games(start, end):
params = (
("season_id","1511"),
("date_from",start.strftime("%Y-%m-%d")),
("date_to",end.strftime("%Y-%m-%d"))
);
headers = {
"apikey": //my api key
}
response = requests.get('https://app.sportdataapi.com/api/v1/soccer/matches', headers=headers, params=params)
r = response.json()
data = r["data"]
number = len(data)
matches = []
for i in range(number):
match = {}
match['status'] = data[i]["status"]
match['status_code'] = data[i]["status_code"]
match['minute'] = data[i]['minute']
full_date = data[i]["match_start"]
dt = datetime.strptime(full_date, '%Y-%m-%d %H:%M:%S')
match['date'] = dt.date()
match['time'] = dt.time()
match['start'] = full_date
home_team = data[i]["home_team"]
match['home_name'] = home_team['name']
match['home_logo'] = home_team['logo']
away_team = data[i]["away_team"]
match['away_name'] = away_team['name']
match['away_logo'] = away_team['logo']
stats = data[i]['stats']
match['home_score'] = stats['home_score']
match['away_score'] = stats['away_score']
matches.append(match)
matches.sort(key = lambda x: datetime.strptime(x['start'], '%Y-%m-%d %H:%M:%S'))
return matches
First thing first, once you decide to start working on pages that do not refresh but still query the server and change, one of your solutions is to start using AJAX calls to query the server for different data.
This would add a bit of code to your project.
For example, your home.html template will need to be split into two. Make sure to also add jQuery to your head.
sporty/home.html
{% extends "sporty/layout.html" %}
{% load static %}
{% block body %}
<div id="matchweek" class="box">
{% include "sporty/matchweek.html" %}
</div>
<button type="button" value="p" onclick="weekControl(this)">Previous</button>
<button type="button" value="n" onclick="weekControl(this)">Next</button>
{% comment %}
Either place weekupdate.js in /static/ or give the path within static,
best would be to have a folder for javascript in static and use 'js/weekupdate.js'
{% endcomment %}
<script src="{% static 'js/weekupdate.js' %}"></script>
{% endblock %}
and sporty/matchweek.html
{{start}},{{end}}
{% regroup matches by date as date_list %}
{% for date in date_list %}
<div class="the_date">
{{date.grouper}}
</div>
{% for match in date.list %}
<div class="match_container">
<div class="status">
{% if match.status_code == 1%}
{{match.minute}}'
{% elif match.status_code == 11%}
HT
{% elif match.status_code == 3 %}
Finished
{% endif %}
</div>
<div class="match">
<div class="home">
{{match.home_name}} <img src="{{match.home_logo}}">
</div>
<div class="score">
{% if match.status_code == 0 %}
{{match.time}}
{% elif match.status_code == 17 %}
TBD
{% elif match.status_code == 1%}
{{match.home_score}} : {{match.away_score}}
{% elif match.staus_code == 11%}
{{match.home_score}} : {{match.away_score}}
{% elif match.status_code == 3 %}
{{match.home_score}} : {{match.away_score}}
{% endif %}
</div>
<div class="away">
<img src="{{match.away_logo}}">
{{match.away_name}}
</div>
</div>
</div>
{% endfor %}
{% endfor %}
Because you will need to update the entire content of matchweek div every time.
views.py
def home(request):
if request.is_ajax():
template = 'matchweek.html'
direction = request.GET.get('dir')
if direction == 'n':
request.session['weekoffset'] += 1
elif direction == 'p':
request.session['weekoffset'] -= 1
else:
template = 'home.html'
request.session['weekoffset'] = 0
offset = request.session['weekoffset']
start = datetime.now().date() + timedelta(days=7*offset)
end = start + timedelta(days=6)
matches = request_games(start, end)
return render(request, f"sporty/{template}",{
"matches": matches,
"start": start,
"end": end
})
What you see in the function is a check if the request is coming from the AJAX call or not and determination on what to do from there.
/static/js/weekupdate.js
function weekControl(id) {
var value = id.value;
$.ajax({
url: '', // The url suffix that leads to your home function, example: '/home/'
type: "GET", // Http method
data: {'dir': value}, // The data to be sent to the server.
success: function (htmlres) { // What to do on success and response reaching back
$("#matchweek").html(htmlres);
}
});
}
What you see here is the AJAX get call to your django view with the data of 'dir' and its value. When it is returned, jQuery will change the content of the matchweek div with the new content.
I haven't tested this but let me know if this works and if you have any questions.

How do you change an HTML tag with certain conditions?

I'm trying to make an e-commerce site with Django and I'm stuck at my home page not being able to display which products are already in my cart. I am pretty sure I haven't got the JavaScript right but I'm an absolute beginner to web-dev so could also be the Python.
This is my home :
{% extends 'base.html' %}
{% block content %}
{% for pett in pets.all %}
<div class="row pt-3" onfocus="func(pett)">
<div class="col-8" onclick="window.location='{% url 'detail' pett.id %}';" style="cursor: pointer">
<h2>{{ pett.name }}</h2>
<h4>{{ pett.breed }}</h4>
</div>
<div class="col-4">
<a id="link{{pett.id}}" href= "javascript:{document.getElementById('add{{pett.id}}').submit()}"><button id="button{{pett.id}}" class='btn btn-primary btn-xs'><h1>Add to cart +</h1></button></a>
</div>
</div>
<form id="add{{pett.id}}" method="POST" action="{% url 'add_to_cart' pett.id %}">
{% csrf_token %}
<input type="hidden"/>
</form>
{% endfor %}
<script type="text/javascript">
function func(pett){
if(cart.objects.filter(pet=pett).count()>0) {
document.getElementById('button{{pett.id}}').innerHTML = "Added ✔︎";
document.getElementById('link{{pett.id}}').href = "";}
}
</script>
{% endblock %}
This is the call to my home method :
from django.shortcuts import render
def home(request):
pets = Pet.objects
if request.user :
cart = Cart.objects.get(buyer=request.user)
else:
cart=NULL
return render(request,'pets/home.html',{'pets':pets,'cart':cart})
This is my cart model :
from django.db import models
class Cart(models.Model):
buyer = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
pet = models.ManyToManyField('pets.Pet')
Everything else is working perfectly.

Javascript inside Jinja "for" loop

I'm coding an app in Python Flask and I'm building interactive Like buttons with Javascript.
Here's my route:
#app.route('/jquery')
def jquery():
posts = Post.query.all()
return render_template('jquery.html', posts=posts)
And in the jquery.html template I have:
{% for p in posts %}
{% if p.upvotes %}
{% set pupvotes = p.upvotes %}
{% else %}
{% set pupvotes = 0 %}
{% endif %}
<p>{{ p.author.username }} says: <b>{{ p.body }}</b> <button id="
{{ p.id }}" onclick="document.getElementById('{{ p.id }}').innerHTML = {{
pupvotes }} +1 + ' Likes'">{{ pupvotes }} Likes</button></p>
{% endfor %}
Everything actually works this way, but I would like to save the results of +1 likes clicks and transfer them to a Python variable so that I can add it to the database and the updated Like numbers show up on the page after refresh.
I tried to use JavaScript function this way:
<script>
function myF1() {
document.getElementById('{{ p.id }}').innerHTML = {{ pupvotes }} +1 + '
Likes';
}
</script>
and:
onclick="myF1()"
But then only the last Like on the page gets updated with click, no matter which Like button I click.
OK, I've made it work:
Here's our Flask route:
#app.route('/ulk')
def ulk():
ppp = request.args.get('p', 0, type=int)
lpost = Post.query.filter_by(id=ppp).first()
lpost.upvotes += 1
db.session.commit()
return jsonify(result=ppp)
And here's our HTML page with some jQuery:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>
<body>
<script type=text/javascript>
$(function() {
$('a#like').bind('click', function() {
$.getJSON('/ulk', {
p: pid
}, function(data) {
$("#result2").text(data.result);
});
return false;
});
});
</script>
<br/><br/>
{% for p in posts %}
{% if p.upvotes %}
{% set pupvotes = p.upvotes %}
{% else %}
{% set pupvotes = 0 %}
{% endif %}
<p>{{ p.author.username }} says: <b>{{ p.body }}</b>
<a href="#" id=like>
<button id="{{ p.id }}" onclick="pid={{ p.id }};pvts = {{ pupvotes }} +1;myF1();">{{ pupvotes }} Likes</button>
</a>
</p>
<script type=text/javascript>
function myF1() {
$( "#" + pid ).text(pvts + ' Likes');
$('#' + pid).on('click', function() {
$(this).prop('disabled', true);
});
}
</script>
{%endfor%}
<br/>
<span id=result2>...</span>
</body>
</html>
You are close, however, as #MartijnPieters pointed out, you still need to communicate with the backend to update the number of likes for the post. To do so, slightly change your HTML to include a button to update the likes with a class and id. The id will be the same as the post id, and the class will be generic. Then, utilize jquery with ajax after creating a script.
First, in the Python backend, create a route to handle the updating of the likes for a post:
#app.route('/update_like')
def update_likes():
_id = int(flask.request.args.get('post_id'))
#Do something to update the database
return flask.jsonify({'success':'True'})
I suggest returning a jsonified response so that you can handle errors that may occur, such as a user liking a post twice. If you discover that that is the case, then you could return flask.jsonify({'success':'False'}) and handle that accordingly in the frontend.
Then, in the HTML:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>
<div class='post_wrapper'>
{%for p in posts%}
<div id='post_{{post.id}}'>
<p>{{p.author.username}} says:</p>
<p>{{p.body}}</p>
{%if p.upvotes%}
<button class='upvote' id='upvote_{{p.id}}'>Like <span id='upvotes_{{p.id}}'>{{p.upvotes}}</span></p>
{%else%}
<button class='upvote' id='upvote_{{p.id}}'>Like <span id='upvotes_{{p.id}}'>0</span></p>
{%endif%}
</div>
{%endfor%}
</div>
<script>
$(document).ready(function(){
$('.post_wrapper').on('click', '.upvote', function(){
var post_id = this.id.match('\\d+');
$.ajax({
url: "/update_like",
type: "get",
data: {post_id: post_id},
success: function(response) {
if (response.success === 'True'){
var like_val = parseInt($('#upvotes_'+post_id).text()) + 1;
$('#upvotes_'+post_id).text(like_val.toString());
}
else{
alert('You already liked that post!');
}
}
});
});
});
</script>
</html>

Categories