Passing context variable from template to JavaScript file - javascript

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 %}

Related

How to transmit Django variables to a Js file

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.

In a Jekyll site using Disqus I get a Content Security Policy error

I built a site using Jekyll hosted on Github Pages:
site,
repo
Jekyll _config.yml:
# Comments
disqus_shortname: bad3r
Disqus configuration in _layout/post.html :
<div class="comments-wrapper">
<div id="disqus_thread"></div>
<script>
/**
* RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
* LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables
*/
var disqus_config = function() {
this.page.url = '{{ absolute_url }}{{ page.url }}'; /*Replace PAGE_URL with your page's canonical URL variable*/
this.page.identifier = '{{ page.url }}'; /*Replace PAGE_IDENTIFIER with your page's unique identifier variable*/
};
(function() { /* dont endit below this line */
var d = document,
s = d.createElement('script');
/* https://bad3r.disqus.com/embed.js */
/* 'https://{{ site.disqus_shortname }}.disqus.com/embed.js' */
s.src = 'https://{{ site.disqus_shortname }}.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the comments powered by Disqus.</noscript>
</div>
<!-- /.comments-wrapper -->
I have enabled comments in the post Jekyll front-matter:
---
layout: post
title: "Welcome to my new blog"
date: 2018-05-25
excerpt: "working on building my blog, here is an example post"
image: "/images/workProgress.jpg"
comments: true
---
link to the post where disque shows an error message here, code on github here
if you open the console on the page you will see the error:
Content Security Policy: The page’s settings blocked the loading of a resource at self (“script-src”).
i didnt have a Content Security Policy when i first encountered the error
but i tried to implement one and i added the CSP in the _includes/head.html :
<!-- CSP(Content Security Policy) -->
<META HTTP-EQUIV='Content-Security-Policy' CONTENT="default-src 'self' ; script-src 'self' 'unsafe-inline' *.disqus.com a.disquscdn.com requirejs.org www.google-analytics.com; style-src 'self' 'unsafe-inline' a.disquscdn.com; img-src 'self' *; media-src 'self' ; frame-src disqus.com;">
and the _includes/head.html is included in the start of all _layouts/*.html
I have no idea why this error still occurs.
Looks like you may be entering an incorrect this.page.identifier. Here is a copy of the Disqus code on a working blog:
_includes/disqus.html:
{% if page.comments %}
<div class="container">
<div class="row">
<div class="col-lg-8 col-md-10 mx-auto">
<div id="disqus_thread"></div>
<script>
/**
* RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
* LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables*/
var disqus_config = function () {
this.page.url = "{{ site.url }}{{ page.url }}"; // Replace PAGE_URL with your page's canonical URL variable
this.page.identifier = "{{ page.id }}"; // Replace PAGE_IDENTIFIER with your page's unique identifier variable
};
(function() { // DON'T EDIT BELOW THIS LINE
var d = document, s = d.createElement('script');
s.src = 'https://DIRSETUP.disqus.com/embed.js'; // YOUR ACCOUNT
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the comments powered by Disqus.</noscript>
</div>
</div>
</div>
{% endif %}
The above code you'll need to copy from Disqus because it will include the URL for the site setup but in your code you have it as variable from the config. I think you may be having an issue by the reference so try changing '{{ page.url }}' to "{{ page.id }}". In the directory _layouts I just pass the include of {% include disqus.html %} to post.html. In _posts I have a template of:
---
layout: post
published: false
comments: true
title: ""
excerpt: ""
date:
categories: ['']
tags: ['', '']
---
If you want the comment count you could also add:
<script id="dsq-count-scr" src="//{{ disqusShort }}.disqus.com/count.js" async></script>
before the closing </body> tag to _layouts/default.html. Then you can add disqusShort: username to _config.yml. In _layouts/post.html add:
{% if page.comments %} • 0 Comments{% endif %}
When I set mine I referenced "Adding Disqus to a Jekyll Blog". I get no errors so hope this helps.

Javascript enabling buttons works in JSFiddle but not in browser - Flask

I am using Python/Flask to develop a web app.
In a page I want to have some buttons disabled initially, and then enabled if a function is called.
In JSFiddle for example something like this works:
JSFiddle
However, if in my index.html file I have something like this:
{%- extends "base.html" %}
{% import "bootstrap/utils.html" as utils %}
{% block content %}
<h1>Three buttons!</h1>
<div id="audio">
<p>
<button id=startRecord onclick="startRecording()">Start</button>
<button id=stopRecord onclick="stopRecording()">Stop</button>
<button id=submitRecord onclick="submit()">Submit</button>
</p>
<p>
<audio id=recordedAudio></audio>
</p>
<p>
<a id=audioDownload></a>
</p>
</div>
{% endblock %}
{% block scripts %}
<script src="{{url_for('static', filename='js/recordtest.js')}}"></script>
{% endblock %}
Where recordtest.js is:
startRecord.disabled = false;
stopRecord.disabled = true;
submitRecord.disabled = true;
function startRecording() {
stopRecord.disabled = false;
}
All buttons start as enabled and are not changed with the function.
I am using Chrome.
Put following lines in your js files in a self executing javascript closure, something like written below.
$(function(){
startRecord.disabled = false;
stopRecord.disabled = true;
submitRecord.disabled = true;
function startRecording() {
stopRecord.disabled = false;
}
})();
Also, put type="text/javascript" in script tag for neatness.
Firstly put an alert in startRecording function to confirm that it is actually getting called, try the code like this
document.getElementById("startRecord").disabled = false;
document.getElementById("stopRecord").disabled = true;
document.getElementById("stopRecord").style.backgroundColor = '#aaa'; // or any color you need to make it look like its hidden
document.getElementById("submitRecord").disabled = true;
document.getElementById("submitRecord").style.backgroundColor = '#aaa'; // or any color you need to make it look like its hidden
function startRecording() {
alert();
document.getElementById("stopRecord").disabled = false;
document.getElementById("stopRecord").style.backgroundColor = '#FFF'; // or any color you need to make it look like its not hidden
}
Also Verify that your java-script files are properly linked, that's probably the cause

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>

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