How to include javascript place holder in Jinja 2 place holder? - javascript

I am trying to embed this feature in my Flask app --> Scattered Polaroid Gallery
So, I have a template (Jinja2), where I am displaying a stack of images. To access the images I am using Flask's url_for() command which uses the symbol ---> {{}}. In the Javascript file which is supposed to dynamically load the images, the same symbol is being used i.e ----> {{}}. I want to know how can I use Javascript's {{}} along with Flask/Jinja 2 {{}}
Below is the Javascript function that replaces every instance of {{img}} with the actual file name.
function addPhotos() {
var template = select('#wrap').innerHTML;
var html = [];
var nav = [];
for (i=0; i<1; i++) {
var _html = template.replace('{{index}}', i)
.replace('img', data[i].img)
.replace('{{caption}}', data[i].caption)
.replace('{{desc}}', data[i].desc);
html.push(_html);
nav.push('<span id="nav_'+i+'" class="i" onclick ="turn(select(\'#photo_'+i+'\'))"> </span>');
}
html.push('<div class="nav">'+nav.join('')+'</div>');
select('#wrap').innerHTML = html.join('');
sort(random([0, data.length]));
}
<div class="mainPage" id="fullpage">
<div class="first section">
<div class="wrap" id="wrap">
<div class="photo photo_front" id="photo_{{index}}" onclick="turn(this)">
<div class="photo-wrap">
<div class="side side-front">
<p class="image">
<!-- <img src="photo/{{img}}"> -->
<img src="{{ url_for('static',filename='photo/{{img}}') }}">
<!-- .replace('{{img}}', data[i].img) -->
</p>
<p class="caption">{{caption}}</p>
</div>
<div class="side side-back">
<p class="desc">{{desc}}</p>
</div>
</div>
</div>
</div>
</div>
Above is the template that uses both Javascript and Jinja2 {{}}.
The following error is shown in the Chrome debug console.
Below is my folder structure for the Flask app -
PS - I have tried using relative path for the image folder instead of url_for() function for ex- <img src="../static/photo/{{img}}"> but it failed as well.
In that case, the following error was shown -
Please help.
EDIT -
After having used " , the following error resulted.

You need to escape the curly brackets by using quotes. Since you need to do this inside an html attribute src you will have to escape these quotes as well since quotes are used already inside the HTML attribute and the way to achieve that is byusing "
Take a look at the img tag src attribute below. If you want to escape the Jinja curly brackets that are not part of an HTML attribute then you can use jinja {% raw %} block (see how I surrounded {{caption}} )
<div class="mainPage" id="fullpage">
<div class="first section">
<div class="wrap" id="wrap">
<div class="photo photo_front" id="photo_{{index}}" onclick="turn(this)">
<div class="photo-wrap">
<div class="side side-front">
<p class="image">
<img src="{{ url_for('static',filename='photo/"{{img}}"') }}">
</p>
<p class="caption">{% raw %}{{'caption'}}{% endraw %}</p>
</div>
<div class="side side-back">
<p class="desc">{% raw %}{{desc}}{% endraw %}</p>
</div>
</div>
</div>
</div>
</div>

Related

How to execute a javascript function for every element in a list with Freemarker in Kotlin Ktor?

I'm calling an api with Kotlin and Ktor to get a book in return as json response. From this response I want to load the book cover in my frontend Freimarker .ftl file. I'm doing this call in javascript and write it to html.
When I'm calling the function like in my code shown, only the first element in the list get the book cover. The rest is empty.
The javascript is executed as inline code in html. I was excepting this function will be called for every new item in the list.
So what can I do to load the image for every element in my list?
index.ftl:
<#-- #ftlvariable name="books" type="kotlin.collections.List<com.nw.models.Book>" -->
<#import "_layout.ftl" as layout />
<#layout.header>
<#list books?reverse as book>
<div class="container-fluid">
<hr>
<div class="row justify-content-center">
<div class="card" style="width: 18rem;">
<img id="img-book" class="card-img-top" src="https://via.placeholder.com/128x209.png">
<div class="card-body">
<h5 class="card-title">${book.title}</h5>
<p class="card-text">${book.author}</p>
<input type="hidden" id="img-url" name="imageUrl" placeholder="${book.imageUrl}">
<script type="text/javascript">
(function() {
let a1 = document.getElementById("img-url").getAttribute("placeholder");
const image = document.getElementById("img-book");
image.src = a1;
})();
</script>
Go to Book
</div>
</div>
</div>
</div>
</#list>
<hr>
<p>
Create book
</p>
</#layout.header>
With the current DOM scripting approach the OP has to assure that the html render process actually creates a unique id value for each book item, thus img-url is not a valid id value for each book item. The same btw applies to each image element's img-book id value. And the placeholder attribute is not to be abused as data storage; the correct way is the usage of a custom data-* attribute.
One very easily could even implement an approach which is entirely free of id attributes and hidden input fields by just using both data related features the custom data-* attribute and the element's related dataset property.
<#-- #ftlvariable name="books" type="kotlin.collections.List<com.nw.models.Book>" -->
<#import "_layout.ftl" as layout />
<#layout.header>
<#list books?reverse as book>
<div class="container-fluid">
<hr>
<div class="row justify-content-center">
<div class="card" style="width: 18rem;">
<img data-book-cover-src="${book.imageUrl}" class="card-img-top" src="https://via.placeholder.com/128x209.png">
<div class="card-body">
<h5 class="card-title">${book.title}</h5>
<p class="card-text">${book.author}</p>
Go to Book
</div>
</div>
</div>
</div>
</#list>
<script type="text/javascript">
document
.querySelectorAll('img[data-book-cover-src]')
.forEach(elmNode =>
elmNode.src = elmNode.dataset.bookCoverSrc
);
</script>
<hr>
<p>
Create book
</p>
</#layout.header>

I want to write icon names inside the paths of images <img source=""> tag

I am using Dark Sky API to get weather information and icon parameter gives me cloudy, partly-cloudy, sunny etc. I saved icon images same name with icon names in the folder. I want to write this parameter inside the source path like
<img src="..\..\icon\weather\ $forecast.weatherDays[0].icon .png" height="300vh" width="300vw">
weather.html
<div id="day1"> <div id="icon"></div> </div>
<div id="day2"> <div id="icon"></div> </div>
weatherManager.js
document.querySelector("#day1 #icon").innerHTML=forecast.weatherDays[0].icon;
document.querySelector("#day2 #icon").innerHTML=forecast.weatherDays[0].icon;
How can I do that?
you need to add the image inside the div using the following code:
var forecast = {};
forecast.weatherDays = [];
forecast.weatherDays[0]= { icon :'partly-cloudy'};
forecast.weatherDays[1]= { icon :'image8-2'};
//console.log(forecast.weatherDays)
document.querySelector("#day1 #icon").innerHTML= '<img src="..\\..\\icon\\weather\\'+forecast.weatherDays[0].icon+'.png" height="300vh" width="300vw">';
document.querySelector("#day2 #icon").innerHTML= '<img src="https://blog.hubspot.com/hubfs/'+forecast.weatherDays[1].icon+'.jpg" height="300vh" width="300vw">';
<div id="day1"> <div id="icon"></div> </div>
<div id="day2"> <div id="icon"></div> </div>

Show values given by AngularJS ng-repeat once clicked from an anchor tag

I'm trying to dynamically show the title of a filename once the anchor tag is clicked. Once the anchor tag is clicked, it's supposed to show its filename, then its file at the bottom (given a gdrive link). Showing the file works well, but I can't seem to show the name of the file. Instead of the filename, it shows {{file.name}}, which means that file.name is not being evaluated. (I am using AngularJS to dynamically traverse through and show files and filenames)
Here is the code.
<div class="ui two column stackable grid">
<div class="column">
<div class="drive-link">
<h2 class="header" id="filename"></h2>
<!-- the filename should be shown here. Value is being passed through {{file.name}} from an a tag below -->
<iframe name="embedded-iframe" allowfullscreen="" frameborder="0"></iframe>
</div>
</div>
<div class="column">
<div class="ui styled accordion">
<div ng-repeat="file in files">
<div class="single-category-component" ng-if="$index==0">
<div class="active title">
<i class="dropdown icon"></i>
{{file.category}}
</div>
<div class="active content">
<a target="embedded-iframe" href="{{file.link}}" onclick="document.getElementById('filename').innerHTML='{{file.name}}';"> {{file.name}} </a>
<!--where I'm passing {{file.name}} to the h2 tag on the top-->
<div ng-repeat="next_file in files | limitTo:files.length:$parent.$index">
<a target="embedded-iframe" ng-if="$index > 0 && next_file.category_id == files[$index-1].category_id" href="{{next_file.link}}">{{next_file.name}}</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Use ng-click to pass the file object to your controller.
HTML
<h2 class="header" id="filename">{{fileName}}</h2>
.............
<a target="embedded-iframe" ng-href="file.link" ng-click="show_file_name(file)"> {{file.name}} </a>
JS
//capture the file properties in the controller function of your ng-click
$scope.show_file_name=function(file){
$scope.fileName=file.name;
$scope.fileLink=file.link;
}
do like this first set onclick method and pass file name to function
<a target="embedded-iframe" href="{{file.link}}" onclick="show_file_name({{file.name}})"> {{file.name}} </a>
now in javascript function you can get file name like this
function show_file_name(name){
console.log(name); //this is the file name that you sent form onclikc method
}
you can pass multiple values like this
onclick="show_file_name({{file.name}}, {{file.link}})"
and get it like this
function show_file_name(name, link){
console.log(name);
console.log(link);
}

Need Javascript If the Sequence match the Html Structure

Javascript expert this is my template coding:
<html>
<head>
</head>
<body>
<div id='top'>
<h2> This is my website headline </h2>
</div>
<div class='outer-wrapper'>
<h3>This is content area for main blog </h3>
</div>
<div class='footer'>
<h4> This is footer content area </h4>
</div>
<!--Copyright Structure Start-->
<div id='copyright'>
<div id='container'>
<p>Copyright 2016. Designed By <a href='#'>Company</a>
</p>
</div>
</div>
<!--Copyright Structure End-->
</body>
</html>
i have the below html structure that is used in the template.
<div id='copyright'>
<div id='container'>
<p> Designed By <a id='doom' href='http://www.example.com'>Company</a>
</p>
</div>
</div>
Case 1: Now,i want if the same sequence exist #copyright > #container > p > a#doom in the the html structure inside the template Then its ok, if any if these has removed, then redirect my page to example.com.
<div id='copyright'>
<div id='container'>
</div>
</div>
See the structure above has no <p></P> tag, now it should be redirected.
Case 2: If there is added extra other html tag inside my html structure in the template rather than these tags: #copyright #container P and a#doom. then it should also redirected.
<div id='copyright'>
<div id='container'>
<div id='wrap'>
<p> Designed By <a id='doom' href='http://www.example.com'>Company</a>
</p>
</div>
</div>
</div>
See the structure has extra div wrap now, it should redirected to example.com because it does not match the sequence.
I hope someone will give the script soon. thanks.
You can just use the selector in JQuery and check the length. If you change the HTML, the selector won't match, and you don't redirect:
Run this when you HTML has loaded (onLoad or domReady):
if( $('#copyright > #container > p > a#doom').length == 0 ) {
alert("Redirect");
}
Example fiddle:
https://jsfiddle.net/feb5zex2/
You basically want to run this code when the document is ready (1. line) and if a specific CSS selector with direct ancestor combinations doesn't match (2. line), redirect using window.location.replace() (3. line).
$(document).ready(function() {
if ($("#copyright > #container > p > a#doom").length == 0) {
window.location.replace("http://www.example.com");
}
})

How to create an array of divs with content?

I'm trying to create an array of nested divs, in which I only need to change 3 values when writing the divs to the document (html).
My divs look like this:
<div class="item">
<div class="item-h"> <a class="item-anchor" href="1_water_bottle.html">
<div class="item-image"> <img class="item-image-first" src="images/img_1_water_bottle.png" alt="">
<div class="item-meta">
<h2 class="title">Water Bottle 1</h2>
<span class="item-arrow"></span> </div>
</div>
</a> </div>
</div>
I need to create an array of about 50 items, and then use the document.write function to write 4 of those arrays for each page, as a section for "similar stuff".
I searched on stackoverflow, and came up with :: this page :: , which explains how to create an array in javascript, and then found another script that uses the document.write function.
The script uses an array of categories, to populate a form selection. And it does so, but using an array : (var categories = new Array("a1", "a2", "a3", ...) and so on.
for(var hi=0; hi<categories.length; hi++)
document.write("<option value=\""+categories[hi]+"\">"+categories[hi]+"</option>");
Could I use these two scripts to populate a section with 4 items from the array of the divs?
If so, then how could I do it? I know it can be done in php, but don't know if this can be done in javascript.
I tried, and created this array in notepad++, but the code wasn't recognized as a string, per array element...
var array_divs = [
$('<div class="item">
<div class="item-h"> <a class="item-anchor" href="1_water_bottle.html">
<div class="item-image"> <img class="item-image-first" src="images/img_1_water_bottle.png" alt="">
<div class="item-meta">
<h2 class="title">Water Bottle 1</h2>
<span class="item-arrow"></span> </div>
</div>
</a> </div>
</div>') ,
$('<div class="item">
<div class="item-h"> <a class="item-anchor" href="1_water_bottle_2.html">
<div class="item-image"> <img class="item-image-first" src="images/img_1_water_bottle_2.png" alt="">
<div class="item-meta">
<h2 class="title">Water Bottle 2</h2>
<span class="item-arrow"></span> </div>
</div>
</a> </div>
</div>')
]
Trying to populate the section, with selective items from the array, for example:
document.write(array_divs[1],array_divs[2]);
I haven't tried this, but since notepad++ didn't treat my div as a string, I had to search again... but couldn't find any info regarding this.
Thanks for any help.
-

Categories

Resources