How setting a variable in img.onload function - javascript

From here i learned how to check if an image is available or not.
But i have a question. I have a variable and i would set her value according id the image is available or not.
For example i have this:
app.checkImage = function (imageSrc, good, bad) {
var img = new Image();
img.onload = good;
img.onerror = bad;
img.src = imageSrc;
}
I have an app object like this:
var app = {
offlineChecked: false,
offline: false,
};
Inside another function i have this code listing:
if(app.offlineChecked == true)
{
//don't do nothing
}
else
{
app.checkImage("https://mysite" + data.image_150,
function(){ app.offline = false; },
function(){ app.offline = true; });
app.offlineChecked = true;
}
But this doesn't work. app.offline is always false, in case the image isn't available and img.onerror fires.
Edit - i read the app.offline value after that code listing, as follow here:
if(app.offlineChecked == true)
{
//don't do nothing
}
else
{
app.checkImage("https://mysite" + data.image_150,
function(){ app.offline = false; },
function(){ app.offline = true; });
app.offlineChecked = true;
}
if(app.offline == true)
{
console.log('offline');
}
else
{
console.log('online);
}

Problem, that onerror function fires more late, than you try to check it.
Try this example
var app = {
offlineChecked: false,
offline: false
};
var ready = false;
app.checkImage = function (imageSrc, good, bad, onready) {
var img = new Image();
img.onload = good;
img.onerror = bad;
img.src = imageSrc;
img.onreadystatechange = onready;
};
if (app.offlineChecked == true) {
//don't do nothing
}
else {
app.checkImage("https://mysite",
function () {
app.offline = false;
},
function () {
app.offline = true;
alert(app.offline);
ready =true;
});
app.offlineChecked = true;
}
setInterval(function () {
if (ready) {
alert(app.offline);
}
}, 1000);
img.onload and img.onerror behave itself as callback, when scripts load or not, it runs onload or onerror. When you try to check it, onerror function doesn't yet launched

I found solution here.
That solved my problem. I write solution on it:
app.checkImage = function(imageSrc, imageChecked)
{
var img = new Image();
img.onload = function(){
app.offline = false;
imageChecked(app.offline);
}
img.onerror = function(){
app.offline = true;
imageChecked(app.offline);
}
img.src = imageSrc;
}
app.offline variable is set in the callback function as follows:
if(app.offlineChecked == true)
{
/**Other operations here if app is offline or not*/
}
else
{
app.checkImage("https://mysite" + data.image_150, function(offline)
{
app.offline = offline;
if(app.offline == true)
{
console.log('offline');
}
else
{
console.log('online');
}
app.offlineChecked = true;
});
}

Related

Ping site with knockout.js

I want to ping a few sites using javascript, and found this pen and does what I want.
However, I don't understand when I add goo12121212gle.com to the list of sites as a test it comes up saying that the domain has responded but in the console log I see ERR_NAME_NOT_RESOLVED??
I am new to JS but I am not sure why the below script is both saying the site is there and not at the same time? Is something missing from the script?
function ping(ip, callback) {
if (!this.inUse) {
this.status = 'unchecked';
this.inUse = true;
this.callback = callback;
this.ip = ip;
var _that = this;
this.img = new Image();
this.img.onload = function () {
_that.inUse = false;
_that.callback('online');
};
this.img.onerror = function (e) {
if (_that.inUse) {
_that.inUse = false;
_that.callback('offline', e);
}
};
this.start = new Date().getTime();
this.img.src = "http://" + ip;
this.timer = setTimeout(function () {
if (_that.inUse) {
_that.inUse = false;
_that.callback('timeout');
}
}, 1500);
}
}
var PingModel = function (servers) {
var self = this;
var myServers = [];
ko.utils.arrayForEach(servers, function (location) {
myServers.push({
name: location,
status: ko.observable('unchecked')
});
});
self.servers = ko.observableArray(myServers);
ko.utils.arrayForEach(self.servers(), function (s) {
s.status('checking');
new ping(s.name, function (status, e) {
s.status(e ? "error" : status);
});
});
};
var komodel = new PingModel(['goo12121212gle.com','msn.com','104.46.36.174','23.97.201.12']);
ko.applyBindings(komodel);
https://codepen.io/lyellick0506/pen/NGJgry
Both the onerror- and onload-callback use "responded" as the message, so there is no way to differentiate between them:
this.img.onerror = function (e) {
if (_that.inUse) {
_that.inUse = false;
_that.callback('responded', e); // <--- change this to a different message
}
};
Alternatively you could just check if the e parameter has been set:
new ping(s.name, function (status, e) {
s.status(e ? "error" : status);
});

How can I execute code after .onload function

I'm working with image preview before upload.
So I'm displaying the choosen files. It's working well.
But I'm stuck in a situation.
Foreach file on the "input file", the scripts tests if it's too small (smaller than 300px w:h).
If one of these files disobey this rule (must be width and height greater than 300px), the script has set an error var as true. And, after the "for" block, check if "error" is true or false.
I'm working in this scenario:
window.onload = function () {
var fileUpload2 = document.getElementById("inputFileID");
fileUpload2.onchange = function () {
var error = false;
if (typeof (FileReader) != "undefined") {
var dvPreview = document.getElementById("divToShowPreview");
dvPreview.innerHTML = "";
var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.jpg|.jpeg|.gif|.png|.bmp)$/;
if(fileUpload2.files.length > 3) {
alert('Only 3 files allowed!');
} else {
for (var i = 0; i < fileUpload2.files.length; i++) {
var file = fileUpload2.files[i];
if (regex.test(file.name.toLowerCase())) {
var reader = new FileReader();
reader.onload = function (e) {
var img = document.createElement("IMG");
img.src = e.target.result;
img.onload = function() {
console.log(this.width + " " + this.height);
if(this.width >=300 && this.height >=300 ) {
dvPreview.appendChild(img);
} else {
error = true;
}
};
};
reader.readAsDataURL(file);
} else {
alert(file.name + " is not a valid image file.");
dvPreview.innerHTML = "";
return false;
}
}
console.log(error);
}
} else {
alert("This browser does not support HTML5 FileReader.");
}
};
};
As you can see, the console.log(error) still shows FALSE!
How can I get this var set as true?
Thanks
the problem is that the img.onload functions is asynchronously executed. therefore console.log(error) is executed before or between the img.onload
this can be proven by looking at the sequence of your console.log, that look something like:
false
300 300
200 300
to solve this problem, create a variable to count how many images have been load, then count it in every img.onload. when the count of image that has been load is equal to the uploaded image count, call a function to check if error exists. for example:
function imageError(){
alert('image size to small');
}
window.onload = function () {
var fileUpload2 = document.getElementById("inputFileID");
// add variables
var imgLoaded = 0;
fileUpload2.onchange = function () {
var error = false;
if (typeof (FileReader) != "undefined") {
var dvPreview = document.getElementById("divToShowPreview");
dvPreview.innerHTML = "";
var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.jpg|.jpeg|.gif|.png|.bmp)$/;
if(fileUpload2.files.length > 3) {
alert('Only 3 files allowed!');
} else {
for (var i = 0; i < fileUpload2.files.length; i++) {
var file = fileUpload2.files[i];
if (regex.test(file.name.toLowerCase())) {
var reader = new FileReader();
reader.onload = function (e) {
var img = document.createElement("IMG");
img.src = e.target.result;
img.onload = function() {
//increase the loaded img count
imgLoaded++;
console.log(imgLoaded); // another check to show the sequence of events
console.log(this.width + " " + this.height);
if(this.width >=300 && this.height >=300 ) {
dvPreview.appendChild(img);
} else {
error = true;
}
// call imageError if all image have been loaded and there is and error
if (imgLoaded == fileUpload2.files.length){
console.log(error) // just to check
if (error){
imageError();
}
}
};
};
reader.readAsDataURL(file);
} else {
alert(file.name + " is not a valid image file.");
dvPreview.innerHTML = "";
return false;
}
}
//console.log(error); // no need for this line
}
} else {
alert("This browser does not support HTML5 FileReader.");
}
};
};
You have to break your for when you find a error, so it will not perform the next verification.
...
} else {
error = true;
break;
}
...

JavaScript image never finishes .onload

New user here.
I am making a hockey game using JavaScript, and I need all of the images to finish loading before the main function is called to avoid flickering.
There are four images used: skaterAmin.png, skaterBmin.png, goalieAmin.png, goalieBmin.png
I am getting stuck on 2 out of 4 .onload functions.
both loadSkaterImgA and loadSkaterImgB will change to true but both loadGoalieImgA and loadGoalieImgB remain false
also used console.log() to confirm they were actually stuck
I also double checked all image src's and they are correct
//load images before main draw function to avoid flickering
var loadSkaterImgA = false;
var loadGoalieImgA = false;
var loadSkaterImgB = false;
var loadGoalieImgB = false;
function preloadSkaterImgA() {
var skaterImgA = new Image();
skaterImgA.onload = function() {
completeSkaterImgA();
return;
}
skaterImgA.src = 'skaterAmin.png';
return skaterImgA;
}
function preloadGoalieImgA() {
var goalieImgA = new Image();
goalieImgA.onload = function() {
completeGoalieImgA();
return;
}
goalieImgA = 'goalieAmin.png';
return goalieImgA;
}
function preloadSkaterImgB(){
var skaterImgB = new Image();
skaterImgB.onload = function() {
completeSkaterImgB();
return;
}
skaterImgB.src = 'skaterBmin.png';
return skaterImgB;
}
function preloadGoalieImgB(){
var goalieImgB = new Image();
goalieImgB.onload = function() {
completeGoalieImgB();
return;
}
goalieImgB = 'goalieBmin.png';
return goalieImgB;
}
function completeSkaterImgA(){
loadSkaterImgA = true;
return loadSkaterImgA;
}
function completeGoalieImgA(){
loadGoalieImgA = true;
return loadGoalieImgA;
}
function completeSkaterImgB(){
loadSkaterImgB = true;
return loadSkaterImgB;
}
function completeGoalieImgB(){
loadGoalieImgB = true;
return loadGoalieImgB;
}
preloadSkaterImgA();
preloadGoalieImgA();
preloadSkaterImgB();
preloadGoalieImgB();
Thank you for reading
You just need to call your preload methods after the DOM (which waits until all images are loaded) has loaded:
window.onload = function () {
preloadSkaterImgA();
preloadGoalieImgA();
preloadSkaterImgB();
preloadGoalieImgB();
}

Why is image onload not working

I realize this is a common question asked by novice javascript programmers which I am. Console.log(img) and console.log("before onload") execute correctly but I never see an Image Loaded message.
AssetManager.loadImages = function(urls) {
var images = [];
var urlCount = urls.length;
for (var i=0; i<urlCount; i++) {
var img = new Image();
images.push(img);
}
var urlsLoaded = 0;
for (var i=0; i<urlCount; i++) {
(function(img) {
console.log(img);
console.log("before onload");
img.onload = function(e) {
console.log("Image Loaded!");
urlsLoaded++;
if (urlsLoaded >= urlCount) {
AssetManager.callback(images);
}
}
})(images[i]);
images[i].src = urls[i];
}
}
For anyone who made the same mistake as me - make sure onload is all lowercase and not camel case: onLoad.
This good:
img.onload = function () { };
This bad:
img.onLoad = function () { };
Try var img = document.createElement("img");
or
AssetManager.loadImages = function(urls) {
var images = new Array();
var urlCount = urls.length;
var urlsLoaded = 0;
var leImg;
for (var i=0; i<urlCount; i++) {
leImg = document.createElement("img");
leImg.onload = function(e){
urlsLoaded++;
if (urlsLoaded >= urlCount) {
// AssetManager.callback(images); --> this is balls, still
}
}
leImg.src = urls[i];
_images.push(leImg);
}
}
(not tested, and drunk)
onload doesn't fire if the image is being loaded from cache. You can use the complete property to check for this case.
if(img.complete){
// do the work
} else {
img.onload = () => {
// do the work
}
}
You can use a function to keep the code DRY.
"img.onload" function when call in nested function not work exact
you need call "img.onload" function explicit in "$().ready (function(){ }" or "window.onload = function() { }"
e.g
$().ready (function(){
var img = new Image();
img.src = 'image.png';
img.onload = function()
{
console.log("loaded");
}
}
I'm not sure what the exact problem is with your code, but here's some code I wrote awhile back to handle the same problem (fiddle: http://jsfiddle.net/LJRSL/) There's some extra stuff in there that's probably not necessary :)
$.preloadImg = function (url, callback, to_len) { //to_length = image fetch timeout in ms
var img = new Image(),
$img = $(img),
st = new Date().getTime(),
to;
if (callback && $.isFunction(callback)) {
to = window.setTimeout(function () {
callback.call(this, url, true);
}, to_len || 5000);
}
$img
.on('load', function () {
to = window.clearTimeout(to);
if ($.isFunction(callback))
callback.call(this, url, false);
})
.attr('src', url)
;
/*this is probably unnecessary*/
if (img.complete) {
$img.off('load');
if ($.isFunction(callback)) {
to = window.clearTimeout(to);
callback.call(this, url);
}
}
};
$.preloadImg('https://www.google.com/images/srpr/logo4w.png', function(img) { $('#test').attr('src', img); alert('done'); });
and for good measure loading multiple:
$.preloadImgs = function (urls, callback, to_len) {
var i = 0, c = 0;
for (; i < urls.length; i++) {
c++;
$.preloadImg(urls[i], function (url, timedout) {
if (--c === 0 && i >= urls.length - 1)
callback.call(this, urls);
}, to_len);
}
};
You might try binding your event via addEventListener instead of onload =
I faced a similar problem. I noticed that my image .onload was not being called if the page is reloaded normally, if I reloaded the page using f12 + right click reload button and chose Empty Cache and Hard Reload, the .onload was called.

Use Value of a Nested Callback as Return for Parent Function

So, I have this:
function isOnline(sURL) {
var bOnline,
oImage = document.body.appendChild( document.createElement("img") );
oImage.onload = function() {
bOnline = true;
};
oImage.onerror = function() {
bOnline = false;
};
oImage.src = sURL;
return bOnline;
}
... and I've had this problem before yet gotten around but I'm a little lost here. How can I get the value of bOnline to pass to isOnline at the right time? As expected, it returns undefined (initially). Any help would be appreciated.
It is always recommended to use callback functions in such situations as given below
var online = false;
isOnline("htp://....", function(){
online = true;
}, function(){
online = false;
});
function isOnline(sURL, onLoad, onError) {
var oImage = document.body.appendChild( document.createElement("img") );
oImage.onload = onLoad;
oImage.onerror = onError;
oImage.src = sURL;
}
I strongly advise you use a callback to continue your logic :
function isOnline(sURL, callbacks){
var bOnline,
oImage = document.body.appendChild( document.createElement("img") );
oImage.onerror = callbacks.error;
oImage.onload = callbacks.success;
oImage.src = sURL;
}
And instead of a call like this :
if(isOnline('some-src')) {
// good stuff
} else {
// bad stuff
}
you should use the function like :
isOnline('some-src',{
success : function(){
// yey! image is online
},
error : function(){
// eerror loading image. boo :((
}
});
If you still want to test at some point in time without using callbacks, you can return the actual image object and pin a ready or error flag on it :
function isOnline(sURL) {
var bOnline,
oImage = document.body.appendChild( document.createElement("img") );
oImage.ready = oImage.error = false;
oImage.onload = function(){
oImage.ready = true;
}
oImage.error= function(){
oImage.error = true;
}
oImage.src = sURL;
return oImage;
}
var img = isOnline('some-src');
// .. after some computing
if(img.ready) {
// yey image has loaded
} else if(img.error) {
// damn error :(
} else {
// still not loaded :-?
}

Categories