Setting img src only works on second attempt - javascript

I suspect this question may not meet the SO criteria as it's not reproducible. If I could reproduce it I'd probably know what was causing the issue.
I am trying to add an image to the DOM via js. I set the images src in the code and then mount it. The problem that I have is that, when only setting the src and mounting it, the image doesn't load. The element is there, but it has no size, and there was no network request for the image. the onload and onerror never fire either. The img is there and the src is correct, but no image is rendered, the size is 0x0.
It's created and mounted like this:
const image = new Image();
image.src = "my-url-here";
document.querySelector("a").after(image);
I can get this working in two ways. Set the src to blank first and then what I intend it to be:
const image = new Image();
image.src = "";
image.src = "my-url-here";
document.querySelector("a").after(image);
or by preloading the image elsewhere:
// immediately:
const image = new Image();
image.src = "my-url-here";
// ...
// some other place:
const image = new Image();
image.src = "my-url-here";
document.querySelector("a").after(image);
Either works fine and are somewhat viable, though not really preferrable solutions. My question, though, is this; why is this happening? I can't reproduce it anywhere else and so it's maybe specific only to the page I'm looking at (in which case perhaps there's not much help available).
If that's not answerable, then perhaps the question is, where can I look to try and get some information on this because it's incredible difficult to know where to start with this one.

Related

JavaScript, set same image source to different images (preload)

Sorry, maybe not correct title..
I have the next question: I want to make preloading with progress bar. And I stuck on one problem.
[CODE 1]:
//Preloader code
var img = [];
img[0] = new Image();
img[0].src = 'test0.jpg';
img[0].onload = function(){
//some code
}
//.....
img[100] = new Image();
img[100].src = 'test100.jpg';
img[100].onload = function(){
//some code
}
//.....
// all images loaded
//.....
/*
for expample in this part of code I need put my image 'test0.jpg' into html
*/
var temp_img = new Image();
temp_img.src = 'test0.jpg';
The question is : will it download 'test0.jpg' again or just take it from cache?
or better to do like this [CODE 2]:
//Preloader code
var img = [];
img['test0'] = new Image();
img['test0'].src = 'test0.jpg';
img['test0'].onload = function(){
//some code
}
//.....
img['test100'] = new Image();
img['test100'].src = 'test100.jpg';
img['test100'].onload = function(){
//some code
}
//.....
// all images loaded
//.....
/*
for expample in this part of code I need put my image 'test0.jpg' into html
*/
var temp_img = img['test0'];
// draw temp_img
I want to use CODE 1. But will it slow down my app? Or better to use CODE 2? Thanks in advance.
Both methods have benefits and drawbacks.
The first method is much lighter on image elements and as a general rule, the fewer DOM elements you generate, the better. There is a chance, though, that the browser will not serve the image from the cache depending on how much information is being loaded. Worst case, you will need to fetch from the network again if the browser has removed the image from the cache.
The second method is much safer and will keep the image held in memory, meaning even if the browser doesn't cache it, it's still available. It's heavier on image elements, though.
Which solution is better depends on your situation. If you're not loading a large amount of images, I'd say solution 1 is the better choice as it leverages the browser's cache. If you really can't afford to reload images off the network, though, solution 2 is safer.
TL;DR
Solution 1 shouldn't slow down your application, but solution 2 will ensure you don't fetch from the network again.
With code 1, your preloader would be useless right? I'd go with 2

JCanvas.createPattern randomly returning 'Null' instead of actual pattern

Now my entire project is too big for a copy and paste, but here is a basic breakdown of what I'm doing right now:
$(document).ready(function(){
var canvas = $('#Canvas');
var data = {source: "images\pattern.png", repeat: "repeat"} ;
var pattern = canvas.createPattern(data); //Returns 'Null' at random
});
Things I've looked at so far:
Loading time (Somewhat related, it seems to break more often when the page loads faster)
Loading order (Doesn't seem related)
Preloading the image by forcing it to an on-page image beforehand (Doesn't fix it )
Preloading it using Image() and passing the image path to Image().src (doesn't fix it either)
Passing the Image() as data.source instead of a string path (might have helped just a little)
Initting JCanvas beforehand (No function seems to exists for this)
Creating the pattern as early or as late as possible (Seems to change the frequency, but not by a lot)
It seems to have a mind of it's own and I can't figure out what I'm doing wrong. Anyone have a clue as to what I'm doing wrong?
-Edit1-
Debugging through the Jcanvas source right now and I think it has something to do with the context. Is there any way for me to preload the canvas context?
-Edit2-
Forget everything I've said about the context, I think I figured it out.
//JCanvas source
[...]
else {
// Use URL if given to get the image
img = new Image();
img.crossOrigin = params.crossOrigin;
img.src = source; //<-- source is the url of my image ("images\pattern.png")
}
// Create pattern if already loaded
if (img.complete || imgCtx) {
onload(); //<-- When this runs, the image pops up perfectly fine
} else {
img.onload = onload(); //<-- This is what causes the problem,
//onload never seems to actually run
// Fix onload() bug in IE9
img.src = img.src;
}
The img.onload event should happen directly after an image loads, but it never seems to happen.

javascript image object not work in chromica

I want to get width of an external image with javascript.
I try this code :
var image = new Image();
image.src = "1.jpg";
alert(image.width);
but it get image width in firefox and get 0 in chrome.
why it not work in chromica?
Try
image.onload = function() {alert(this.width);}
You're trying to get the width before the image has been downloaded. You have to wait, e.g.:
var image = new Image();
image.onload = function() {
alert(image.width);
};
image.src = "1.jpg";
Note that it's important to hook onload before you set src, because otherwise you have a race condition. Even though JavaScript is single-threaded on browsers (unless you use web workers), the browser is not. It can fire the load event as soon as you set src and, seeing no handlers, not queue them for callback.

Graphics BitMapFill TypeError

I'm working with the easeljs javascript to make a sort of game.
I'm using this example: http://www.createjs.com/#!/EaselJS/demos/game
As you can see there are spacerocks. This are graphics objects:
this.graphics.beginStroke("#FFFFFF");
I would like to fill the background with an image like this:
var bitmap = new createjs.Bitmap("http://nielsvroman.be/twitter/root/easeljs/image.png");
this.graphics.beginBitmapFill(bitmap, "no-repeat");
But I always get this error:
Uncaught TypeError: Type error
Does anybody know what I'm doing wrong?
Use a reference to an HTML Image, and not a Bitmap instance.
var image = new Image();
image.srce = "http://nielsvroman.be/twitter/root/easeljs/image.png";
this.graphics.beginBitmapFill(image, "no-repeat");
Note that you have to ensure the image is loaded, otherwise it may not show up on the first stage update. You can either tick the stage, or listen for image onload, and refresh the stage then.
image.onload = function() {
stage.update();
}

Preloading images in HTML, is there a more modern way?

I have an image loaded by JS on a mouse event. It's a fairly big image so I want to make sure it gets pre-loaded. I reemmber some old techniques from years ago and found this example:
<SCRIPT LANGUAGE = JAVASCRIPT>
if (document.images)
{
img1 = new Image();
img2 = new Image();
img1.src = "imageName1.gif";
img2.src = "imageName2.gif"
}
</SCRIPT>
I wondered if this is still good/relevant, or maybe browsers automatically detect unused images and preload them anyway? Note my page has to support IE6, so I might still need older techniques anyway, but I'm still interested if more modern browsers have a better way?
Nope, this is it. Why change something that works?
But a more proper usage is like this
(function() {
var img1 = new Image();
var img2 = new Image();
img1.src = "imageName1.gif";
img2.src = "imageName2.gif"
})();
or just
new Image().src = "imageName1.gif";
new Image().src = "imageName2.gif"
Both of these avoids cluttering the global scope with variables.
And language="JavaScript" is deprecated. Use type="text/javascript".
Depends what kind of images you are talking about, icons/buttons etc. could be done using a technique called CSS Sprites.
http://www.alistapart.com/articles/sprites
That's interesting. I was asking myself the exact same question recently. Another method would be to create a DOM element for each element and wait until you need to display it before injecting it into the document body. For example,
var img1 = document.createElement('img');
var img2 = document.createElement('img');
img1.setAttribute('src','imageName1.gif');
img2.setAttribute('src','imageName2.gif');
...and then later, when you know the images are ready to be inserted...
document.getElementById('imagePlaceholder1').appendChild(img1);
document.getElementById('imagePlaceholder2').appendChild(img2);
This does result in the file getting 'pre-loaded' in the modern browsers I tested and it may actually be more consistent with your own coding styles, but I'm still worried that some browsers might not load the image at the time of the element creation but wait until it's added to the document body. So I opted to use the exact solution you mentioned. At least until the next update to ECMAScript, there's nothing wrong with "old code" (at least old code like new Image()). It works and it was intended to work this way. I don't think it's particularly hacky.
[Edit] The second block of code should be made to execute when you are sure the images have loaded and/or when the user does whatever it is you expect him or her to do that triggers its appearance.

Categories