I have HTML file that contained my CSS and JS. When creating my flask app I decided to separate out the CSS and JS to separate files in a static directory.
When I have everything in one HTML file, everything works as expected, but when the CSS and JS are in separate files, parts of the JS don't execute.
This is my import for in the HTML file:
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script type="text/javascript" src="{{ url_for('static', filename='scripts/main.js') }}"></script>
<link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.4.2/pure-min.css">
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
</head>
This is the contents of the standalone JS file:
$('#user_button').click(function(event) {
$("#user_id").html($('option:selected').html());
$('.button_div').show();
});
var prodData = [];
var boughtProds = [];
$('.prod_button').click(function(event) {
if (boughtProds.indexOf($(this).data('name')) == -1) {
prodData.push({
name: $(this).data('name'),
price: $(this).data('price'),
quantity: 1,
});
boughtProds.push($(this).data('name'));
} else {
prodData[boughtProds.indexOf($(this).data('name'))].quantity = prodData[boughtProds.indexOf($(this).data('name'))].quantity + 1;
}
var total = 0;
for (var x in prodData) total += prodData[x].price * prodData[x].quantity
total = Math.round(total * 100) / 100
var subtotal = '<tr><td></td><td>Subtotal</td><td>$' + total + '</td></tr>';
var allProds = '';
$.each(prodData, function(k, v) {
allProds = allProds + '<tr><td>' + v.name + '</td><td>' + v.quantity + 'x</td><td># $' + v.price + ' each</td></tr>\n';
});
$('.table_contents > tbody').html(allProds);
$('.table_contents > tfoot').html(subtotal);
});
$(document).ready(
function() {
$('.button_div').hide();
})
The weird thing is that this function works properly on the document load:
$(document).ready(
function() {
$('.button_div').hide();
})
and this function DOES NOT work:
$('#user_button').click(function(event) {
$("#user_id").html($('option:selected').html());
$('.button_div').show();
});
But even weirder is that everything works when it is all in one HTML file.
Any thoughts?
You either need to move <script type="text/javascript" src="{{ url_for('static', filename='scripts/main.js') }}"></script> outside of your <head> tag (e.g., to the end of <body>) or you need to put $('#user_button').click(...); inside $(document).ready(...);.
What's happening is that your browser begins loading your external script files as it processes your <head> tag. As soon as the file is loaded, the browser executes it, binding the click event to #user_button. This happens before it processes your <body> tag, so #user_button isn't yet part of the DOM.
If you tried to inspect $('#user_button') you'd see that it's empty.
console.log($('#user_button'));
This outputs
[]
I have faced similar problem. When inspected network, static js was loading from cache.
When I turned-off cache, it started working.
Therefore you need to restart debug server or turn off cache during development.
Related
My script works when it is included in the html file, but when I move it to an external .js file, canvas doesn't draw.
this is my html file:
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<title>Reveal RGB Values</title>
<form action='/' method='POST' enctype='multipart/form-data'>
<h1>Select file to upload:</h1>
<br>
<input type='file' name='file'>
<input type='submit' value='submit'>
</form>
{% if status == 'uploaded'%}
<h1>There will be a photo here</h1>
<canvas id="frame"></canvas>
<canvas id= "solution_frame"></canvas>
<div id="solution"></div>
{% endif %}
<script type = text/javascript src="{{ url_for('static', filename='script.js') }}"></script>
</body>
In the external .js file, I have two canvases that successfully get built (I can see empty blanks that match the sizes)
var frame = document.getElementById('frame');
frame.width = 800;
frame.height = 600;
var context = frame.getContext('2d');
var solution_frame = document.getElementById('solution_frame');
var solution_context = solution_frame.getContext('2d');
solution_frame.width = 25;
solution_frame.height = 25;
but I cannot draw the image
function draw_image(){
base_image = new Image();
// yay! jinja works here too.
var image_url = '{{img_url}}';
base_image.src = image_url;
base_image.onload = function(){
//context.drawImage(base_image, 0, 0);
scale_to_fit(this);
}
}
draw_image();
function scale_to_fit(img){
//get the scale
var scale = Math.min(frame.width/img.width, frame.height/img.height);
var x = (frame.width/2) - (img.width/2) * scale;
var y = (frame.height/2) - (img.height/2) * scale;
context.drawImage(base_image,x,y,img.width*scale, img.height*scale);
I found a similar post that suggested me to add this
document.addEventListener('DOMContentLoaded',draw_image,false);
saying the script is acting before the canvas is fully loaded, but it doesn't seem to be the issue.
Can anyone see where I'm possibly going wrong? Thanks ahead
EDIT!: It just occurred to me that the issue might be related to retrieving the image source location with Jinja?
It seems like my problem is not html/js related at all. I am using Jinja to retrieve the image location from the server, and Jinja doesn't serve to that external js file. It seems to me that function needs to be kept in the html file.
That's correct. Jinja doesn't run any processing on statically included assets.
I see two ways around your problem.
Either hard code the URL in script.js:
var image_url = '/path/to/image'
Or remove that line from the draw_image function and set that JS variable in the template, prior to including script.js:
<script type='text/javascript'>
const image_url = {{img_url}};
</script>
<script type='text/javascript' src="{{ url_for('static', filename='script.js') }}"></script>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
</head>
<body>
<input type="file" id="files" multiple />
<label id="list"></label>
<script>
//Interact with local files using the HTML5 file API
function handleFileSelect(evt)
{
//target is the element that triggered the event
var files = evt.target.files; // FileList object
// files is a FileList of File objects. List some properties.
for(var i=0; i<files.length; i++)
{
f = files[i];
document.getElementById('list').innerHTML += f.name + ' ' + f.type + ' ' + f.size + ' bytes ' + f.lastModifiedDate + '<br/>';
}
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>
</body>
</html>
I am just wondering why does the code not work correctly if the script section is moved from the body to the head.
The correctly working code should display the file name along with its size and other details, but when the code is moved it displays none of this.
Because when you place it in the head, the files element doesn't exist yet. So when you call document.getElementById('files'), it returns null, causing addEventListener to crap out.
The browser builds the page top down. Most commonly you put JavaScript at the bottom because of this.
Alternatively, you can hook into the DOMContentLoaded event. Which is basically what jQuery's $(document).ready() does. Or do window.onload = function() {...} or document.onload = function() {...}.
But really, placing it at the bottom is simpler. I usually just do that.
I'm having some trouble running some JS inside a html5 body.
Here's what's happening, whenever I remove all instances of the arrays from the JS file I am using, the script loads fine in the index file, however, when I add src to the attribute and/or mention an array name from said file, it breaks. simple as that.
since I'm planning on making a pretty big site, I have already begun organizing my root.
here's a little demo:
rootFolder/
index.htm
js/targetJS.js
here's the code
<script src="js/targetJS.js" type="text/javascript">
document.writeln("<table id='services' class='services' name='services'>");
document.writeln("<tr>");
document.writeln("<th> Preview: </th>");
document.writeln("<th> Description: </th>");
document.writeln("<th> Cost: </th>");
document.writeln("</tr>");
var i = 0;
//for ( i = 0; i < servicePrev.length; i++)
{
if (i % 2 == 0){
document.writeln("<tr class='even' id='even'>");
}
else{
document.writeln("<tr class='odd' id='odd'>");
}
//document.writeln("<td> " + servicePrev[i] + " </td>");
//document.writeln("<td> " + serviceDesc[i] + " </td>");
//document.writeln("<td> " + serviceCost[i] + " </td>");
document.writeln("</tr>");
}
document.writeln("</table>");
</script>
Whenever i add the src in the attribute and the lines that are commented out, the code does not work, however, when I omit the src and the lines that are currently commented out, the code works fine. even JSfiddle reports it working fine.
The contents of the JS file are 3 arrays with 5 indexes.
You need to seperate your tags
<script type="text/javascript" src="awesomescript.js"></script>
and
<script>
// some awesome code here
</script>
Since html5, you are free to name <script type="text/javascript"> or just use <script> for javascript, as text/javascript is default.
Quoted from http://javascript.crockford.com/script.html
The script tag has two purposes:
It identifies a block of script in the page. It loads a script file.
Which it does depends on the presence of the src attribute. A
close tag is required in either case.
The src attribute is optional. If it is present, then its value is a
url which identifies a .js file. The loading and processing of the
page pauses while the browser fetches, compiles, and executes the
file. The content between the and the
should be blank.
So, the script file should be loaded by dedicated script tag without content, the script content should be inserted into another script tag, after all if you have other errors you can check in the console of your broswer
<script src="js/targetJS.js" type="text/javascript"></script>
<script type="text/javascript">
document.writeln("<table id='services' class='services' name='services'>");
document.writeln("<tr>");
document.writeln("<th> Preview: </th>");
document.writeln("<th> Description: </th>");
document.writeln("<th> Cost: </th>");
document.writeln("</tr>");
var i = 0;
//for ( i = 0; i < servicePrev.length; i++)
{
if (i % 2 == 0){
document.writeln("<tr class='even' id='even'>");
}
else{
document.writeln("<tr class='odd' id='odd'>");
}
//document.writeln("<td> " + servicePrev[i] + " </td>");
//document.writeln("<td> " + serviceDesc[i] + " </td>");
//document.writeln("<td> " + serviceCost[i] + " </td>");
document.writeln("</tr>");
}
document.writeln("</table>");
</script>
I am currently doing this:
<div id="textChange" style="display:none;">Blah blah</div>
<script type="text/javascript">
var d = new Date();
var funnyDate = (d.getFullYear() + "" + (d.getMonth()+11) + "" + (d.getDate()+10));
if((funnyDate>=20131916) && (funnyDate<=20131923))
{
document.getElementById("textChange").style.display ="block";
}
</script>
and would like to move the script to an external JS file. How do I do that? I doesn't seem to be working for me.
Thanks.
Include this script after your #textChange div and it will work. For example before closing </body> tag:
...
<script src="funny-script.js" type="text/javascript"></script>
</body>
This is the simplest method. You could also run this code on DOMContentLoaded or window.onload events, but looking at what your script doing I don't think it makes sence.
1-open notepad or notepad ++ or whatever you use as a text editor.
2-copy the javascript code to the text editor without and tags
var d = new Date();
var funnyDate = (d.getFullYear() + "" + (d.getMonth()+11) + "" + (d.getDate()+10));
if((funnyDate>=20131916) && (funnyDate<=20131923))
{
document.getElementById("textChange").style.display ="block";
}
3-save the files with any name you want and don't forget to add the .js extension to the file for example save the file as "test.js"
4-copy the "test.js" to the same directory as html page.
5-add this line to the html page
<script type="text/javascript" language="javascript" src="test.js"></script>
One way to do this is to create a function and include this in a js file
function style_changer(){
var d = new Date();
var funnyDate = (d.getFullYear() + "" + (d.getMonth()+11) + "" + (d.getDate()+10));
if((funnyDate>=20131916) && (funnyDate<=20131923))
{
document.getElementById("textChange").style.display ="block";
}
}
Now in your html give reference to the js file containing this function for example
<script type="text/javascript" src="yourscriptfilename.js" />
you can include this in your section and should work
Save the a file called script.js with the contents.
var d = new Date();
var funnyDate = (d.getFullYear() + "" + (d.getMonth()+11) + "" + (d.getDate()+10));
if((funnyDate>=20131916) && (funnyDate<=20131923))
{
document.getElementById("textChange").style.display ="block";
}
And place this tag inside your HTML document. Place it just before the </body> so you'll know that the element textChange will exist in the DOM before your script is loaded and executed.
<script type="text/javascript" src="script.js" />
Make sure that script.js is in the same directory as your HTML document.
put this below code in a function
step1:
function onLoadCall()
var d = new Date();
var funnyDate = (d.getFullYear() + "" + (d.getMonth()+11) + "" + (d.getDate()+10));
if((funnyDate>=20131916) && (funnyDate<=20131923))
{
document.getElementById("textChange").style.display ="block";
}
}
Step2:-
call that function on page load
<body onload='onLoadCall()'>
...
</body>
step3:-
now move the script to another file it will work
Put script in a separate file and name it yourScript.js and finally include it in your file
add the code within the script file
function changeFunnyDate(){
var d = new Date();
var funnyDate = (d.getFullYear() + "" + (d.getMonth()+11) + "" + (d.getDate()+10));
if((funnyDate>=20131916) && (funnyDate<=20131923))
{
document.getElementById("textChange").style.display ="block";
}
}
Finally add the script in your file & call the method
<script src="yourScript.js" type="text/javascript"></script>
Take everything between your script tags and put it in another file. You should save this file with a .js file extension. Let's pretend you save it as textChange.js.
Now the simplest thing to do would be to include the script file just after your <div> tag -- so basically where the <script> tags and code were before, write:
<script type="text/javascript" src="textChange.js"></script>
This assumes that 'textChange.js' is in the same folder as your HTML file.
...
However, that would far too easy! It is generally best practice to place <script> tags in the <head> of your HTML file. You can move the line above up into the head but then the script will load before your <div> does--it will try to do what it does and it will fail because it can't find the div. So you need to put something around the code in your script file so that it only executes when the document is ready.
The simplest way to do this (and there may be better ways) is write the following...
window.onload = function () {
var d = new Date();
var funnyDate = (d.getFullYear() + "" + (d.getMonth()+11) + "" + (d.getDate()+10));
if ((funnyDate>=20131916) && (funnyDate<=20131923))
{
document.getElementById("textChange").style.display ="block";
}
}
This will mean your script is in the head where it should be and that it only performs when your whole page is ready, including the div that you want to act on.
Hope this helps.
The recommendation of the open source web analysis software Piwik is to put the following code at the end of the pages you want to track, directly before the closing </body> tag:
<html>
<head>
[...]
</head>
<body>
[...]
<!-- Piwik -->
<script type="text/javascript">
var pkBaseURL = (("https:" == document.location.protocol) ? "https://piwik.example.com/" : "http://piwik.example.com/");
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var piwikTracker = Piwik.getTracker(pkBaseURL + "piwik.php", 4);
piwikTracker.trackPageView();
piwikTracker.enableLinkTracking();
} catch( err ) {}
</script><noscript><p><img src="http://piwik.example.com/piwik.php?idsite=4" style="border:0" alt="" /></p></noscript>
<!-- End Piwik Tracking Code -->
</body>
</html>
Under the following assumptions:
https is never used
we don't care that the page loads slower because the script is loaded before the DOM
is it okay to convert the above to the following:
HTML file:
<html>
<head>
[...]
<script src="http://piwik.example.com/piwik.js" type="text/javascript"></script>
</head>
<body>
[...]
<noscript><p><img src="http://piwik.example.com/piwik.php?idsite=4" style="border:0" alt="" /></p></noscript>
</body>
</html>
Custom Javascript file with jQuery:
$(document).ready(function() {
try {
var piwikTracker = Piwik.getTracker("http://piwik.example.com/piwik.php", 4);
piwikTracker.trackPageView();
piwikTracker.enableLinkTracking();
}
catch(err) {
}
}
Are there any differences?
You are deferring the tracking until the page is fully loaded. Inline Javascript is executed when the browser finds it, so you'll have different number of visits depending on where you call piwikTracker.trackPageView();. The latter you call it, the lesser number of visits/actions will be counted.
Now, what do you consider a visit/action? If a user click on a link on your page, before the page fully loads, do you consider it a visit?