how to get an array element with javascript variable in django template? - javascript

i`m creating a slider so i want to get an element of template array in Django.
my HTML file is:
<div id="sideBar_mostVisited_control">
<a href="">
<p>
{{ mostVisited_names.0 }}
</p>
</a>
<div>
<p>
1
</p>
</div>
<button type="button" id="mostVisited_arrowRight">
<img src="{% static 'icons/base/arrowRight.png' %}" id="mostVisited_arrowRight">
</button>
<button type="button" id="mostVisited_arrowLeft">
<img src="{% static 'icons/base/arrowLeft.png' %}" id="mostVisited_arrowLeft">
</button>
</div>
<div id="sideBar_mostVisited_images">
<div>
{% for image in mostVisited_images %}
<img src="{{ image }}">
{% endfor %}
</div>
</div>
i want to change name when its image changed. my jQuery file is:
var index=$('#sideBar_mostVisited_control div p').html();
$('#sideBar_mostVisited_control div p').html(index+1);
$('#sideBar_mostVisited_control a p').html("{{ mostVisited_names.index }}");
but index is not recognized in {{ mostVisited_names.index }}.
what can i do?

The problem :
Since the JS file is static, you can't put Django variables into it.
A solution :
A way to resolve this situation is to "store" Django variables needed for your js in your html. Afterward you can grab it and use it in your js script !
Some code :
<script type="text/javascript">
// "store" variables from Django in the body
$('body').data('name_index', {{mostVisited_names.index}});
</script>
Then in your JS, get the value from the datamap:
var index=$('#sideBar_mostVisited_control div p').html();
$('#sideBar_mostVisited_control div p').html(index+1);
$('#sideBar_mostVisited_control a p').html($('body').data('name_index'));

Related

How can I re-run a Django For Loop inside a HTML Div using Javascript on Click Event

I have a HTML div like this,
<div class="coment-area ">
<ul class="we-comet">
{% for j in comment %}
<div id="delete_comment{{j.id}}" class="mt-3">
{% if j.post_id.id == i.id %}
<li >
<div class="comet-avatar">
{% if j.user_id.User_Image %}
<img class="card-img-top" style=" vertical-align: middle;width: 50px;height: 50px;border-radius: 50%;" src= {{ j.user_id.User_Image.url }} alt="">
{% else %}
<img class="card-img-top" style=" vertical-align: middle;width: 60px;height: 60px;border-radius: 50%;" src="static\images\resources\no-profile.jpg">
{% endif %}
</div>
Inside of it is a For Loop that is executed when the page is first loaded.
Below this For Loop is a Comments Button
<div >
<button type="submit" onclick="comment_save(event,{{i.id}})" class= "my-2 ml-2 px-2 py-1 btn-info active hover:bg-gray-400 rounded ">Comment</button>
</div>
</div>
</li>
</ul>
</div>
Whenever this button of Comments is clicked, a function in Javascript is called which is defined below,
function comment_save(event,post_id)
{
var comment_value=$("#comment_value"+post_id).val();
var user_id=$("#comment_user_id"+post_id).val()
postdata={
"comment_value":comment_value,
"user_id":user_id,
"post_id":post_id
}
SendDataToServer("readmore",postdata,function()
{
alert()
})
$("#comment_value"+post_id).val(" ")
<! --- document.location.reload().. Something here that refresh that for loop --->
}
What I want is this that whenever the button is clicked, it re-executes that for Loop inside my main div without having to refresh the page. I have been trying to do this for two days but could not find any solution to this. Can anyone help me in doing this?
The Django Templating Language is executed server-side. That means the client (browser, running Javascript) has no access to it whatsoever.
Some of your options are:
Do everything back-end: Re-render the template (which you said don't want to do).
Do everything front-end: You could have your view function return the data used in your template loop and re-implement it in your front-end (but that makes the original template loop kind of pointless).
Hybrid: Return the data for only the new comment in your response and add it to the list with Javascript.

Show and hide text of different posts

I have several posts each of them composed of three parts : a title, a username/date and a body. What I want to do is to show the body when I click on either the title or the username/date and hide it if I click on it again. What I've done so far works but not as expected because when I have two or more posts, it only shows the body of the last post even if I click on another post than the last one. So my goal is only to show the hidden text body corresponding to the post I'm clicking on. Here is my code:
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Test page{% endblock %}</h1>
<a class="action" href="{{ url_for('main_page.create') }}">New</a>
{% endblock %}
{% block content %}
{% for post in posts %}
<article class="post">
<header>
<script language="JavaScript">
function showhide(newpost)
{var div = document.getElementById(newpost);
if (div.style.display !== "block")
{div.style.display = "block";}
else {div.style.display = "none";}}
</script>
<div onclick="showhide('newpost')">
<h1>{{ post['title'] }}</h1>
<div class="about">by {{ post['username'] }} on {{ post['created'].strftime('%d-%m-%Y') }}</div>
</div>
</header>
<div id="newpost">
<p class="body">{{ post['body'] }}</p>
</div>
</article>
{% if not loop.last %}
<hr>
{% endif %}
{% endfor %}
{% endblock %}
Of course I looked for a solution as much as I could but I'm kind of stuck plus I'm a complete beginner in HTML/JS/CSS. And one last thing, I'm currently using Python's framework Flask. Thank you by advance.
You need to give each of your posts a unique id for your approach to work.
Change your code to
<div id="{{post_id}}">
<p class="body">{{ post['body'] }}</p
</div>
where post_id is that post's unique id e.g. its id in the database you are using that you pass to the template in your view. Then, change the call to the onclick event handler to
<div onclick="showhide('{{post_id}}')">
If you don't have a unique id you can also use the for loop's index: replace all post_id instances above with loop.index. See Jinja's for loop docs for more information.

Get attribute from a specific element of a class

Basically I have to develop a Tic-Tac-Toe game, here is the HTML file which I can't rewrite only reformat a bit, but the idea should stay the same.
{% block content %}
<nav class="navbar fixed-top navbar-light">
<button id="retry-button" class="btn btn-success">Try again?</button>
Reset settings
</nav>
<div id="game-board" class="mb-3" data-row-num="{{ row_num }}" data-col-num="{{ col_num }}" data-win-size="{{ win_size }}">
{% for row in range(row_num) %}
<div>
{% for col in range(col_num) %}
<div class="game-cell"
data-coordinate-x="{{ col }}"
data-coordinate-y="{{ row }}"></div>
{% endfor %}
</div>
{% endfor %}
</div>
{% endblock %}
As you can see i have a game-cell class which contains by default 9 elements. I would like to return the data-coordinate-x and data-coordinate-y when I click one of the game-cells. I had a previous try but if I clicked it returned all of the blocks not just the one i clicked on. I have to write it in Js. If you can point me in the right direction that's more than enough for me.
Thanks!
If I understood correctly, you need to access data attributes of your game-cell element. In order to do this, you need to select the element by some ID or class. I have modified your code a little to make it run inside stackoverflow`s platform. I have added an ID which i called "unique" and I also set some values into your coordinate-x and y data attributes. Please review the code bellow and see how I managed to get those data attributes. It's important to notice that this is not the only way to access them.
var gamecell = document.getElementById('unique');
console.log(gamecell.dataset.coordinateX);
console.log(gamecell.dataset.coordinateY);
<nav class="navbar fixed-top navbar-light">
<button id="retry-button" class="btn btn-success">Try again?</button>
Reset settings
</nav>
<div id="game-board" class="mb-3" data-row-num="{{ row_num }}" data-col-num="{{ col_num }}" data-win-size="{{ win_size }}">
<div>
<div class="game-cell" id="unique"
data-coordinate-x="172"
data-coordinate-y="273"></div>
</div>
</div>
Its also possible to get these values using the getAttribute method.
var elem = document.getElementById('unique');
var coordX = elem.getAttribute('data-coordinateX');
var coordY = elem.getAttribute('data-coordinateY');
Please, take a look at this page, it explains some aspects of data attributes:
https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes
Simply access your clicked game-cell by: (it will find the clicked coordinateX and coordinateY)
document.querySelectorAll('.game-cell').forEach((game) => {
game.addEventListener('click',function(event){
console.log(game.dataset.coordinateX);
console.log(game.dataset.coordinateY);
});
});
you must to get your element by class name or id(add an id)
than you can get its attributes like this
let gameCell = document.getElementById('game-cell-id');// id for example
gameCell.getAttribute('data-coordinate-x')

Count images inside a div, then add another/new img src (file)

I'm currently using Flask for my back-end coding, and working on my front-end as of now. Below are the images uploaded on the server. Now I need to edit those images, like I need to upload another image or change the existing image. We're using a cropper.js on this one, and I don't know how will I manage this one because I'm not that good when it comes to front-end scripting like javascript/jquery/ajax. Maximum images can upload is up to 8 images, I need to count the total existing images, then add another img src file, for example if I had 3 images, then I need to show 5 more img src file for adding new images. Any help will do and will be appreciated. Below is my code on HTML with Jinja2 template.
<div class="col-xs-3">
<label class="rs-thumb rs-thumb-cover">
<div class="rs-thumb-content" id="inputImage1-wrap"><img src="{{ resource.image_url }}" alt="" id="inputImage1-pic" width="100%"><i class="fa fa-picture-o"></i>
<span class="rs-cover">Cover</span>
</div>
</label>
</div>
{% for imgs in resource.images[1:] %}
<div class="col-xs-3">
<label class="rs-thumb rs-thumb-cover">
<div class="rs-thumb-content" id="inputImage1-wrap"><img src="{{ imgs.image }}" alt="" id="inputImage1-pic" width="100%"><i class="fa fa-picture-o"></i>
<!-- <span class="rs-cover">Cover</span> -->
</div>
</label>
</div>
{% endfor %}
Image for Edit Module on front-end
Html + JQuery solution, mostly tested so should work.
HTML
<div class="imgBox">
<!-- Your content will appear here -->
</div>
JQuery
// Get the amount of images on the current page
var amountOfImg = $("img").length;
var amountToCount = 8;
for (var i = 0; i < amountToCount - amountOfImg; i++) {
$(".imgBox").append("<input type='file' name='fileInput' /> <b id='removeImg'>Remove</b>")
}
$("#removeImg").click(function() {
// When the user clicks on the #removeImg text, find the closest "img" element and remove it.
$(this).closest("img").remove();
});

Django template showing \u200e code

Hey guys I am beyond frustrated/exhausted trying to fix this unicode code \u200e showing in my web page. I tried everything I can think of. Here is what my page looks like, its data scraped articles from news.google.com and shown on my page with the time submission (the time submission is where the \u200e pops up everywhere)
http://i.imgur.com/lrqmvWG.jpg
I am going to provide my views.py, my articles.html (the page in the picture that is set up to display everything), and header.html (for whatever reason. But this is the parent template of articles.html for the CSS inheriting). Also, I researched and know that the \u200e is a left-to-right mark and when I inspect the source in news.google.com, it pops up in the time submission element as
‎
like so:
<span class="al-attribution-timestamp">‎‎51 minutes ago‎‎</span>
I tried editing the views.py to encode it using .encode(encoding='ascii','ignore') or utf-8 or iso-8859-8 and a couple other lines of code I found researching deep on google but it still displays \u200e everywhere. I put it in so many different parts of my views.py too even right after the for loop (and right before + after it gets stored as data in the variable "b" and its just not going away. What do I need to do?
Views.py
def articles(request):
""" Grabs the most recent articles from the main news page """
import bs4, requests
list = []
list2 = []
url = 'https://news.google.com/'
r = requests.get(url)
sta = "‎"
try:
r.raise_for_status() == True
except ValueError:
print('Something went wrong.')
soup = bs4.BeautifulSoup(r.text, 'html.parser')
for listarticles in soup.find_all('h2', 'esc-lead-article-title'):
a = listarticles.text
list.append(a)
for articles_times in soup.find_all('span','al-attribution-timestamp'):
b = articles_times.text
list2.append(b)
list = zip(list,list2)
context = {'list':list, 'list2':list2}
return render(request, 'newz/articles.html', context)
articles.html
{% extends "newz/header.html" %}
{% block content %}
<script>
.firstfont (
font-family: serif;
}
</script>
<div class ="row">
<h3 class="btn-primary">These articles are scraped from <strong>news.google.com</strong></h3><br>
<ul class="list-group">
{% for thefinallist in list %}
<div class="col-md-15">
<li class="list-group-item">{{ thefinallist }}
</li>
</div>
{% endfor %}
</div></ul>
{{ list }}
{% endblock %}
header.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Sacred Page</title>
<meta charset="utf-8" />
{% load staticfiles %}
<meta name="viewport" content = "width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="{% static 'newz/css/bootstrap.min.css' %}" type = "text/css"/>
<style type="text/css">
html,
body {
height:100%
}
</style>
</head>
<body class="body" style="background-color:#EEEDFA">
<div class="container-fluid" style="min-height:95%; ">
<div class="row">
<div class="col-sm-2">
<br>
<center>
<img src="{% static 'newz/img/profile.jpg' %}" class="responsive-img" style='max-height:100px;' alt="face">
</center>
</div>
<div class="col-sm-10">
<br>
<center>
<h3><font color="007385">The sacred database</font></h3>
</center>
</div>
</div><hr>
<div class="row">
<div class="col-sm-2">
<br>
<br>
<!-- Great, til you resize. -->
<!--<div class="well bs-sidebar affix" id="sidebar" style="background-color:#E77200">-->
<div class="well bs-sidebar" id="sidebar" style="background-color:#E1DCF5">
<ul class="nav nav-pills nav-stacked">
<li><a href='/'>Home</a></li>
<li><a href='/newz/'>News database</a></li>
<li><a href='/blog/'>Blog</a></li>
<li><a href='/contact/'>Contact</a></li>
</ul>
</div> <!--well bs-sidebar affix-->
</div> <!--col-sm-2-->
<div class="col-sm-10">
<div class='container-fluid'>
<br><br>
<font color="#2E2C2B">
{% block content %}
{% endblock %}
{% block fool %}
{% endblock fool %}
</font>
</div>
</div>
</div>
</div>
<footer>
<div class="container-fluid" style='margin-left:15px'>
<p>Contact | LinkedIn | Twitter | Google+</p>
</div>
</footer>
</body>
</html>
If you want, you can use replace() to strip the character from your string.
b = articles_times.text.replace('\u200E', '')
The reason that you see \u200E in the rendered html instead of ‎ is that you are including the tuple {{ thefinallist }} in your template. That means Python calls repr() on the tuple, and you see \u200E. It also means you see the parentheses, for example ('headline' '\u200e1 hour ago')
If you display the elements of the tuple separately, then you will get ‎ in the template instead. For example, you could do:
{% for headline, timeago in list %}
<div class="col-md-15">
<li class="list-group-item">{{ headline }} {{ timeago }}
</li>
</div>
{% endfor %}

Categories

Resources