Dynamic creation of methods/objects with jinja/javascript - javascript

I've got this working code right now,
For example' sake I made a straight forward piece of code:
{% for t in things %}
<button id="name{{t.id}}">{{ t.text }}</button>
<script>
$('#name{{ t.id }}').on('click', function() {
console.log('testingscript');
</script>
{% endfor %}
But since this is not a good way to mix html/js I'd like to either put the js in a seperate file or a jinja solution..
EDIT: The q is how do i do this?

That is a lot of script tags. Instead, try something like this in the head:
<script>
$('button.mybutton').on('click', function() {
console.log($(this).text());
});
</script>
and the body has
{% for t in things %}
<button class="mybutton" id="name{{t.id}}">{{ t.text }}</button>
{% endfor %}
Therefore, whenever a button with class mybutton is clicked, the single script writes its contained text to the console. The id isn't what is invoking the callback, the class is.

Related

About using jinja templating in JS file

I have been using a template in which there's images of previous and next button is in JavaScript file. The Framework I'm using is Django, is there any solution to use jinja templating/rendering for these images in JS file.
JS code:
$(".active-banner-slider").owlCarousel({
items:1,
autoplay:false,
autoplayTimeout: 5000,
loop:true,
nav:true,
navText:["<img src={% static 'img/banner/prev.png' >","<img src={% static 'img/banner/next.png' %}>"],
dots:false
});
I used same static method with html files and it worked, I don't know if this method does even work with JS file or not? if it does what would be the correct way?
Yes, you can generate a JS component of a web page using the Django template processor, or Jinja if you prefer. You do, however, need to make sure that the JS is generated in the correct context (surrounded by appropriate tags, in the right place in your rendered output). You also have to be careful to code your JS using { { and } } (significant spaces!) never {{.
If you use "view page source" and your browser's debugging tools, you will probably spot what you are doing wrong.
My site base template has a block onready_js like this:
<script type="text/javascript"> $(document).ready( function() {
{% block onready_js %}{% endblock onready_js %}
});
</script>
into which you can inject bits of JS to be executed when the page becomes ready, like this (ignore the irrelevant details, apart from the use of {{...}} and {% if ... %} etc. Absent any block definition, the base template generates a null $(document).ready( function() { });
{% block onready_js %}
{% if form or POST_name %}
// activate the button column to POST to this target with this name
var buttons = $('button.MyFilterSelectButton');
buttons.attr('type','submit').attr('name','{{POST_name}}')
buttons.click( function(event){
$('#id_{{POST_name}}').val( $(this).attr('value') );
/* stuff deleted */
$('.MyFilterSelectCol').show();
{% else %}
// hide the button column which doesn't do anything useful
$('.MyFilterSelectCol').hide();
{% endif %}
{% endblock onready_js %}

Using a variable to for loop using django

I'm very new to python and django framework. I'm facing a minor issue of not being able to assign a variable to my for loop.
In my html file there are buttons and a list (rendered using a loop).
for ex:
Buttons
<li><a class="layer-item" href="#" onclick="selectLayer('base')" title="Base layer">Base layer</a></li>
<li><a class="layer-item" href="#" onclick="selectLayer('soil')" title="Soil layers">Soil layers</a></li>
Inside script tags i'm updating the variable value as
<script>
var layerType = "";
function selectLayer(layer){
layerType = layer;
}
</script>
Also i have a loop like following in the same html file
{% for layer in base %}
<div class="col-4">
<span class="base-layer-title d-block">{{layer.title}}</span>
</div>
{% endfor %}
Here i want to replace base according the button clicked.
For ex:
<a class="layer-item" href="#" onclick="selectLayer('soil')" title="Soil layers">Soil layers</a>
Clicking on the above button should make the for loop as
{% for layer in soil %}
<div class="col-4">
<span class="base-layer-title d-block">{{layer.title}}</span>
</div>
{% endfor %}
From i read you can do something like this to assign a value to a variable.
{% with name="World" %} But not sure how to implement it in my issue.
Any help is appreciated
Also i have a loop like following in the same html file
{% for layer in base %}
{{layer.title}} {% endfor %}
Here i want to replace base according the button clicked.
In short, Django is a server-side framework and it cannot directly respond to any client-side activity. You cannot do it effectively without client-side libraries like React, JQuery, etc.
Workaround 1
You can make a new request to the server on click and re-render the entire page with new parameters.
urls.py
path('my_pattern/<slug:my_layer>', myview)
views.py
def myView(request, my_layer):
# your logics
base = get_layer_data(my_layer) # <-- logic to get list dynamically
return render(request, 'my_template.html', context={'base':base})
my_template.html
{% for layer in base %}
<div class="col-4">
<span class="base-layer-title d-block">{{layer.title}}</span>
</div>
{% endfor %}
...
<a class="layer-item" href="/my_pattern/soil" title="Soil layers">Soil layers</a>
<a class="layer-item" href="/my_pattern/some_other_layer" title="Some other layers">Soil layers</a>
...
The base will have dynamically generated data on every request.
Workaround 2
You can, however, render all the data on the page and control it using collapse in bootstrap https://getbootstrap.com/docs/4.5/components/collapse/

JavaScript Function Doesn't Work On Django

When the first page is loaded, I want the user to come across all the music, but if he selects a list from RadioButton, I only want the music in that list, but the javascript function doesn't work.
Let me add that I don't normally know JavaScript, but I need to use it.
<div style = "margin-top : 100px;"class = "container">
{% for table in tables %}
<input type="radio" name="list1" onclick="mL('{{table}}')"> {{table}}
{% endfor %}
<div align="center">
<audio class="my_audio" controls="controls" autoplay="autoplay" style="width:500px;"></audio>
<ul>
{% for table in tables %}
{% for music in musics %}
<li style="list-style-type:None">
<a id="{{table}}" href="javascript:void(0);" onclick="playSong('{{music}}')">{{music}}</a>
</li>
{% endfor %}
{% endfor %}
{% for music in musics %}
<li style="list-style-type:None">
<a id="default" href="javascript:void(0);" onclick="playSong('{{music}}')">{{music}}</a>
</li>
{% endfor %}
</ul>
</div>
</div>
<script> function mL(x)
{
{% for table in tables %}
if (x=={{table}})
document.getElementById("{{table}}").style.display="block";
document.getElementById("default").style.display="none";
{% endfor %}
else
document.getElementById("{{table}}").style.display="none";
document.getElementById("default").style.display="block";
return;
}
</script>
This isn't a Django issue, it's purely about the JavaScript (or should be).
Here are some problems with your code:
In HTML, the id attribute should be unique in the document. You seem to have many <a> tags with the same id. Use the class attribute, or even better use your own data attribute like data-table.
You can code generate JavaScript using Django template tags like you have, but I think it's a bad idea because it's very hard to reason about how the code will work. Don't use {% for %} inside the <script> block.
JavaScript doesn't use spaces for code blocks like Python does. You need to use braces { } instead.
Once those things are fixed, use the debugging console in your browser (F12 in Firefox and Chrome). It will let you see any syntax errors, and you can even run code in the console to see how things like document.getElementById work.

How to trigger the rendering of a bokeh plot programatically?

I have a lot of plots on my page and I don't want them to fire all on page load, but trigger them as the user scrolls down, or after a while.
I use the components module, so I'm unsure where to put a setTimeout or something like that.
in Django view I have:
from bokeh.resources import CDN
from bokeh.embed import components
script, div = components(plot.make_box_plot(), CDN)
and then in tag:
{% if div %}
{{ div | safe }}
{% endif %}
{% if script %}
{{ script | safe }}
{% endif %}
Does bokeh have some api for this?
This doesn't work as I get a js syntax error:
<script>
window.plot_script = {{ script }}; // and then use it in a js file inside setTimeout
</script>

Jinja2 and HTML Div tag

I have an html file which I am rendering with jinja2 in python, which has some div sections like
<div id="imdb">
{{imdb_output}}
</div>
Now even when the value of imdb_output variable is returned None from its function in python file, as expected HTML still displays the div section although with no content, but with its css!
But what do I need to do so that even the empty div section does not appear if imdb_output has no values to display?? Do I need to add some JS?
Please help!
Here is a screenshot of the problem:-
http://imgur.com/qVfk2
use this
{% if imdb_output %}
<div id="imdb">
{{imdb_output}}
</div>
{% endif %}
You should read jinja2 documentation for template designers
Just check if imdb_output is empty:
{% if imdb_output %}
<div id="imdb">
{{imdb_output}}
</div>
{% endif %}

Categories

Resources