How to make a script know about a flask parameter? - javascript

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.

Related

Upload part of a page or one picture from the page - the first (as soon as possible)

I am using AngularJS 1.4, and this is the code for my page
<div ng-app="myApp">
<div ng-controller="mainController">
<div ng-controller="first"> // this is ng-include - first.html
<img id="bannerImage"/>
</div>
<div ng-controller="first2"> // this is ng-include - first2.html
<img id="bannerImage1"/>
</div>
<div ng-controller="first3"> // this is ng-include - first3.html
<img id="bannerImage2"/>
</div>
<div ng-controller="second"> // this is ng-include - second.html
<img id="mainImage"/>
</div>
</div>
</div>
I need to first load "mainImage.jpg" in "second.html", but judging by the console loads all in the following sequence:
first.html
first2.html
first3.html
second.html
bannerImage.jpg
mainImage.jpg
mainImage2.jpg
mainImage3.jpg as include order in page
I need to load the picture "mainImage,jpg" as soon as possible and display it on the page.
Preferably, the order would be like that or better:
second.html
mainImage.jpg
first.html
...........
That isn't possible without knowing the image urls and preloading them prior to calling them.
In your described scenario, where template pages are being loaded, it doesn't seem like this is an option.
The reason why what you are observing is happening is because the server for your jsp is composing the html. So the html is all composed into the stream writer for the source code. Once the source code is sent to the browser, it then renders the source. It will request the images as they are encountered in the source.
There is no way to mix the image requests with the html composure because they are two separate actions. One is composing a string for a stream writer, and the other is making network requests for external resources.
The only hope if you are trying to change this is to cache the external resources prior to them being requested.
One way to attempt to preload the image would be to save it to a variable in the head of the document using JavaScript
<head>
...other related head elements...
<script>
(function cache(){
var mainCache = new Image();
mainCache.src = "mainImage.jpg";
})()
</script>
This approach will at least start the loading process immediately upon the page starting up, however depending on the image size it may still be loading as the page renders.

How can I load the HTML resulting from external .js call?

Googlebot sees content differently (doesn't index it at all) than the visitor if the content was generated dynamically from a JS file (see image above). Let's say I have the following code:
<body>
<div>Bunch of Content</div>
<script type="text/javascript" src="/js/somefile.js" />
<div>Bunch of Content</div>
</body>
How can I display the actual resulting HTML in the document when the page loads:
<body>
<div>Bunch of Content</div>
<p>Javascript dynamically created this string and this string.</p>
<p>Date: timestamp by JS</p>
<p>Other info dynamically created by JS.</p>
<div>Bunch of Content</div>
</body>
I have JS doing the heavy lifting to generate some content dynamically specifically for the page. The problem is, because the content is being generated in a JS file, the content never gets loaded in the DOM for indexing by crawlers.
Is there a way to do this? Thanks!
Google CAN index dynamic content, but it does not mean it will index it, or display it in search results, as it usually only looks for it in search of negative aspects (like black-hat SEO practices), although for some sites it may decide to use it for its index (it's a blind guess really, when it comes to how Google handles this, as they don't disclose this kind of details).
If your JS is making an AJAX request, and you're the owner of the API or whatever endpoint you're calling from the request, then your best bet is to cache the result on the server side, and modify your HTML page (which should be dynamic) so it renders the latest cached result in the HTML sent to the browser, but wrapped in a container tag (like a <div>) with an inocuous CSS rule like opacity: 0; so the content isn't visible to users by default, which should be changed to opacity: 1; by your JS file once the up-to-date HTML is loaded.
You could use jQuery to accomplish this, like in the example below:
$(document).ready(function() {
var el = "<section>Dynamically added content</section>";
$('.a').after(el);
})
div {
padding: 10px;
background-color: #ccc;
}
section {
padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="a">Bunch of Content</div>
<div>Bunch of Content</div>
Update: If you're using Ajax to get data from the server, then you would include the update on your code from the returning data object. You could extend this to iterate through the values you get.
$.getJSON('[Your url]', { param: 'value' },
function (data) {
var el = "<section>" + data.value + "</section>";
$('.a').after(el);
});
});

Using global variables in HTML/CSS, is it possible?

Let me try and explain what I mean here....
I have a lot of images on my page, and different paths where they are stored.
<img src="what/ever/folder/pic01.jpg">
<img src="and/even/longer/path/name/pic09.jpg">
<img src="what/ever/folder/pic01.jpg">
<img src="and/even/longer/path/name/pic09.jpg">
etc... they are scattered all over the long page
Would it be possible with CSS or HTML or.. to make a variable containing each path, and then use that in the HTML?
PATH01 = 'what/ever/folder/'
PATH02 = 'and/even/longer/path/name/'
And then do the images, styles etc..
<img src={PATH01}"pic01.jpg">
Or something like that? (am I making any sense?`hehe)
HyperText Markup Language, commonly abbreviated as HTML, is the
standard markup language
This means that here are no vars in html. But there a lot of html server-side processors like php,node.js etc which can give you result you are looking for.
PHP example:
<?php
$path01 = 'some/path/';
?>
<img src="<?=$path01?>pic01.jpg">
<br/>
<img src="<?php echo $path01?>pic01.jpg">
good question, <base> is what you are looking for
Specify a default URL and a default target for all links on a page
http://www.w3schools.com/tags/tag_base.asp
in your case
<img src="what/ever/folder/pic01.jpg">
can be written in
<base href="http://whatever.com/what/ever/folder" />
<img src="pic01.jpg">
but <base> is a unique element in single page, which means you can have only one ENV variable set.
p.s. 99% of time we use html template system (php, jsp or react.js, handlebars) to solve this kind of problem in real life
No you can't do that using purely HTML or CSS. You could however do something like that using javascript or the server language of your choice.

Formatting dynamically formed HTML elements created after Script is run

So this is actually a very tricky concept to portray so here is my attempt.
I am utilizing an HTML form template in LANDesk Service Desk - tool is irrelevant but important to note that there is back-end code that I cannot touch that is generating HTML.
So basically, the tool is pulling data from a back-end database containing a list of objects. It then inputs this data into an HTML form template that I have created using variables as placeholders for the objects. The HTML is then built on the fly with however many objects are in the database. Thus, I have no way of accessing the head - (which means native JS, and inline CSS).
My template looks like this...
<div class="my-template">
<a class="my-template my-link">My Link</a>
</div>
<script>
var myLinks = document.getElementsByClassName('my-link');
for (var i = 0 ; i < myLinks.length ; i++) {
myLinks[i].style.display = "none";
}
</script>
When I view the source on the loaded page it looks something like this...
<body>
<!--misc. page stuff-->
<!--First Item-->
<div class="auto-create">
<div class="my-template">
<a class="my-template my-link">My-Link</a>
</div>
</div>
<!--Second Item-->
<div class="auto-create">
<div class="my-template">
<a class="my-template my-link">My-Link</a>
</div>
</div>
</body>
All of the elements are formatted the way I want them to be...besides the last element on each page. I have determined that this is because each time the tool is running the object through the template, it is running the script. The issue is, there is a stupid default button that they place at the bottom of each object that is broken. (This is why I have the script changing the style to display: none..should have mentioned this earlier). Basically I want to delay the execution of the script until not only the object has been run through the template...but the entire page has loaded...but I can't seem to get the last button to go away.
I know that this is a lot of poorly written words trying to form an explanation, but I really think this is impossible...but I am convinced there has to be a way. (Also, the company isn't providing us with any help in finding a workaround, so I had to basically MacGyver this one

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

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.

Categories

Resources