How to transmit Django variables to a Js file - javascript

As you can see in the code below, I have imported a <script type="text/javascript" src="{% static 'js/posts_lazy_loading.js' %}"></script> to my Index.html.
But there are Django variables in that JS file. like: {{ sizes }} and {{ urlsPosts }}, they go from Views.py to the Index.html.
Unfortunately Django doesn't see these variables in the JS file if I keep the JS as a separate file.
If I copy paste the JS right to the HTML without separating - everything works well.
How can I include these Django variables into the separate Js file?
Index.html:
<html>
{% load static %}
{% include 'head.html' %}
<body>
<header>
</header>
</body>
<footer>
<script type="text/javascript" src="{% static 'js/posts_lazy_loading.js' %}"></script>
</footer>
</html>
Views.py:
def index(request):
posts = Post.objects.all()
sizes = ''
urlsPosts = ''
for i in range(0, len(posts)):
if i == len(posts):
sizes = sizes + str(posts[i].thumbnail.width) + 'x'
sizes = sizes + str(posts[i].thumbnail.height)
urlsPosts = urlsPosts + posts[i].thumbnail.url
else:
sizes = sizes + str(posts[i].thumbnail.width) + 'x'
sizes = sizes + str(posts[i].thumbnail.height) + ' '
urlsPosts = urlsPosts + posts[i].thumbnail.url + ' '
return render(request,'index.html',{'posts':posts, 'sizes':sizes, 'urlsPosts':urlsPosts)
posts_lazy_loading.js:
var images = document.getElementsByClassName('cover_main_page'),
posts = document.getElementsByClassName('post'),
descriptions = document.getElementsByClassName('description'),
description_height = descriptions[0].clientHeight;
post_content = document.getElementsByClassName('post_content'),
loading = document.getElementsByClassName('dots_portoflio'),
sizes = "{{ sizes }}",
sizeslist = sizes.split(" "),
urlsPosts = "{{ urlsPosts }}",
urlslist = urlsPosts.split(' '),
ratios = [],
viewport_width = document.documentElement.clientWidth,
newwidth = 0,
margin = 3, //each post has 3vw margin left and 3vw margin right
mobile = 0,
mobilewidth = 94;
.... a lot of code here ....

Yup, django will generate this line as follows:
It won't open the JS as this will ask the browser to load the JS, to use django inside your JS, you have one of two options
Use {%include 'JSFILE'%} but in this case, your JS file shall be in the templates folder
Put the JS code itself in your HTML template.

Related

Passing context variable from template to JavaScript file

This thread here discussed using variables in inline JavaScript in templates. If I have separate .js files containing scripts, sitting in static folder, such as following:
utils.js
const createButton = (buttonCount) => {
containerId = "myContainerId"
container = document.getElementById(containerId)
for (var i = 0; i < buttonCount; i++) {}
newButton = document.createElement("button")
newButton.value = "Test"
newButton.id = "testButton" + i
container.appendChild(newButton)
}
}
createButton(buttonCount)
mytemplate.html
{% extends "base.html" %}
{% load static %}
{% block title %}Testpage{% endblock %}
{% block content-main %}
<link href="{% static "css/mycss.css" %}" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.4.0/css/bulma.css" />
<div id="myContainerId"></div>
<script src="{% static 'js/utils.js' %}"> </script>
{% endblock %}
If I have a variable buttonCount passed into this template via a view function's context, how do I pass it to the utils.js file to be called by function createButton()?
views.py
def button_view(request):
...
buttonCount = 5
return render(request, 'mytemplate.html', {'buttonCount': buttonCount})
There can be a few ways:
Using Input Field
<input id="buttonCount" value = "{{buttonCount}}" style="display:none;">
Then read value of element with id= buttonCount in utils.js.
Inline Script **Not Suggested,Use Document.onload instead.
<script>
set_button_count({{buttonCount}});
</script>
But this will create a problem when your utils.js is not loaded yet.
document.onload
Place the script source in <head></head>
<script src="{% static 'js/utils.js' %}" defer> </script>
<script>
document.addEventListener('onload',function(
{set_button_count({{buttonCount}});
})
</script>
set_button_count() is to be placed in utils.js
Defer will ask browser to only fire document load when utils.js
is complete and it will be fetched and loaded after the document is
loaded.
Warning: Inline scripts are to be used with strict CSP (Content Security Policy).Any inline script can be given a src as nonce.
CSP can be done on Server Side on apache or Nginx which are very common web server/reverse proxy or you can also mention the same in HTML if you don't have control on that.
<meta http-equiv="Content-Security-Policy"
content="default-src 'self';
script-src 'self' 'nonce-{{nonce}}';">
and this nonce can be generated something like this:
import random,base64
def usersession_processor(request):
user = request.user
unbaked_nonce = '%32x' % random.getrandbits(16*8)
unbaked_nonce = unbaked_nonce.encode('utf-8')
baked_nonce = base64.b64encode(unbaked_nonce)
baked_nonce = baked_nonce.decode('utf-8')
Then <script src="{{nonce}}"></script> can be used for safe inlines.
I don't think this is recommended but you could do something like this if you're using the django template context. Put the script at the bottom of the page and include the buttoncount as a Django Templating Language variable. I don't think it's recommended to mix Django template variables with javascript though.
You can put a new block in your 'base.html' file, at the bottom inside the body tag like this:
{% block inline_javascript %}
{% enblock inline_javascript %}
Then inside the page you want the function to run on you put the script inside the same tags at the bottom of that page outside the 'block content' like:
{% block inline_javascript %}
<script>
const createButton = ({{ buttonCount }}) => {
containerId = "myContainerId"
container = document.getElementById(containerId)
for (var i = 0; i < {{ buttonCount }}; i++) {}
newButton = document.createElement("button")
newButton.value = "Test"
newButton.id = "testButton" + i
container.appendChild(newButton)
}
}
</script>
{% enblock inline_javascript %}

Django and javascript - how to use the value of dropdown box to access the static image stored on server using the static tag

{% load static %} line 1
<html> line 2
<head> line 3
<meta charset="UTF-8"> line 4
</head>
<body>
<select id="ddlViewBy">
<option value="Pranamasana.jpg">Pranamasana</option>
</select>
<img id='cat' crossorigin="anonymous" height = "620" width = "620"/>
<button onclick = "myfun()">button</button>
<script>
function myfun() {
var e = document.getElementById("ddlViewBy");
var strUser = e.options[e.selectedIndex].value;
document.getElementById("cat").src = "{% static 'Pranamasana.jpg' %}"; line 16
}
</script>
</body>
</html>
Even though I have a drop down box I am hard coding the name of the image to be accessed in line 16.
I want to know the way if I can use the string 'struser' so that the image selected by user can be displayed without hard coding.
Any help would be appreciated and thanks in advance.
I am using django and this is a html page in my project
Django template executes your code before the javascript does so you can't really use the javascript concatenate string adding. So the best way is to use {% get_static_prefix %}
var staticUrl = "{% get_static_prefix %}"
var strUsr = e.options[e.selectedIndex].value;
document.getElementById("cat").src = staticUrl + strUsr

Use url_for of Flask in ajax function

I'm using Flask to create a little WebApp. In the file.py there is a
render_template('index.html', listaimmagini = listaimmagini)
where "listaimmagini" is a list of images name (According to Flask standard, the images are in static folder). Now in "index.html" i'm trying to show these images but seems that webapp doesn't found it in static folder (there is the usual broken icon for all my images)
Where is the error in my code?
Index.html
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
window.onload = function(){
var img = [];
{% for imagelego in listaimmagini %}
img.push("{{url_for('static', filename = imagelego)}}");
{% endfor %}
var parent = document.getElementsByClassName('scroll')[0];
if(img.length>0){
parent.style.overflowY = 'scroll';
for(i=0;i<img.length;i++){
image = document.createElement('IMG');
image.src = img[i][0];
image.alt = '';
image.setAttribute("class", "scegli");
parent.appendChild(image);
}
</script>

Javascript removes closing <a> tag?

I'm having a strange problem with one of my scripts. In the script parameters I'm trying to creating a link which makes up for the "read more" link on the frontend. Using the Jed Foster Read More script I'm trying to override the default "moreLink" and "lessLink" as was documented.
The default setting works perfect but when an override in the parameters is used somehow the closing tag is removed and the link is parsed empty.
This is how the script looks like:
<script type="text/javascript" src="{{ url('gantry-theme://js/readmore.js') }}"></script>
<script type="text/javascript">
var $j = jQuery.noConflict();
{% if particle.title %}
var $dropspeed = {{ particle.dropdownspeed|raw }};
var $collapsedheight = {{ particle.collapsedheight|raw }};
var $readmore = '"Read Moreeeee";
$j(document).ready(function() {
$j('.g-employee-text').readmore({
speed: $dropspeed,
collapsedHeight: $collapsedheight,
heightMargin: 30,
moreLink: 'Read More',
});
});
{% endif %}
</script>
And this is how its shown in the developer tools:
var $j = jQuery.noConflict();
var $dropspeed = 3000;
var $collapsedheight = 150;
var $readmore = '<a href="#">"Read Moreeeee";
$j(document).ready(function() {
$j('.g-employee-text').readmore({
speed: $dropspeed,
collapsedHeight: $collapsedheight,
heightMargin: 30,
moreLink: '<a href="#">Read More',
});
});
As you can see the closing tag is not available. The HTML looks as follows:
An empty link doing nothing.
Some notable information:
Read More script by Jed Foster
Gantry 5 framework
Hope someone can help me out here.
var $readmore = '"Read Moreeeee";
Why do you need the double quotes ?
Have you tried removing them ?
var $readmore = 'Read Moreeeee;

Django-compress not getting javascript

I am using Django-compress to compress my css and js files. Relevant snippets as follows.
settings
COMPRESS = True
COMPRESS_VERSION = True
COMPRESS_CSS = {
'css_all': {
'source_filenames': (CSS_ROOT + 'main.css',
CSS_ROOT + 'jquery-ui-1.7.1.custom.css',
CSS_ROOT + 'ui.daterangepicker.css',),
'output_filename': 'css/all_compressed.r?.css',
}
}
COMPRESS_JS = {
'js_all': {
'source_filenames': (JS_ROOT + 'daterangepicker.jQuery.js',
JS_ROOT + 'jquery-ui-1.7.1.custom.min.js',
JS_ROOT + 'jquery-1.3.1.min.js',),
'output_filename': 'js/all_compressed.r?.js',
}
}
COMPRESS_AUTO = True
template
{% load compressed %}
{% compressed_css 'css_all' %}
{% compressed_js 'js_all' %}
My CSS is loading fine but not the javascript. However, When I manually enter the JS sources in my template like this:
<script type="text/javascript" src="{{ JS_ROOT }}/js/jquery-1.3.1.min.js"></script>
<script type="text/javascript" src="{{ JS_ROOT }}/js/jquery-ui-1.7.1.custom.min.js"</script>
<script type="text/javascript" src="{{ JS_ROOT }}/js/daterangepicker.jQuery.js"></script>
I am able to get my javascript date widget working.
Could this be something to do with Django-compress messing the javascript code when it tries to compress it?
Django-compress is searching for CSS and JS files in MEDIA_ROOT so im sure there is a problem. Also u can specify prefix in extra_context

Categories