Retrieve naturalWidth of updated image src - javascript

$(".photo").on('click', function(){
this.src = this.src.replace(/thumb/g, 'original');
alert(this.naturalWidth);
}
I am using jQuery in Rails4 to update the src attribute of an image. I am also using paperclip for image uploading.
The flow: when I click the image in the first time, it returns the thumb width(140px). However, the subsequent clicks return the natural width of the original image(1200px).
Is it possible to get the natural width of the original image in the first time?

Wait for the image to be loaded. onload handler will be invoked when image has finished loading
This event will fire every time src property of the image is changed.
Try this:
$(".photo").on('click', function() {
this.src = this.src.replace(/thumb/g, 'original');
var img = new Image();
img.onload = function() {
alert(this.naturalWidth);
}
img.src = this.src;
}

$(".photo").on('click', function(){
$("<img/>")
.attr("src", $(this).attr("src"))
.load(function() {
alert(this.width)
alert(this.height)
});
});

Related

JQuery: How to hide an image until source changed

I have an image that is being resized programmatically, based on the current height/width of the container. My problem is that it shows the image at it's original size before it does the resizing.
See this JSFiddle
You'll notice how it flashes up a stretched image before it fits the image nicely in the middle.
I want to hide the image until that resizing has taken place, but I can't figure out how.
Any suggestions?
JSCode:
function LoadImg(img) {
img.css('visibility','hidden');
var src=img.attr('src');
var imgh = img.parent().height();
var imgw = img.parent().width();
var pattern = /&?(w|h)=[^&]+/g;
src = src.replace(pattern, '');
img.attr('src', src + '&w=' + imgw + '&h=' + imgh);
img.css('visibility','');
}
Html:
<div class="window">
<img src="http://www.angclassiccarparts.co.uk/image_anysize.aspx?f=/images/ww/panel/service_kits.jpg&w=154&h=154&color=png" id="img" onload="LoadImg($(this));" />
</div>
I've tried hiding with visibility hidden until the function has run, but that doesn't wait for it to load...
You're changing the source of the image, which forces it to load a new image, then you instantly set the image to visible.
Ultimately you want to wait until the second image is loaded before showing it, which can be achieved using .load() like so:
img.on('load', function() {
img.css('visibility','visible');
});
Here's an updated jsFiddle with the working code: http://jsfiddle.net/ev4YL/2/
I would, however, recommend a different approach. It doesn't make much sense to load an image, then when it's loaded load another image. Perhaps you should store the dimensions in html data attributes, then load the images dynamically on document.ready.
Something like this could work, if you set each image to have a data-src instead of src to begin with:
$('img').each(function() {
var img = $(this);
var src = img.attr('data-src');
var imgh = img.parent().height();
var imgw = img.parent().width();
var pattern = /&?(w|h)=[^&]+/g;
src = src.replace(pattern, '');
img.attr('src', src + '&w=' + imgw + '&h=' + imgh);
img.on('load', function() {
img.css('visibility','visible');
});
});
And the demo here: http://jsfiddle.net/ev4YL/4/
You can hide the image with display: none until the end of the function, then set the image to display: block (or whatever you need) at the very end. That way the rest of the function has already run, when it displays it will have already been resized.
See JSFiddle
But basically just:
CSS:
img {
display: none;
}
JavaScript:
function loadImg(img) {
----all of your function here----
img.css('display', 'block');
}

How to preload images

I'm trying to preload images on my web page. I've seen a lot of discussions about it and most of them suggest to create an Image object then edit the src attribute. However this doesn't work on the latest versions of Chrome and Firefox. The request is marked as "pending" until the image is actually shown on the page and then I can notice a little delay before the image to be shown. Even creating an actual img tag on the page (with display:none) doesn't work until the image is shown. And finally when I try the following code, only the last image of the loop is actually loaded
var img = document.getElementById('some_visible_image');
for(var i=1;i<5;i++)
for(var j=1;j<3;j++){
img.src = 'images/'+i+'_'+j+'_green.png';
img.src = 'images/'+i+'_'+j+'_orange.png';
img.src = 'images/'+i+'_'+j+'_red.png';
}
So how can I reduce the loading time of the images (without using large sprites)?
You need to create instance for every image
// redirect after all the images are preloaded
function redirect() {
location.href = "yourtargetpage.html";
}
// should solve the first-time-load problem
var loads = 0;
function loaded() {
// the total number of images needed to load
if(++loads==42) redirect();
}
// if all the images aren't loaded in 3 seconds, don't wait further
setTimeout(redirect, 3000);
for(var i=1;i<5;i++)
for(var j=1;j<3;j++){
var img = new Image();
img.src = 'images/'+i+'_'+j+'_green.png';
if(img.complete) loaded(); // if cached, onload isn't fired sometimes
else img.onload = loaded; // fires for the first time the page loads
}
or the src is overwritten before the image has a chance to load.
To show your images immediately after the first load, you may run this script on a different page, wait until every image
I found the solution, thanks to Jan Turoň's answer. Here is my code :
for(var i=1;i<=5;i++)
for(var j=1;j<=3;j++){
var img = new Image();
img.src = 'images/'+i+'_'+j+'_green.png';
var img = new Image();
img.src = 'images/'+i+'_'+j+'_orange.png';
var img = new Image();
img.src = 'images/'+i+'_'+j+'_red.png';
var img = new Image();
img.src = 'images/'+i+'_'+j+'_grey.png';
}
Try visibility:hidden; instead of display:none;

Resize HTML canvas after loading image

See http://jsfiddle.net/jdb1991/6sxke/
I've got a canvas element that doesn't know what it's going to be used for until an image has loaded, so I need to be able to change the dimensions of the element on the fly, after creating the image object.
Something is going wrong though, as it seems to be running the commands asynchronously; writing the image to the context before the resize occurs.
use:
function objectifyImage(i) {
var img_obj = new Image();
img_obj.src = i;
return img_obj;
}
var canvas = document.getElementById('display');
var context = canvas.getContext('2d');
i = objectifyImage('https://www.google.co.uk/images/srpr/logo3w.png');
i.onload = function() {
canvas.width = i.width;
canvas.height = i.height;
context.drawImage(i, 0, 0);
};
​
demo: http://jsfiddle.net/ycjCe/1/
The element can be sized arbitrarily by CSS, but during rendering the
image is scaled to fit its layout size. (If your renderings seem
distorted, try specifying your width and height attributes explicitly
in the attributes, and not with CSS.)
source: https://developer.mozilla.org/en-US/docs/Canvas_tutorial/Basic_usage
It appears i = objectifyImage will set the image src before the image.onload handler is defined. This will cause cached images to get loaded on some browsers prior to the onload definition. Its a good idea to always define onload handlers before setting the image.src to avoid timing issues with cached images.
var self = this;
.....
this.img = document.createElement('img');
this.img.onload = function () {
self.loaded = IMGSTATE_OK;
$Debug.log('loaded image:"' + self.img.src);
}
this.img.onerror = function () {
self.loaded = IMGSTATE_ERR;
$Debug.log('error image:"' + self.img.src);
}
this.img.src = href;
..... later on check the load state

Set an Image object as a div background image using javascript

I want to load 4 images from background showing a load bar to the client
and when the images will be downloaded i want to set them as background images to 4 div blocks.
I am looking for something like this.
var myImages = new Array();
for(var i = 0; i < 4; i++)
myImages[i] = new Image();
//load images using the src attribute
//and execute an on load event function where to do something like this.
var div0 = document.getElementById('theDivId');
div0.style.backgroundImage = myImage[index];
Is there any way to set a background image using an Image javascript object?
You can do something close to what you had. You don't set an image background to be an image object, but you can get the .src attribute from the image object and apply that to the backgroundImage. Once the image object has successfully loaded, the image will be cached by the browser so when you set the .src on any other object, the image will load quickly. You could use this type of code:
var imgSrcs = [...]; // array of URLs
var myImages = [], img;
for (var i = 0; i < 4; i++) {
img = new Image();
img.onload = function() {
// decide which object on the page to load this image into
// this part of the code is missing because you haven't explained how you
// want it to work
var div0 = document.getElementById('theDivId');
div0.style.backgroundImage = "url(" + this.src + ")";
};
img.src = imgSrcs[i];
myImages[i] = img;
}
The missing part of this code is deciding which objects on the page to load which image into when the image loads successfully as your example stood, you were just loading each one into the same page object as soon as they all loaded which probably isn't what you want. As I don't really know what you wanted and you didn't specify, I can't fill in that part of the code.
One thing to watch out for when using the .onload event with images is you have to set your .onload handler before you set the .src attribute. If you don't, you may miss the .onload event if the image is already cached (and thus it loads immediately).
This way, the image shows up instantly all in one once it's loaded rather than line by line.
function setBackgroundImage(){
imageIsLoaded(myURL).then(function(value) {
doc.querySelector("body > main").style.backgroundImage = "url(" + myURL + ")";
}
}
function imageIsLoaded(url){
return new Promise(function(resolve, reject){
var img = new Image();
try {
img.addEventListener('load', function() {
resolve (true);
}, false);
img.addEventListener('error', function() {
resolve (false);
}, false);
}
catch(error) {
resolve (false);
}
img.src = url;
});
}

swapping images of different sizes [Javascript vs IE]

I have the following simple preloading function which substitute an image "src" attribute with another image (an animated GIF "Loading"). The problem arises only in IE: if the "loading" GIF is smaller than the actual image src, that will be resized. For example if I have a square 100px image and preload it, the image is temporarly substituted by an animated GIF of 50x50px. Whem the original image is fully loaded it is NOT displayed at its size, but at the smaller 50px. Here is the code, if you need it
_preload = function(url, placeholderUrl) {
var img = new Image();
loading = true;
var placeholder = new Element("img", {
src: placeholderUrl
});
img.placeholder = placeholder;
img.onload = function(evt) {
this.placeholder.src = this.src;
loading = false;
}
img.src = url;
return placeholder;
}
Here you can see the visual error
You should be able to adjust the width/height of the image within the callback function:
img.onload = function(evt) {
this.placeholder.src = this.src;
this.placeholder.width = this.width;
this.placeholder.height = this.height;
loading = false;
}
Example: Resizing image onLoad
I guess replacing placeholder with img (the img-elements inside the dom), instead of simply changing the src-attribute of placeholder, should fix this issue.

Categories