I'm trying to solve image is loading 2 times for a single preview
1st time image will be loaded for preview purpose in iframe
2nd time image metadata such as width, height will be fetched with same path
Below image shows 2 times loading same image:
in both the call 8.9kB,8.6kB will be loaded i want to avoid that.
Question: I want to calculate image aspect ratio with single load of image. 2 calls i need to avoid
Note: i want iframe based solution
Here is demo: https://codepen.io/eabangalore/pen/rNLWJWE?editors=1010
For reproducing: we need to disable cache
Please help me thanks in advance!!!
The way you asked your question is very frustrating because you have created arbitrary "limitations" (eg. iframe, disabled cache) but don't describe why those limitations are necessary. Looking at your code it's clear that you don't have much experience working in the web/javascript, so it would be really nice if you told us what you needed as opposed to how to do it. We could probably come up with a much better solution for you.
Anyhow, to answer your question the way you asked... what you need to do is load the resource ONCE outside of an image tag or iframe (in memory), base64 encode the result, and use the encoded data for both the iframe src and the image src. Here's the pseudocode:
// this first line will load the image
const imageData = fetchImageAsDataUrl('http://path-to-your-image');
// these next two lines use the existing image data from above
// you will see two entries in the "network" tab with urls like "data:image/jpeg..."
// but there was no additional data transferred across the internet
iframe.src = imageData;
img.src = imageData;
const dimensions = getImgDimensions(img)
If you look at the network tab, you will see that only one image is transferred over the internet (the first circle). The next two circled entries happen because the iframe/img src attributes are set, but the data was not loaded over the internet (notice how the url starts with data:image/jpeg...).
Here's the codepen:
https://codepen.io/DesignByOnyx/pen/gOMKYzL?editors=1010
The browser is generally speaking smart enough to not fetch the same asset twice from the server, this is called caching. The checkmark Disable cache in your devtools is checked, meaning it will not use cache. This can be useful while developing but you can trust that people generally will not disable cache.
I also don't see the same behaviour on the codepen.
The only way you would be able to achieve this using an iframe is if you have control over the domain it is loading or there are means by which you can enable cross origin resource sharing. That way you will be able to access the DOM contents of the iframe and retrieve the needed information from the image element in there.
Another solution is to avoid using iframe in the first place which doesn't make much sense in the example you have given, but you've said you prefer it to stay that way.
And still worth mentioning, as stated in the other answer, the browser will most likely not fetch the image twice anyway so you don't need to worry about that.
Related
So, I wanted to avoid the cache to see images I'm uploading to this website I'm working on, which I access through localhost.
I hit a handy solution pretty quick:
Attaching to the end of image's path ?random= and a random number generated by Math.floor(). All this with the help of a script.
The HTML showed in the browser:
<img class="gallery_img" src="./uploads/4.jpg?random=172">
Awesome, it works beautifully.
Now, the thing that has been hard to find is an explanation of why and how this actually works.
I mean, 1) how the browser still finds the image in the server with this new path?
Or asked the other way around, 2) how the server handles this ?random=172 attachment and delivers the image asked before that?
If somebody could point me to the right direction I would be grateful.
Solution:
Have a look on what are query parameters.
And if you are dealing with the problem of avoiding the cache, have a look here:
Disable cache for some images
That is not part of the path, that is a query parameter.
And most of the times the server of images does not care about query parameters, at least not a literally random one, maybe it would support a query parameter called width or size and dynamically generate an image of the correct size. But random is most likely simply discarded and the image is served normally.
I've found a lot of techniques to preload images both with CSS and JS, but none of them was able to REALLY preload images the way I need, or more specifically in the order I need.
Simply put the browser will preload all images and stuff in one block, but the order in which each image will be downloaded by the browser is totally on his own calculation, mostly (and totally reasonably) the top most elements in the document will be downloaded first.
Unfortunately this is quite true in my tests with <img> elements only; for other elements with something like background images it's not really like that, even if the images are used as background for the <body> element for example.
The only solution this far that worked the way I needed was to place some <img>elements right after the <body>tag and set them with style="display:none". This is working, but rather ugly and terribly rough way imo to achieve this.
I'm also a bit concerned for SEO, since bots will find right at the start of the document some hidden images just for this purpose (I'm mostly preloading images for preloaders effects like "loading.." with a small logo image).
I was quite charmed with a super brilliant solution I saw to preload images with a pseudo element on the body like this body:before and then use multiple background images. While this technique indeed works to preload, it won't effect the loading order priority... very sad it's so perfect! :(
Isn't there really any other way to force to preload stuff with top priority over the rest of the assets without cluttering the top of the document with hidden images?
UPDATE
As I explain in the comments below, I'm not concerned in having the images loaded in a particular order, I want them to be downloaded BEFORE the most part of the assets and other item in the "download" chart, so that the images will render almost instantly inside the browser along with normal CSS layout rendering when the page is accessed.
UPDATE 2
More info: the term "preload" is indeed misguiding, a more close term for what I'm looking for could be "prefetch" but basically it goes like this:
Most browsers download 6 requests in parallel at a time, holding up the rest of the downloads. If what you "really" need is in this top 6, you are lucky, else it in the next 6, or maybe the one after and so on.
What I'm trying to do is find a proper way to tell "hey download this first please" and in particular "this image".
As pointed out by #farkas in the answers below rel="subresource" is indeed a good start but as pointed here, it works mostly as "[..]suggests it’s actually downloaded as a lower priority than stylesheets/scripts and fonts but at an equal or higher priority than images", so it will indeed be loaded first than many other things, but still no proper way to break in those 6 gold top spots.
As you can see, the browser downloaded first the styles, THEN 1 of the images I needed loaded ASAP, then the scripts, leaving out the other 2 images I needed to be downloaded with top priority.
To be noted tho that I've placed all my scripts not in the head, they are all placed at the bottom before the closing </body>, and also (as stated on top of my question) I've marked my images RIGHT AFTER the opening <body> tag, but only dark-pattern.jpg has been downloaded first, the other 2 were postponed
...
</head>
<body>
<img src="dark-pattern.jpg" style="display:none">
<img src="preloader.jpg" style="display:none">
<img src="xs-style.png" style="display:none">
.. rest of code
...
I'd like to know a proper way to say, "please have a spot for my pictures, just download the stiles, the script can come later".
Is it possible to achieve this?
I've found some more detail on this matter in here too, but nothing on my specific request apart rel="subresource"
http://www.stevesouders.com/blog/2008/03/20/roundup-on-parallel-connections/
http://sgdev-blog.blogspot.it/2014/01/maximum-concurrent-connection-to-same.html
http://andydavies.me/blog/2013/10/22/how-the-browser-pre-loader-makes-pages-load-faster/
PS. if all this thing has a specific technical name, please let me know so I finally can give the beast a name, thanks :P
Loading images using CSS or JS, will be always slower then using HTML. This is due to the fact that CSS and JS is loaded and parsed after HTML. Additionally to that, the browser optimizes this by using a speculative preload parser.
So if your images are already in HTML, you won't reorder your img downloads, if you add a preload script for those images.
Therefore you have basically two options:
Load images as soon as possible by adding them top (either with your hidden img or using link rel="subresource" (Chrome only)
Delay loading all other non-crucial assets using a lazyloader
Try this:
var all = ['img1.jpg','img2.jpg'];
function onAllImagesLoaded() { alert('loaded!'); }
function preload() {
var i = new Image();
var src= all.pop();
if (!src) {
onAllImagesLoaded();
return;
}
i.src = src;
i.onload = preload;
}
preload();
There are some issues with cached images in IE, sometimes it may omit onload call for cached resources.
Edit
You can also use nice plugin designed to track all images loading (but it doesn't preserve images order, all images are loaded simultaneously):
http://imagesloaded.desandro.com/
If you make a new image and define is source do you need to preload? For example:
var image = new Image();
image.src = 'data:image/jpeg;base64,/9j/4Q+sRXhpZgAATU0AKgAAAAgABw...';
// Append image to canvas.
I've been doing some tests but I'd rather rather have reliable evidence, so links would be nice.
Thanks
EDIT: Actually I may have been wrong apparently different browsers behave differently in this respect and although the image is available information such as it's width and height aren't necessarily. I assume this is because the browser functions that calculate this information are non-blocking and assume you are listening to onload.
So yes listen to the onload event to ensure that a dynamic image has been loaded by the users browser before attempting to use it.
Based on information from: Should setting an image src to data URL be available immediately?
Ignore the following advice (it remains to provide context to my answer):
By storing it as a variable you are in a way preloading it. All that happens when you preload an image is it's data is retrieved and stored. You have already stored it's data in a variable - what is there to preload?
Because variable assignment is synchronous the image will be available to your code that follows.
The whole point of preloading is the fact that an image is usually at a different location on the server and that loading of separate files is often asynchronous thus you ensure that your script waits for the image to be downloaded. By creating your image inline you are effectively storing it in the JavaScript file and it will be downloaded at the same time.
so you select an image via the file input, the selected image file gets gets turned into a window.url.createobjecturl and passed to a hidden "img" element unmodified, then a preview of the image element's current data is rendered into a canvas element. so far, so good. but then when i try to render the canvas.toDataURL i keep getting that aggravating security exception about it being insecure. this happens on chrome and firefox.
understand that this is a file OBJECT that was select with an html INPUT element, and NOT via a "file://" url, and the webpage is an actual webpage, and is loaded via "http://" and not via "file://".
the image file has not even left the browser yet to go to the server, so there should not be any domain issues. it's just a raw blob being asserted as the source to an image, which is then telling the canvas to update its preview, which it does. after that, when trying to saved the canvas contents, the browser triggers an error.
i have read all of the specs regarding scenarious where the canvas element becomes tainted, and this scenario does not meet ANY of those scenarios.
i've seen a similar example on mozilla demos of some one offering code snippets to show people how to do the same thing, but i have not seen if any one had problems with it.
any ideas? TIA
#
=== UPDATE ===
#
okay, i've figured out what the PROBLEM is, but i'm still not clear on WHY it's a problem. here's the setup:
1) page is called via, eg, "example.com/"
2) script is called via: "r.example.com/script.js"
3) if script loads ANY image from "r.example.com", to use for the PAGE DESIGN, and NOT the canvas, it some how taints the entire page. in this case i draw the entire page via javascript, so the header image is tainting the rest of the page. if i change the header image to come from "example.com" instead of "r.example.com", the problem with the canvas complaining about not being secure goes away, and everything is fine.
what i don't understand is WHY this is happening. the header image is being loaded from the same place as the javascript file, and, for the sake of argument i even set the access-control-allow-origin to "*", for both the main domain and the subdomain, which makes no difference.
so, access control is allowed from anywhere, the header image is coming from the same place as the javascript file, and it is NOT being drawn to the canvas (that's a user file), so why would drawing the header image via javascript taint a canvas that it has nothing to do with??? also, the css and other media are loaded from the same subdomain, but this does not affect the page, so long as the script did not load them [o_0].
i want to keep all of my resources on a separate subdomain for scalability, so, this issue is frustrating, because i don't quite understand why it's still happening...
If you want your image to be on a separate subdomain, you have to change the origin of the image to allow all subdomains like this:
img .origin = '*.mydomain.com'
I'm using canvas with kineticJS and just tested it myself.
it appears that you have to set this property on the image object itself, as it has no domain initially [o_0]
img.origin = 'mydomain.com'
I want to make a javascript (or jQuery if that's a possibility) button for my HP which stops the loading of the images on the page (for example when a user has to pay per MB and is only interested in the text).
I searched and searched and found answers like "remove the src", or "use window.stop()", but the problem is that they don't work, cancel the whole loading process, or simply don't do what I had in mind (like removing the images completely).
Does anyone know how I could achieve that?
Thank you very much :)
PS.: found a how to that claims that it can stop the download of specific parts of the site, but it doesn't really explain how to specify the part. I don't get how to link things here so here's the url: http://www.ehow.com/how_6104889_kill-browser-downloads-javascript.html
Thanks again.
Short answer: don't bother. If a user has such limited bandwidth that loading images is a problem, they will have disabled images anyway, or they will use some mechanism to load images on demand. You don't want to burden users with a non-standard solution that only works on your homepage. Simply put, it is not your problem.
Long answer: you can use placeholders instead of actual images on the initial page load, and then use Javascript to set the src attributes one by one, having each successful load trigger the next image. You will lose parallel loading though, which means you are punishing high-bandwidth users (which is the overwhelming majority these days) with much longer loading times, and you'll be spending a lot of effort on a feature that is (see short version) mostly useless.
You could try to change src to point to an empty image.
You won't be able to cancel the image loading process programmatically from within the web page.
You could try breaking all image srcs using JavaScript but it's a dirty approach, and your results may vary - it could be that the browser continues to load the resource nevertheless.
The best way to go would probably be either loading images on demand (which is possible to do from within the page), or offer the option of serving pages from server side that don't contain the images in the first place.
However, as #tdammers correctly points out in his answer, it's probably best not to bother. People on a traffic quota will take their own precautions against loading too much content.
I wouldn't bother replicating a browser configuration option with an in-page button, but I would recommend showing a placeholder image then lazy-loading the images for mobile users.
Also as you like JQuery, there are jQuery Lazy-Loading plugins out there.