I want to load only certain images from HTML DOM, based on image width and height.
I dont know how to access the width and height properties of a image using JavaScript.
This must run under any browser.
My app is a bookmarklet, so all the images will be loaded by the time a user will start the bookmarklet. So, i will only scan the DOM, get all the img srv values, and use them. The trick is that i dont want all the images, just the ones that match my wanted sizes.
I have this code so far, and it gets all the images from DOM :
var imgObj = document.getElementsByTagName('img');
for(var i=0;i<imgObj.length;i++)
{
imgsList[i] = imgObj[i].getAttribute('src');
if(consoleLog)console.log(imgsList[i]);
}
return images = imgObj.length;
my problem has been solved here: How to get image size (height & width) using JavaScript?
But i dont know how to adapt my code to img.clientWidth
Is it imgsList[i].clientWidth ?
imgObj[i].clientWidth, imgList contains a list of just the src attributes.
Be careful when using any widths and heights of images as they load asynchronously into the browser. This means that when the DOM loads the width and height will be 0. Only after the images themselves finish loading will the element have a width and height appropriately set.
To get around this you can have load handlers whose callback will be executed once the image finishes loading.
Again though a slightly odd behaviour is that a browser that caches the image will not call this load function again (at least not ones in jQuery) and so you need to make sure for cached versions you do any width checks in a DOM load callback.
You can do this in standard javascript however as an example and since I have a jQuery example in front of me which I was working on earlier I will show you how it can be done in jQuery.
Suppose the image has an id=imageid
function checkWidths() {
//do anything you want here
//jQuery uses the .width and .height functions to get the appropriate attributes of an element, these return a value without the px % etc. To get the actual css use .css('width') instead.
}
$(document).ready(function() {
if($('#imageid').width() > 0)
checkWidths();
});
$('#imageid').load(function() {
checkWidths();
}
To know the dimensions of an image, you need either :
to have the image loaded (then clientWidth is OK if your script is executed in an onload callback)
to have them specified as attributes (<img src=... width=33>). In this case use imgObj[i].getAttribute('width');
Note that if you want to reload an image and avoid all cache problems, the simplest is to change its URL, for example like this :
var srcbase = imgObj.getAttribute('src').split('?')[0];
imgObj.src = srcbase + '?time='+(new Date()).getTime();
(this supposes the image is defined by the path until the '?')
This is it guys, and it works perfect.
populateImgsList : function()
{
var imgObj = document.getElementsByTagName('img');
var j = 0;
for(var i=0;i<imgObj.length;i++)
{
if(consoleLog)console.log('w '+imgObj[i].clientWidth+' h: '+imgObj[i].clientHeight);
if( (imgObj[i].clientWidth>100) && (imgObj[i].clientHeight>100) )
{
imgsList[j] = imgObj[i].getAttribute('src');
if(consoleLog)console.log(imgsList[j]);
j++;
}
}
return images = imgList;
},
Related
I inherited a project where a page is loaded, then code attached to that page fills in a div with dynamically generated html - it basically fills an existing div with a html string.
This string contains links to images, etc.
I want to tell when all the images, etc have loaded- I cannot seem to get any jQuery standard checks
to work - ie I have tried attaching $(window).load() after the dynamic stuff has been inserted.
I am wondering if I should write $(window).load() dynamically as well, or if there is any other
method- ie $("#thediv").load (doesn't seem to work. I cannot query all the new html for image tags, etc-
too much stuff is being put in.
The $(window).load() doesn't work for dynamic content as far as I know. You can use the .load event for each image separated. Here's an example:
var container = $("<div> ... Stuff ... </div>");
var images = container.find('img');
var imageIdx = 0;
images.load(function(){
imageIdx++;
if (imageIdx == images.length){
callback();
}
});
Where callback() is the function that runs after all images where loaded.
From my comment: window load applies to the initial page load only. Not dynamic loading of content within it. Attach load handlers to each loaded image element and count them.
This is the shortest version I could come up with for you:
// After HTML load finishes
var img = 0;
var imgCount = $("#thediv img").load(function(){
if (++img == imgCount){
// We are done loading all images!
}
}).length;
$(window).ready() only applies to the content within the HTML file and you can only use load to attach an onload event handler to a specific image (not a container), something like this might work for you.
window.ImageLoadHandled = false;
window.ImageLoadCount = 0;
function ImageLoadHandler() {
// guard against calling this function twice
if(window.ImageLoadHandled) return;
window.ImageLoadHandled = true;
// All images have loaded || timeout expired...
}
$("#myAjaxedDiv img").load( function() {
window.ImageLoadCount++;
if( window.ImageLoadCount == $("#myAjaxedDiv img").length ) {
// all images in #myAjaxedDiv have loaded
ImageLoadHandler();
}
});
// if images haven't loaded after 5 seconds, call the code
setTimeout( ImageLoadHandler, 5000 )
The only problem with this is that if an image fails to load for whatever reason, the code will never be hit, which is quite risky. To counteract this I'd recommend creating a setTimeout() method to call your code after a few seconds timeout in-case there is a problem loading images (client or server side) and I've also taken #TrueBlueAussie's correction into account in the edit.
Your alternative is to preload the images with your HTML page
I'm trying to scrape images from a url, and only allow the user to pick images that are of a certain size. I was having issues getting this to work good with Nokogirl, and thought about just proceessing it client side with jquery when the page to select the image's appears. For some reason, it isn't working 100%
.select_product is the name of the image class that renders images for the user to select.
$(document).ready(function () {
$("img").load(function () {
$(".select_product").each(function () {
var width = $(this).width();
if (width < 100) {
$(this).hide();
}
});
});
});
This js works, but for some reason it always see's the width on the "this" as having a width < 100, when in fact some images are certainly higher.
load event is fired once for every image, supposing you have 10 images, it's fired 10 times and when the first image is loaded the handler is executed even if other images are not loaded yet, you can listen to the load event of the window object instead:
window.onload = function() {
$(".select_product").filter(function() {
return $(this).width() < 100;
}).hide();
}
But I would read the images' width on the server-side instead of loading and then hiding them, also note that jQuery load() event method as of jQuery 1.8 is deprecated.
I have run into numerous sites that use a delay in loading images one after the other and am wondering how to do the same.
So i have a portfolio page with a number of images 3 rows of 4, what i want to happen is for the page to load,except for the images in img tags. Once the page has loaded i want images 1 of each row to load then say 0.5 seconds later the next image in the row(s) and so no. I'm going to have a loading gif in each image box prior to the actual image being displayed.
I know its doable but cant seem to find the term for doing this. This is purely for looks as it is a design site.
Thanks for the help.
This is very easy to do in jQuery
$('img').each(function(i) {
$(this).delay((i + 1) * 500).fadeIn();
});
Fiddle: http://jsfiddle.net/garreh/Svs7p/3
For fading in rows one after the other in a table it just means changing the selector slightly. Remember to change from div to img -- I just used div for testing
$('tr').each(function(i) {
$('td div', this).delay((i + 1) * 500).fadeIn();
});
Fiddle: http://jsfiddle.net/garreh/2Fg8S/
Here is what you can do, you can load the image tags with out the src and using a custom property:
<img alt='The image' path='image/path.jpg' />
then you can use javascript to load the images when the site is loaded or whenever you please;
// simplified
window.onload = function () {
var images = document.getElementsByTagName('img');
// loop and assign the correct
for (var i =0; i < images.length;i++){
var path = images[i].getAttribute('path');
images[i].src = path;
}
}
I hope you get the concept of how the images are delayed
**please note the path attribute is not a standard one.
The easiest way I can think to do this is to have a table set up that will eventually hold the image tags, but have none on load. Javascript can loop through an array of image urls, and insert those image tags into random locations on the table.
If you want to have the delay, setInterval is the perfect tool. http://www.w3schools.com/jsref/met_win_setinterval.asp
// You can hard-code your image url's here, or better still, write
// a server-side script that will read a directory and return them
// so it is fully dynamic and you can add images without changing code
unpickedImages = array();
// Start loading
loadAllImages = setInterval( insertImage, 600 );
function insertImage() {
if( unpickedImages.length > 0 ) {
var imageUrl = unpickedImages.shift();
// pick empty x, y on your table
// Insert the image tag im that <td></td>
} else {
clearInterval( loadAllImages );
}
}
You really don't need javascript to do this. If you specify the image sizes in the HTML or CSS, the browser will layout and display the page while loading the images, which will likely be loaded in parallel. It will then display them as soon as it can.
That way if users re-visit your site and have the images cached, they all show up immediately. If you have a script to load the images after a delay, you are making visitors wait for content unnecessarily and all their efforts to have a faster browser and pay for a fast internet connection has gone to waste.
i have certain links, on mouse over of those links I am changing <div> background image
jQuery I have used is-
function imgchange()
{
$('.smenu li').mouseover( function(){
var src = $(this).find('a').attr('href');
$('.hbg').css('background-image', 'url(' + src + ')');
$(this).find('hbg').attr('title', 'my tootip info');
});
}
It is working fine but the problem is when I running it on server images takes 3-4 sec to be changed on change, but the second time I do mouse over images are getting changed instantly, I think this is because of browser stored images in cache. So I added one javascript to preload images on page onLoad() ivent -
<script language = "JavaScript">
function preloader()
{
heavyImage = new Image();
heavyImage.src = "images/soluinfo1.jpg";
heavyImage.src = "images/soluinfo2.jpg";
heavyImage.src = "images/soluinfo3.jpg";
heavyImage.src = "images/soluinfo4.jpg";
heavyImage.src = "images/soluinfo5.jpg";
heavyImage.src = "images/soluinfo6.jpg";
heavyImage.src = "images/soluinfo7.jpg";
}
</script>
<body onLoad="javascript:preloader()">
but this script has not solved my problem.what should I do?
#Richard's answer (sprites) is probably the best one for what you are after, but the reason your code is not working is that in most browsers, only the last heavyImage.src="" is given enough time to actually register with the browser as an actual request. You're creating only one Image object setting and resetting the .src attribute faster than the browser can request the files (I think modern JavaScript engines take the added step of removing all the intermediate .src statements specifically because of this).
There are a couple of ways to fix this. The easiest is to create multiple Image objects, one for each image. And the easiest way to do that is through something like this:
<script type="text/javascript">
function preloader()
{
function doPreload(strImagePath)
{
var heavyImage = new Image();
heavyImage.src = strImagePath;
}
var arrImages = ["images/soluinfo1.jpg","images/soluinfo2.jpg","images/soluinfo3.jpg","images/soluinfo4.jpg","images/soluinfo5.jpg","images/soluinfo6.jpg","images/soluinfo7.jpg"];
for (var i = 0; i < arrImages.length; i++) {
doPreload(arrImages[i]);
}
}
</script>
By putting the heavyImage variable inside its own function (remember to use the var keyword), you're ensuring that the Image object exists inside its own dedicated scope.
Another way to do this is to attach a "load" event listener to a single heavyImage. Every time the image finishes loading, go fetch the next image. The disadvantage to this method is that your images will be loaded one at a time (bad for navigation images, but great for, say, and image gallery), whereas the first technique will fetch the images in parallel (typicallly four at a time).
You might find it easier to change your approach and use CSS sprites (and another article). Then you would just have one image referenced, and you use CSS to set which part of that image gets shown in which scenario.
This assumes that the images you're using are under your control and you can use an image editor to combine them into one large image.
About the lightboxes. The box adjusts its dimension to match the picture. Question is how do the box find out the size of the picture?
To answer the comment about detecting when its done loading, i believe you can use the onLoad event. in jquery this would look somthing like:
$('img').attr('src', 'uri/for/image').load(callbackFunction);
or manually:
var tmp = new Image();
tmp.onload = callbackFunction;
tmp.src = 'uri/for/image';
your callbackFunction could then use $(this).height() and $(this).height() safely. so your callbackFunction is where you would have the actual logic to trigger the rest of your implementation.
in alot of cases if seen this callback (or its equiv. implementation) simply set a global variable and then somewhere else in the code youll see polling of this variable every N ms. and when its set it will trigger the rest of the script.
I assume something akin to:
imgWidth = $(img).width();
imgHeight = $(img).height();
It would load the image in a hidden element (or positioned off screen), get the dimensions, animate the container to fit, then expose the image (usually via some sort of transition/animation).