Trying to access variables outside the function in Javascript - javascript

I am using the following snip of Javascript from another SO answer:
var _URL = window.URL || window.webkitURL;
$("#file").change(function (e) {
var file, img;
if ((file = this.files[0])) {
img = new Image();
img.onload = function () {
alert(this.width + " " + this.height);
};
img.src = _URL.createObjectURL(file);
}
});
I cannot figure out how to get access to those this.width and this.height variables outside of the function. I have set them equal to existing variables and the variables are always 0 or null.

Its not really useful to just make them available outside a function since you will never really know the onload happened. You want a callback that will use those values at the appropriate time.
var _URL = window.URL || window.webkitURL;
$("#file").change(function (e) {
var file, img;
if ((file = this.files[0])) {
img = new Image();
img.onload = function () {
someCallback(this.width, this.height);
};
img.src = _URL.createObjectURL(file);
}
});
function someCallback (width, height) {
// use those values
}
Yes you can use a global variable but again I point out you won't know when those values have been populated and could end up with problems in your code.

You can also do something like this
var _URL = window.URL || window.webkitURL;
var width="";
var height="";
$("#file").change(function (e) {
var file, img;
if ((file = this.files[0])) {
img = new Image();
img.onload = function () {
width=this.width;
height=this.height;
};
img.src = _URL.createObjectURL(file);
}
});
Now you can use height and width variable out side of your change event. now this both variables are global variable

Related

How to call a function that gives a url, which is then used to store and display an image using FileReader

I am new to coding in javascript, I have been tasked as an excersise using some pre-existing functions to create an image item using a given url. I need to read the image, store it in local storage and then display it on the screen. The only functionI need to add too is process file. I am stuck and cannot get it to display the image. I get an error saying that the path does not exist. Below is my code, any guidance to what I am doing wrong? I feel like I am very close but doing something funamendatly wrong.
function addImageEntry(key, url) {
var imgElement = new Image();
imgElement.alt = "Photo entry";
imgElement.src = url;
addSection(key, imgElement);
}
function makeItem(type, data) {
var itemObject = { type: type, data: data };
return JSON.stringify(itemObject);
}
function processFile(event) {
function addImage(url) {
var key = "diary" + Date.now();
addImageEntry(key, url);
var imgElement = new Image();
imgElement.src = url;
var item = makeItem("image", imgElement.src);
localStorage.setItem(key, item);
}
var inputElement = event.target;
var fileObject = inputElement.files[0];
var reader = new FileReader();
reader.addEventListener("load",addImage);
url = reader.readAsDataURL(fileObject);
event.target.value = "";
}
The url = reader.readAsDataURL(fileObject) won't store the image data.
It stores in reader.result.
Use imgElement.src = reader.result.
document.querySelector('input[type="file"]').addEventListener('change', processFile)
function processFile(event) {
var fileObject = event.target.files[0]
var reader = new FileReader()
reader.addEventListener('load', addImage)
reader.readAsDataURL(fileObject)
function addImage() {
var imgElement = new Image()
imgElement.src = reader.result
document.body.append(imgElement)
}
}
Amend:
function addImage(event) {
// use reader.result is ok too
localStorage.setItem('myimage', event.target.result)
}
function addImageEntry() {
var imgElement = new Image()
imgElement.src = localStorage.getItem('myimage')
imgElement.style.display = 'block'
document.body.append(imgElement)
}

Javascript variables declared and initialized but give undefined when checked

The following are the variables i have declared in javascript script tag.
The Variables are declared globally and initialized in the inner function which is inside another function (outer).
The problem is; when i try to check the variables using console.log i get "undefined". I don't know why.
I have read the variable hoisting, scope etc of Javascript variables. But i am unable to solve it. Please help.
var width;
var height;
var ratio;
var nwidth;
var nheight;
var wbool;
var imgsrc;
var canvas;
$("#myimage").change(function(){
readURL(this);
});
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
var image = new Image();
image.src = e.target.result;
image.onload = function(){
if(this.width > this.height){
ratio = this.width/this.height;
nheight = parseInt(Math.ceil(1024/ratio));
wbool = true;
}
else{
ratio = this.height/this.width;
window.nwidth = parseInt(Math.ceil(768*ratio));
wbool = false;
}
}
console.log(window.nwidth + "" + wbool);
You're console.log()'ing nwidth before it has been assigned.
image.onload is an asynchronous operation (think like a callback). the console.log() is firing before the variable data has been assigned.
Try moving the log into the onload function.
var width;
var height;
var ratio;
var nwidth;
var nheight;
var wbool;
var imgsrc;
var canvas;
$("#myimage").change(function(){
readURL(this);
});
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
var image = new Image();
image.src = e.target.result;
image.onload = function(){
if(this.width > this.height){
ratio = this.width/this.height;
nheight = parseInt(Math.ceil(1024/ratio));
wbool = true;
}
else{
ratio = this.height/this.width;
window.nwidth = parseInt(Math.ceil(768*ratio));
wbool = false;
// it will be defined here, because you are doing
// it inside the async operation.
console.log(window.nwidth);
}
}
// this will be undefined, because the var has not been set
// by the time this line executes.
console.log(window.nwidth + "" + wbool);
why does this happen?
async operations, like ajax calls ( or file loading in your code), take time to complete. Since javascript runs on a single thread, if the app were to stop and wait for the operation to complete, then the browser would lock up. Not good!
So, async operations are skipped over, and the callback portion is executed once the operation completes. This means your code is executing like this:
start loading the file
console.log() // undefined
loading complete, and the variable has been defined.
To trigger a custom event, you could do something like this:
$("#myimage").change(function(){
readURL(this);
});
// SET UP LISTENER FOR YOUR CUSTOM EVENT
$(document).on('fileWasLoaded', function () {
console.log(window.nwidth + "" + wbool);
});
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
var image = new Image();
image.src = e.target.result;
image.onload = function(){
if(this.width > this.height){
ratio = this.width/this.height;
nheight = parseInt(Math.ceil(1024/ratio));
wbool = true;
}
else{
ratio = this.height/this.width;
window.nwidth = parseInt(Math.ceil(768*ratio));
wbool = false;
// TRIGGER YOUR CUSTOM EVENT WHEN THE IMAGE IS LOADED
$(document).trigger('fileWasLoaded');
}
}

Values returned from image.onload(function() are 0 or undefined?

I try to get height/width from some background images, but how to get these values into some variables?
var bgobj = jQuery(this); // assigning the object
var url = bgobj.css('background-image').replace(/url\(|\)$|"/ig, '');
var img = new Image();
img.src = url;
Option 1:
alert('img.width: ' + img.width); // alert: " img.width: 0 "
Probably, the image hasn't loaded. So I try onload:
Option 2:
jQuery(bgimg).on('load', function() {
height = jQuery(bgimg).height();
//alert('height ' + height); //'480px' which is correct!
});
No way to get the value out for further use!? So I try callback:
Option 3:
var imageSize = function(url, callback) {
var img = new Image();
img.onload = function(){
var response = {};
var img = new Image();
img.onload = function() {
var x = img.width;
var y = img.height;
var z = y/x;
response = {width:x,height:y};
if(callback) callback(response);
}
img.src = url;
}
img.onload();
}
var getSize = function(url, callback) {
imageSize(url, function(response) {
var dim = response;
})
callback(dim);
}
var h;
imageSize(img.src, function(response) {
h=response.height;
//alert(h); // 800px (OK))
})
//alert(h); //undefined
//alert(imageSize.height); //undefined
//alert(imageSize.h); //undefined
//alert(imageSize.response.h); //undefined
Still no way to get the value into an ordinary variable.
Where did I go wrong?
You've overcomplicated it, but option 3 is one way to do it.
var imageSize = function(url, callback) {
var img = new Image();
img.onload = function(){
if(callback) callback(img.width,img.height);
}
img.src = url;
}
$(function(){
var url = $('#foo').css('background-image').replace(/url\(|\)$|"/ig, '');
imageSize(url,function(w,h){
alert("width=" + w + ", height=" + h);
})
});
#foo{
background-image:url(http://lorempixel.com/100/100/)
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">test</div>
The thing to remember is that the method imageSize is asynchronous, so you must pass it a callback which will be called when the image has loaded. You cant have another method where you treat it as a synchronous call, that just wont work.

Creating a Blob from an external image url

I have an file input that i used to get a file and turn it into a blob. Is there anyway I can get an external image url and turn that into a blob? Here is the code I am using to do it with just a file from a <input type="file" />:
//Process the file and resize it.
function processfile(file) {
if (!(/image/i).test(file.type)) {
alert("File " + file.name + " is not an image.");
return false;
}
// read the files
var reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function (event) {
// blob stuff
var blob = new Blob([event.target.result]); // create blob...
window.URL = window.URL || window.webkitURL;
var blobURL = window.URL.createObjectURL(blob); // and get it's URL
// helper Image object
var image = new Image();
image.src = blobURL;
image.onload = function () {
for (var x = 0; x < self.ThumbSizes.length; x++) {
// have to wait till it's loaded
var resized = resizeMe(image, self.ThumbSizes[x]); // send it to canvas
var resized_blob = dataURItoBlob(resized);
uploadFile(resized_blob, self.ThumbSizes[x].Name);
}
}
};
Instead of passing a file through I wanted to be able to structure this code to pass a image url and convert it into a blob.
I hope it helps you. (I didn't run it.)
function processfile(imageURL) {
var image = new Image();
var onload = function () {
var canvas = document.createElement("canvas");
canvas.width =this.width;
canvas.height =this.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0);
canvas.toBlob(function(blob) {
// do stuff with blob
});
};
image.onload = onload;
image.src = imageURL;
}

$ outside of jQuery

This app https://developer.mozilla.org/en-US/demos/detail/meet-me-there/launch accepts uploaded photos, attaches a qr code to them, and then allows you to share them. I've attached below the JavaScript for everything except the QR functionality. The app doesn't use jQuery, but at the beginning it assigns a function to the $.
window.onload = function(){
var $ = function(id){
console.log(id);
return document.getElementById(id);
},
When I run the app with the console.log in the above position, it shows that quite a few 'ids' are getting passed through that console.log(id). As the file loads, it logs 'surface', 'cam' and 'upload' and, as you engage the app, it logs 'result', 'sharer', 'uploadedURL' and many others. Problem is that I don't see how everything keeps getting passed through that function for the console.log to log the different 'id's at that point in the code. Therefore, I wonder what the significance of '$' is in this context (no jQuery). Specifically, by creating that '$' function, is it called anytime that any of the other events with $ are run, such as $('upload').onclick = function(){...
Is it working similar to how adding a prototype is working in jquery by using $.prototype.function() in jquery. If so, where does it get this functionality from if there's no jQuery.
window.onload = function(){
var $ = function(id){
console.log(id);
return document.getElementById(id);
},
canvas = $('surface'),
ctx = canvas.getContext('2d'),
watcher, loc='No location provided', located;
$('cam').onchange = function(event){
console.log(event);
console.trace();
var files = event.target.files,
file;
if (files && files.length > 0) {
file = files[0];
try {
var URL = window.URL || window.webkitURL || window.mozURL;
var imgURL = URL.createObjectURL(file);
var img = new Image();
img.id = "tester";
//Load it onto the canvas
img.onload = function() {
console.trace();
canvas.width = this.width;
canvas.height = this.height;
$('info').innerHTML = ("Width: " + this.width + "px, Height: " + this.height + "px");
$('result').width = 400;
$('result').height = (400 / (this.width/this.height)) >> 0;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
var codeSize = (canvas.height/4) >> 0;
var imgn = new Image();
imgn.onload = function(){
ctx.drawImage(imgn, (canvas.width-5- codeSize), (canvas.height-5-codeSize), codeSize, codeSize);
$('result').src = canvas.toDataURL();
}
imgn.src = (QR.encode(loc, codeSize, 5));
}
img.src = imgURL;
} catch (e) {
console.log("error: " + e);
}
}
},
// borrowed this functionality from cgack's demo
// https://developer.mozilla.org/en-US/demos/detail/snap-and-share
$('upload').onclick = function(){
$('infomsg').style.display = 'block';
var url = "http://api.imgur.com/2/upload.json",
params = new FormData(),
http = new XMLHttpRequest();
params.append('key','29a8b1db1d8fda0df87006def2307242');
params.append('image',canvas.toDataURL().split(',')[1]);
http.open("POST", url);
http.onload = function() {
var url = JSON.parse(http.responseText).upload.links.imgur_page;
$('uploadedUrl').href = url;
$('uploadedUrl').innerHTML = url;
$('shareFb').href = ("http://www.facebook.com/sharer.php?u="+url);
$('shareTwitter').href = ("http://twitter.com/intent/tweet?url="+url);
$('sharer').style.display = 'block';
$('infomsg').style.display = 'none';
};
http.send(params);
console.log(params);
};
watcher = navigator.geolocation.watchPosition(function(position){
console.trace();
console.log("navigator");
loc = "geo:" + position.coords.latitude + "," +position.coords.longitude;
located = true;
}, function(error){
if(error.code == error.PERMISSION_DENIED || error.code == error.POSITION_UNAVAILABLE)
alert('damn, we were not able to locate you. sorry.');
}
);
};
$ is just a variable name, like any other. It has no special meaning.
"Problem is that I don't see how everything keeps getting passed through that function for the console.log to log the 'id' at that point in the code."
Any time you see $, it's a reference to the function. So a () after it invokes it with the given argument. It's just like any other function, just with a funny name referencing it.
"Therefore, I wonder what the significance of '$' is in this context (no jQuery). Specifically, by creating that '$' function, is it called anytime that any of the other events with $ are run"
Again, no real significance. It's just a function name. If you renamed all the instances of $ to byId, it would behave the same.
window.onload = function(){
// var $ = function(id){
var byId = function(id){
console.log(id);
return document.getElementById(id);
},
canvas = foo('surface'),
ctx = canvas.getContext('2d'),
watcher, loc='No location provided', located;
byId('cam').onchange = function(event){
/* a bunch of code */
},
byId('upload').onclick = function(){
/* a bunch of code */
};
// rest of the code
};

Categories

Resources