onmouseover problems with JavaScript (rendered using django and django-imagekit) - javascript

I'm using Imagekit. View.py includes:
def pics(request):
p = Photo.objects.all()
return render_to_response('Shots.html',
{'p': p})
The following simple code in the template will generate associated images:
{% for p in p %}
<img src = "{{ p.display.url }}">
<img src = "{{ p.thumbnail_image.url }}">
{% endfor %}
I'm attempting to generate a series of thumbnails {{ p.thumbnail_image.url }} which, when mouseover'd, will generate the slightly larger version of the image, {{ p.display.url }} via Javascript. The following code in the template attempts to do so:
<html>
<head>
<HEAD>
<script
language="Javascript">
{ image1 = new Image
image2 = new Image
image1.src = {{ p.thumbnail_image.url }}
image2.src = {{ p.display.url }}
</script>
</head>
<body>
{% for p in p %}
<a href=""
onMouseOver="document.rollover.src=
image2.src
onMouseOut="document.rollover.src=
image1.src">
<img src="{{ p.thumbnail_image.url }}" border=0 name="rollover"></a>
{% endfor %}
</body>
</html>
This will display the series of thumbnails, but the larger image will not display when mouseover'd. I believe it has to do with how I'm specifying the variable {{ p.display.url }}.

I cleaned up your code, but as #fish2000 mentioned, this is still a dirty way of doing it. I came up with the following:
<html>
<head>
<script>
var thumbs = [];
var hovers = [];
{% for p in p %}
thumbs.push(new Image());
thumbs[thumbs.length - 1].src = p.thumbnail_image.url;
hovers.push(new Image());
hovers[hovers.length - 1].src = p.display.url;
{% endfor %}
</script>
</head>
<body>
{% for idx, p in enumerate(p) %}
<a href="">
<img src="{{ p.thumbnail_image.url }}" border=0 name="rollover" onmouseover="this.src = window.hovers[{{ idx }}].src" onmouseout="this.src = window.thumbs[{{ idx }}].src">
</a>
{% endfor %}
</body>
</html>
I wrote up a basic example over at JSFiddle to try and mock what your Python code will produce: http://jsfiddle.net/TeEHU/
To explain a little bit what I did, I setup a couple of JavaScript arrays in the beginning to hold both the thumbnails and the hovers. Initially, I was just going to make them arrays of strings referencing the URLs but followed suit the way you did using the Image object to preload the image hovers.
From here, I got rid of the event handler attributes you defined in the anchor tag and moved it to the image tag so we could have direct access to the image attributes when the user moused over on it.
I generally don't condone the use of generating dynamic JavaScript from the server-side but I was just trying to stay consistent with your code.

It looks like your JavaScript is a little gnarly in general -- some specific e.g.'s:
you're using the depreciated language param in the <script> tag;
you have what looks like an unclosed bracket at the top of your first script block
I don't know if you can reference variables you've declared in onmouseover/onmouseout tags, as you're doing;
Often, you have line breaks in the middle of things like tags or param values, which those may be legal (I'm not sure) but they're of questionable value, at least to me; they are keeping me from understanding what you are doing. Consider removing them.
Also: generally, your use of quotes is a mess... Trust me, if you clean them up, you'll understand your own code much better.
However THE MAIN THING in your case should be: look at the code as rendered to the browser to solve your JavaScript problems. First and foremost. That'll narrow down whether or not the particular bug you seek to squash is due to your template syntax/logic/etc, vs. your client JavaScript. In any case, it's not specifically a django issue per se.

Related

Change DOM element class based on text content of another element when generated by Jinja for loop

I need to alter the colour of an HTML element based on the text content of another element. However, the content is being generated with a Python for loop using a Jinja shortcut.
For example:
{% for article in articles %}
<div class="row article">
<div class="col s6">
<strong>{{ article.title }}</strong>
<p>Page count: {{ article.page_count }}</p>
<p>Layout code: <span id="layout">{{ article.layout }}</span></p>
</div>
<div id="show_layout" class="col s1 layout"></div>
</div>
{% endfor %}
I'm trying to use Javascript or jQuery to make the #show_layout element red if a layout code is present (ie. there is some text content in that span). The trouble is that I'm only able to make all or none show up red as the JS function runs once and affects every iteration of the for loop. For example, if 3 article listings are generated by the for loop (pulled from MongoDB) then each of the #show_layout elements turn red, if just one has any layout code content. I've tried experimenting with using the 'this' keyword, but I'm not getting anywhere.
Currently this is the basic function I'm altering, though there have been many different versions! I'm calling this on page load; calling it from the element itself doesn't seem to do anything!
function showLayout() {
let code = document.getElementById("layout").textContent;
let toChange = document.getElementById("show_layout");
if (code !== "") {
toChange.classList.add("layout-red");
console.log(code)
}
else {
console.log("arghghg")
}
}
I'm very new to Python and Jinja, so perhaps my approach is entirely wrong. Can anyone suggest a better way of doing this, or am I missing something obvious?
CBroe pointed me in the right direction here, by suggesting that I do this via Jinja, which had not occurred to me (I'm very, very new to Jinja!).
adding:
{% if article.layout != "" %}
<div id="show_layout" class="col s1 layout-red show_layout"></div>
{% endif %}
did the trick!
Thank you CBroe!

How to set different url in css?

Here is a css code block.
<style type="text/css">
header.intro-header{
position: relative;
background-image: url('{{ site.baseurl }}/{% if page.header-img %}{{ page.header-img }}{% else %}{{ site.header-img }}{% endif %}')
}
</style>
I want to do such thing : if site.baseurl contains http I want to remove site.baseurl prefix , otherwise I wan to add site.baseurl prefix.
Can anyone help me ? I am new to css
EDIT
Thanks for friends who has commented. I am using jeklly theme. In every markdown, there is such line: header-img: "xx". As you see, the actural url of header-img is above css code.
CSS is not a programming language so a traditional conditional block is not possible in that sense. You can achieve you goal still by using Javascript or your programming language of choice to check if the base URL contains a certain string and print your URL value based on the result.

How to make a script know about a flask parameter?

I am using a Flask server. Some of the templates use JavaScript scripts of their own.
One of these scripts generates a svg on the page. This function needs a picture produced by the server.
Here is a simplified version of what exists for now:
template (myTemplate.html):
{% extends "layout.html" %}
{% block body %}
<div id="graph">
<img src="/picture/{{ datasetName }}"></img>
</div>
<script src="script.js"></script>
{% endblock %}
javascript (script.js):
var graph = d3.select("#graph");
var svg = graph.append("svg") //this generates a <svg> in the <div>, it's d3js syntax.
.attr("width",window.innerWidth)
.attr("height",window.innerHeight)
.append("g");
flask server (server.py):
from flask import *
#app.route('/', methods=['GET'])
def foo():
return render_template('myTemplate.html')
#app.route('/picture/<datasetName>', methods=['GET'])
def picture(datasetName):
img = (...) #some function to get my picture
return send_file(img.to_bytesio(), mimetype='image/svg', cache_timeout=0)
My problem is that I would like to be able to use the picture in my javascript (to set it as a background for the svg which will move when navigating in the svg), but currently I have no clean way to get it. I could move the script to the html page but my project is quite big and I want to avoid that.
What would be a clean way to proceed ?
The easiest way to get the loaded image as the background to the generated image is to use a CSS overlay. That requires almost no change to your HTML structure or drawing routines at all.
The CSS would look like:
#graph {
position: relative;
}
#graph * {
position: absolute;
top: 0px;
left: 0px;
}
Now everything in div#graph overlays each other.
A second way would be to have that loaded image be a part of the CSS background-image for the <div> or its <svg>. CSS has good background image support, with options for stretching, truncating, and tiling. A tutorial is here.
A final option requires more surgery:
Remove the <img ...> tag
Have your D3 code generate an image element. The docs are here.
<image xlink:href="/picture/..." x="0" y="0"
height="150" width="250" />
This is feasible, but I don't recommend it. CSS has better sizing, positioning, and tiling controls than SVG, esp. relative to the whole browser page. The image parameters often have to be explicitly specified, including image width and height, so you'll have to know or calculate them. And there is the problem of communicating from your template to your JS what the value of datasetName is. So...stick with one of the CSS options. Ideally the first.
Can you use something like the following
{% extends "layout.html" %}
{% block body %}
<div id="graph">
<img src="/picture/{{ datasetName }}"></img>
</div>
<script>
var imagePath = '/picture/{{ datasetName }}';
</script>
<script src="script.js"></script>
{% endblock %}
Basically server-side you generate a client-side script tag, which when executed client-side, would give you imagePath variable usable from client-side scripts.
P.S. Just noticed you wanted to avoid that. Sorry.
What you may also have is a URL mapping on the flask server, e.g. #app.route('/scripts/picture/<datasetName>.js', methods=['GET']), that generates client-side script file with parameters that you need client-side on the page.
This way you would keep the script related code separate from your html.

Changing background color of a bootstrap panel

I am trying to change the background color of a panel using javascript to emulate "selected" functionality.
So, on click I get hold of the div by ID and change its background color.
It works fine but only momentarily and again resets the background color, and I have no idea why?
DJANGO HTML Template
<div class="panel-group">
{% if articles %}
{% for article in articles %}
<div class="panel panel-success" id="aid_{{ article.articleId }}">
<div class="panel-body">
<b>{{ article.title }}</b><br/>
<span style="color:darkgrey; font-size:.9em; font-family:sans-serif; font-style:italic">{{ article.source }} - {{ article.date }}</span><br/>
{{ article.sentences }}
</div>
</div>
{% endfor %}
{% else %}
NO ARTICLES PRESENT
{% endif %}
</div>
Javascript
function populateArticle(aid) {
document.getElementById('aid_'+aid).style.backgroundColor="#DEF1DE";
}
Also here is a link to a gif I recorded that shows the behavior: http://g.recordit.co/fSoTieo5Qn.gif (copy-paste the link in a new tab in case if it gives error).
Any ideas why this is happening?
You are not preventing default <a> tag behavior, so Your page refreshes.
onclick="populateArticle({{ article.articleId }});return false;"
Should fix it.
No idea why that may be happening, I personally would try this:
<script>
$(document).ready(function () {
$(".panel-body a").on("click", function (e) {
e.preventDefault();
var id = "#aid_" + $(this).attr("data-articleID");
$(id).css("background-color", "#DEF1DE");
});
});
</script>
After your jQuery script and lose the onClick in your HTML (Bad practice) instead pass the id reference by adding a data-articleID attribute. Like this:
<b>article title</b>
If your issue still persists you'd have to check for any other JavaScript changing the background back to original colors.

How to pass Django textfield to html attribute and read with javascript

I want to pass a caption text for an image from a django template to javascript.
This is the relevant part of the html code:
<ul id="portfolio">
{% for picture in gallery_selected.photo_set.all %}
<li><img src={{ picture.path }} alt={{ picture.caption }}></li>
{% endfor %}
</ul>
Now I want to read the 'alt' tag from the images in javascript in order to create a fancy caption:
$("#portfolio img").click(function() {
var src = $(this).attr("src");
window.alt = $(this).attr("alt");
alert(window.alt);
});
I did not create the caption yet, I just wanted to test if the caption text is passed on (using the alert function).
However the alert only displays the first word of my caption text. As soon as a space occurs in the string, everything else is ignored.
Does anybody know how I can fix this issue?
You just need to wrap it in quotes. You should do that anyway with HTML attributes, for safety.
<img src="{{ picture.path }}" alt="{{ picture.caption }}">

Categories

Resources