jQuery select images above the fold - javascript

I am currently using the jQuery lazyload plugin to load images. I am using javascript to replace the src and data-original attributes. This causes a slight flicker on load. I am wondering if there is a way with jquery to select only the images below the fold or above the fold so that I can avoid this flicker.
var $imgs = $("img:not(.nolazy)");
$imgs.each( function(){
var imgSrc = $(this).attr("src");
$(this).attr("data-original",imgSrc).attr("src","gray.gif");
});
$imgs.lazyload({
effect : "fadeIn"
});
Edit: #Jason Sperske great answer. This is the code that I have resolved the flickering issue with:
var wH = $(window).height();
var $imgs = $("img:not(.nolazy)");
$imgs.each( function(){
var imgPosition = $(this).offset();
if(imgPosition.top > wH){
var imgSrc = $(this).attr("src");
$(this).attr("data-original",imgSrc).attr("src","gray.gif");
}
});
$imgs.lazyload({
effect : "fadeIn"
});

While there is no built in selector for this purpose you could iterate over them and look for position values that are greater than the window height. Ben Pickles (his SO profile) has implemented this into a filter called onScreen which you can use like a selector (note that it will still fetch all elements, but then pair down the list before you attempt to modify them, so the selector won't be any faster (actually slightly slower), but the reduced set of elements will be faster to update).

Related

How to make a grid of interactive elements?

I'm trying to create a portfolio website that resembles this, a full-page grid of images that change when you hover over them... (another example, the third screen!)
And currently I have a crude solution that looks like:
<img src="1.png" id="img" swap="2.png"/>
// then in JS...
$("#img").hover(function(){
var _this = $(this);
var current = _this.attr("src");
var swap = _this.attr("swap");
_this.attr('src',swap).attr('swap',current);
}); //
code credit
But this isn't a very scaleable solution and other than having 1000 images, each with their own unique ID which is identified so the src can be toggled, I'm not sure what to do -- plus I don't know how this would react to different display sizes/screen cut-offs. And while background-image in CSS tiles nicely, it doesn't allow interactivity... unless maybe you had a JS script track cursor position(?)
!! This is my very first project, any help would be appreciated :) (Codecademy is a very sheltered learning environment........)
you don't have to use ids and create a handler for every image.
this will apply to every image CURRENTLY on the page:
$("img").hover(function(){
var _this = $(this);
var current = _this.attr("src");
var swap = _this.attr("swap");
_this.attr('src',swap).attr('swap',current);
});
and this will react to every image, even images added after the page is loaded:
$(document).on('hover', 'img', function () {
var _this = $(this);
var current = _this.attr("src");
var swap = _this.attr("swap");
_this.attr('src',swap).attr('swap',current);
});
To account for screen sizes and your other concerns, you'd need to either set a fixed width and height on your images, or make sure all your images are of similar resolution.
You could do this with backgrounds as well by creating a grid of divs then change the background of the div on hover, similar to the above handlers.

Change Another Image On Link Hover

The output in HTML is something like this:
ProductImage1 ProductImage2 ProductImage3 ProductImage4
Color1 Color2 Color3 Color2 Color4 Color5 Color6
What I want to do is when I hover my mouse over any color above, an original (current) image of ProductImage will change to another one (to match the hovered color). And that original image will be back when mouse leaves.
Here is the javascript I've done for hovering over each ProductImage.
var sourceSwap = function () {
var $this = $(this);
var newSource = $this.data('alt-src');
$this.data('alt-src', $this.attr('src'));
$this.attr('src', newSource);
}
$(function () {
$('img.main').hover(sourceSwap, sourceSwap);
});
UPDATE
I excluded unnecessary parts from my question. The answer from #hunter worked very well when I tested it here jsfiddle.net/4dK2x/27. However it didn't work when I combined it with my php parts to create dynamic lists. I'm still looking around and trying to find out the problems. I will come back and update my answer if I find a solution for it.
Here's updated code which should work with as many sets of products as you need if you mimic a similar html structure
$('.image .toggles img').hover(function () {
var src = $(this).attr("src");
var $main = $(this).closest(".image").find(".main");
$main.attr("toggle", $main.attr("src")).attr("src", src);
},
function () {
var $main = $(this).closest(".image").find(".main");
$main.attr("src", $main.attr("toggle"));
});
Example: http://jsfiddle.net/4dK2x/1/
You could do this two ways, you can try it by using CSS:
#tagName{
background: url("yourImage.jpg");
}
#tagName:hover{
background: url("anotherImage.jpg");
}
this assumes you have a div tag around the image, you can also reference class id's etc. (read into CSS for more details).
or you could do it through JavaScript
lets say you are not using JQuery (i need to familiarize myself more with JQuery)
var image1 = document.getElementById("nameofDivTag");
//on hovering kinda forgotten the JS version of hovering, JQuery has probably easier way
image1.style.background("url:("aDifferentImage.jpg"));
if i am wrong yay! if not yay!
hope it helps

hide() vs hide("slow")

I need to hide a div and, with this code it works fine:
var idObj = $(this).attr('key');
var valH = $(this).attr('hideval');
var valS = $(this).attr('showval');
if ($('div[name='+idObj+']').attr('isdisplay') == 'no') {
$('div[name='+idObj+']').children().show("slow");
$('div[name='+idObj+']').attr('isdisplay','yes');
var divTitle = $('div[name='+idObj+']').children().first();
var divArrow = $(this).children().first();
//.attr('src',prefixImg+valH);
//divTitle.show();
//divArrow.show();
$(this).children().first().attr('src',prefixImg+valH);
} else {
var divTitle = $('div[name='+idObj+']').children().first();
var divArrow = $('div[name='+idObj+']').children().last();
//.attr('src',prefixImg+valS);
$('div[name='+idObj+']').children().hide();
$('div[name='+idObj+']').attr('isdisplay','no');
divTitle.show();
divArrow.show();
$(this).children().first().attr('src',prefixImg+valS);
}
My div is hidden and the Title and arrows to reopen the div are shown. But if I try to use hide("slow") the divTitle and divArrow don't appear when my div is closed. Same problem using hide(1000).
Is there a difference between hide with and without "slow" parameter?
thanks,
Andrea
From the official site
The matched elements will be hidden immediately, with no animation. This is roughly equivalent to calling .css('display', 'none'), except that the value of the display property is saved in jQuery's data cache so that display can later be restored to its initial value. If an element has a display value of inline, then is hidden and shown, it will once again be displayed inline.
When a duration is provided, .hide() becomes an animation method. The .hide() method animates the width, height, and opacity of the matched elements simultaneously. When these properties reach 0, the display style property is set to none to ensure that the element no longer affects the layout of the page.
So, if hide is used without delay, it hides immediately without animating - eg, poof.
If it's used with time, it becomes animated, so it disapears over time.
For your problems, it is difficult to judge without the corresponding html code.
$(element).hide() hides an element instantly, where $(element).hide('slow') will animate its disappearance (slowly).
It looks like (though I'm not sure) you want to do stuff after the animation is finished. In that case, do something like this:
var that = this; // here to preserve scope for the block below
$('div[name='+idObj+']').children().hide('slow', function() {
// This stuff happens after the hide animation is done.
$('div[name='+idObj+']').attr('isdisplay','no');
divTitle.show();
divArrow.show();
$(that).children().first().attr('src',prefixImg+valS); // <= note "that" instead of "this"
});
According to the jQuery documentation
The strings 'fast' and 'slow' can be supplied to indicate durations of
200 and 600 milliseconds, respectively.
Also duration in milliseconds can be supplied to it..

How to get the image width and height using Javascript?

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;
},

How to find out the dimension of the lightbox?

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).

Categories