Canvas drawing doesn't work in external .js file - javascript

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>

Related

Exif.js always returns "undefined"

I'm currently developing a simple WEB Application that allows users to upload a photo.
That photo's EXIF GPS data is then supposed to be extracted to a variable that will then be used in a google maps widget, with a "pin" on the location of shooting. The idea is then generate a link for users to be able to share both the photo and the google maps widget on Forums.
The issue at the moment is in the use of the EXIF.js library.
I currently have a simple html page just to test/try this such library and the code is:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>EXIF</title>
</head>
<body>
<img src="image1.jpg" id="img1" />
<h1>Localização da foto</h1>
<p id="info_model"></p>
<script src="exif.js"></script>
<script>
window.onload=getExif;
function getExif() {
var imagem = document.getElementById("img1");
var modelo = EXIF.getTag(imagem, "Model");
document.getElementById("info_model").innerHTML = modelo;
}
</script>
</body>
</html>
The expected result should be for it to say: "iPhone 6S Plus"
The actual result is: "undefined"
I can confirm the photo used to test the code does in fact have valid EXIF
New code as suggested:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>EXIF</title>
</head>
<body>
<img src="image1.jpg" id="img1" />
<h1>Modelo da câmara</h1>
<p id="info_model"></p>
<script src="exif.js"></script>
<script>
window.onload=getExif;
function getExif() {
var img1 = document.getElementById("img1");
EXIF.getData(img1, function() {
var model = EXIF.getTag(this, "Model");
var modelo = document.getElementById("info_model");
modelo.innerHTML = `${model}`;
});
}
</script>
</body>
</html>
getData works asynchronously and as such, needs to be passed a callback function, which your code does not have. You can only call getTag after you've called getData.
See the example on
https://github.com/exif-js/exif-js
Start with calling the EXIF.getData function. You pass it an image as a parameter:
either an image from a <img src="image.jpg">
OR a user selected image in a <input type="file"> element on your page.
function getExif() {
var img1 = document.getElementById("img1");
EXIF.getData(img1, function() {
var make = EXIF.getTag(this, "Make");
var model = EXIF.getTag(this, "Model");
var makeAndModel = document.getElementById("makeAndModel");
makeAndModel.innerHTML = `${make} ${model}`;
});
}
window.onload = getExif;
<script src="https://cdn.jsdelivr.net/npm/exif-js"></script>
<pre>Make and model: <span id="makeAndModel"></span></pre>
<img src="path/to/image.jpg" id="img1" />
I know this may be already solved, but I'd like to offer alternative solution using library exifr. It's new, maintained and actively developed library with focus on performance.
<img src="image1.jpg" id="img1" />
<h1>Modelo da câmara</h1>
<p id="info_model"></p>
<script src="https://unpkg.com/exifr#2.1.3/index.js"></script>
<script>
async function getExif() {
var img1 = document.getElementById("img1");
let output = await exifr.parse(img)
var model = EXIF.getTag(this, "Model");
var modelo = document.getElementById("info_model");
modelo.innerHTML = output.Model;
}
</script>
The important part here is the async/await. The image is loaded asynchronously so you need to wait until it's loaded and parsed. This is similar to above mentioned callbacks but more modern.
You can check out the library's playground and experiment with images and their output, or check out the .repository and docs

Flask app not executing javascript when it's in an external file

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.

Why is FileReader.readAsText() returning null?

I am trying to read a file in the same directory of an HTML and JavaScript file however it seems to be returning null. Below I have added the code I have from each file.
HTML File:
<html>
<!-- Code to call the Google Maps API and link style.css sheet -->
<body>
<div class="content">
<div id="googleMap"></div>
<div id="right_pane_results">hi</div>
<div id="bottom_pane_options">
<button onclick="get_parameters()">Try It</button>
</div>
</div>
</body>
<script type="text/javascript" src="./javascript.js">
</script>
</html>
JavaScript File:
function get_parameters() {
alert("hi"); // Just to let me know the function is getting called
var freader = new FileReader();
var text;
freader.onload = function(e) {
text = freader.result;
}
freader.readAsText('./test.txt', "ISO-8859-1");
text = freader.result; // To my knowledge, this should be taking the current line freader is on and storing it into text
var div = document.getElementById('bottom_pane_options');
div.innerHTML = div.innerHTML + text;
}
test.txt
Iron
Aluminum
Steel
//etc. for x number of times (depends on data I have parsed previously)
All I would like is for JavaScript to read test.txt and parse it into an array (text). The issue is, when I click the button 'Try It', the alert pops up (telling me the function is being called) and text contains null. I am running all files off my computer and all are in the exact same directory.

place javascript in html5 in external file

In html5 how do i place the class below (constructor and method)in another file and reference it in the html file.
Below I have everything in 1 file and I dont want that.
<canvas id="myCanvas" width="600" height="400"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.font="14px Arial";
//how to move to other file
function ClassPerson(gender,name1) {
var aa;
this.gender=gender;
this.name1=name1;
aa=6;
};
//how to move to other file
ClassPerson.prototype.m_sayGender = function()
{
ctx.fillText("this gender= " + this.gender + " gender=" + this.name1,10,40);
};
//stay in this file
var person1 = new ClassPerson('male','dave');
var person2 = new ClassPerson('female','bet');
ctx.fillText("this gender= " + person1.gender,10,20);
person1.m_sayGender();
myObject._three();
</script>
You simply create an external JS file with your code
and include it like this:
<script src="myFile.js"> </script>
or
<script src="<myFile>.js" type="text/javascript"></script>
Be sure to place the JS file in the directory where you have your HTML file
After comment: I guess you have to dynamically create an image with javacript set it's src porpertie and the diplay it.
Set the whole JS code of your class in an external *.js file. Then import it into your *.html file like this:
<script src="<external-file-name>.js" type="text/javascript"></script>

CDATA Issue Within Magento Rotator

So I'm currently developing a Magento Website. I set up a rotator using the code found here:
http://www.magentocommerce.com/wiki/4_-_themes_and_template_customization/cms_and_home_page/javascript_banner_rotator_for_home_page
If I put the code into the homepage it works as it's supposed to. However if I put the code within a static block CDATA forces itself into the code, breaking it. I'm unable to remove the CDATA as it keeps replacing itself. Code Below:
<script type="text/javascript">// <![CDATA[
var imgs1 = new Array("{{media url="wysiwyg/rotator-1-1.jpg"}}","{{media url="wysiwyg/rotator-1-2.jpg"}}","{{media url="wysiwyg/rotator-1-3.jpg"}}");
var lnks1 = new Array("http://www.example.com/","http://www.example.com/","http://www.example.com/");
var alt1 = new Array("That Looks Nice","That Looks Nice","That Looks Nice");
var currentAd1 = 0;
var imgCt1 = 3;
function cycle1() {
if (currentAd1 == imgCt1) {
currentAd1 = 0;
}
var banner1 = document.getElementById('adBanner1');
var link1 = document.getElementById('adLink1');
banner1.src=imgs1[currentAd1]
banner1.alt=alt1[currentAd1]
document.getElementById('adLink1').href=lnks1[currentAd1]
currentAd1++;
}
window.setInterval("cycle1()",4000);
// ]]></script>
<p><a id="adLink1" target="_top"> <img id="adBanner1" src="{{media url="wysiwyg/rotator-1-1.jpg"}}" alt="" width="235" height="250" border="0" /></a></p>
Any help would be appreciated.
You are commenting the javascript ending </script> tag, try putting </script> after the line CDATA ends.
Not sure about this, but worth a try.

Categories

Resources