I have created a custom jQuery plugin that does some simple image resizing for my website. Here is the site: http://www.daemondeveloper.com/photography/gallery.php
As you can see, for debugging purposes I have made portrait images have an opacity of 0.5 and landscape images an opacity of 1. I classify images as portrait or landscape using this custom plugin:
(function($) {
$.fn.superFit = function(options) {
var $this = $(this);
var parent = $this.parent();
var parentW = parent.width();
var parentH = parent.height();
var imgW = $this.width();
var imgH = $this.height();
var imgRatio = imgH / imgW;
var parentRatio = parentH / parentW;
if(imgRatio < parentRatio) //We have a landscape image
{
//First set the height of image to be 100%;
$this.css('height', '100%');
imgW = $this.width();
parentW = parent.width();
//Now center the image
$this.css('margin-left', -(imgW/2)+(parentW/2));
}else{ //We have a portrait image
$this.css('width', '100%');
$this.css('opacity', '0.5');
}
}
})(jQuery);
I want portrait images to fill up the width of its parent but overflow off the bottom of the parent. This seems to be working fine. However, the panoramic images (there are 2) that should have a landscape classification are being looked at by the jQuery as a portrait. That is, until you refresh the page. If you click on the Gallery menu item or hit refresh, all of a sudden the plugin works and you can see the landscape images become opacity 1 and fill up the parent as they should.
So what is causing the jQuery to fire only after refreshing the page again?? I am guessing it must have something to do with the way the pictures are loaded or something.
Finally, here is the code that runs the plugin function:
$('#gallery ul li').each(function() {
var $frame = $(this).children('div');
var fw = $frame.width();
var fh = $frame.height();
$frame.children('img').superFit();
});
This is being ran on document.ready
UPDATE: Actually using refresh or F5 does NOT fix the issue. For some reason only when you click the Gallery menu item or get focus on the address bar and hit Enter does it work...
I am guessing it must have something to do with the way the pictures are loaded or something.
Yes, you won't be able to get the dimensions of an image before it is loaded. On refresh the images will load from cache before DOMready.
Instead, hook on the .load() event.
Related
Sorry in advance if this is a minor question, but I'm new to javascript. I'm writing code for a webpage with full-width color backgrounds. Essentially, what I'm trying to do is detect the height of the window, and then make sure that the color block is the size of the window. The function works well on page load.
The problem is when I shrink the window, the div height doesn't change with the window size. I get all sorts of errors, like graphics poking out from behind the div.
I think what I'm missing is a way to detect the height of the content within each div and resize the height accordingly.
You can see how it works at http://pressshoppr.com
Here's the code:
$(function(){
var windowH = $(window).height();
if(windowH > wrapperH) {
$('.fullWidthSectionBG').css({'height':($(window).height())+'px'});
$('.fullWidthSectionBGFirst').css({'height':($(window).height())-120+'px'});
}
$(window).resize(function(){
var windowH = $(window).height();
var wrapperH = $('.fullWidthSectionBG').height();
var newH = wrapperH + differenceH;
var truecontentH = $('.fullWidthSection').height();
if(windowH > truecontentH) {
$('.fullWidthSectionBG').css('height', (newH)+'px');
$('.fullWidthSectionBGFirst').css('height', (newH)-120+'px');
}
});
});
I am not sure I totally understand the effect you are going for here, but I would imagine that if your initial bit of code achieves it, all you have to do is reuse exactly that. Treat each resize as if the page had just loaded, and get the results you want, eg:
$(function(){
// encapsulate the code that we know WORKS
function init() {
var windowH = $(window).height();
if(windowH > wrapperH) {
$('.fullWidthSectionBG').css({'height':($(window).height())+'px'});
$('.fullWidthSectionBGFirst').css({'height':($(window).height())-120+'px'});
}
}
// call on page ready
init()
// ...and call again whenever the page is resized
$(window).resize(init)
});
I have this jQuery code which centralizes an image within a DIV horizontally and vertically:
var $itemImage = $('.a-img');
$itemImage.each(function() {
var $img = $(this);
var h = $img.height();
var w = $img.width();
$img.css('margin-top', +h / -2 + "px").css('margin-left',+ w/ -2 + "px");
});
It works when the page is first loaded. However, there's a link on the page that will show a pop-up box where you can update the photo. Once you click "Upload" on the pop-up box, the image on the main page will change without refreshing the entire page. The jQuery code that initially applied to the image no longer works (the image is no longer centralized).
How do I solve this problem?
Put this into a function, and call this function when you load the image. Oh, and this is JavaScript. Remove the $ on the variables: itemImage instead of $itemImage, img instead of $img.
As a quick explanation, I created an image that resizes to fill the background using this function which works great:
function resize_bg(element_id){
$("#"+element_id).css("left","0");
var doc_width = $(window).width();
var doc_height = $(window).height();
var image_width = $("#"+element_id).width();
var image_height = $("#"+element_id).height();
var image_ratio = image_width/image_height;
var new_width = doc_width;
var new_height = Math.round(new_width/image_ratio);
if(new_height<doc_height){
new_height = doc_height;
new_width = Math.round(new_height*image_ratio);
var width_offset = Math.round((new_width-doc_width)/2);
$("#"+element_id).css("left","-"+width_offset+"px");
}
$("#"+element_id).width(new_width);
$("#"+element_id).height(new_height);
return true;
}
So no problem for the full background image. The problem appears, when I change the image source using Javascript. In other words, I have 1 image set as background but on hover of certain elements on the page, the image changes but it doesn't change the resize right. So the first image on load is resized and positioned correctly, but when I switch the image using .attr('src',newimg) the image is not resized correctly even though I call the function again.
Here is the code I use to change the image and resize it:
$('#menu_work li a').hover(function(){
$('#content').hide();
var img_src = $(this).next('img').attr('src');
$('#full_screen_img').attr('src', img_src );
resize_bg();
$('#full_screen_img').show();
},function(){
$('#full_screen_img').hide();
$('#content').show();
});
Thanks for any help.
It appears that you have left out the element_id argument when calling resize_bg() in the hover event handler. As a result, resize_bg() can't find the element you want to resize.
#maxedison is right, you forgot to pass the element id.
Another problem is that when you change the src, the new image might not be loaded yet, so you won't get the right dimensions in resize_bg until it is.
In that case you'll need to resize the image once it's loaded:
$('#full_screen_img').attr('src', img_src ).load(function() {
resize_bg('<ELEMENT_ID>');
});
resize_bg('<ELEMENT_ID>');
On another note, I'd recommend you change resize_bg to get a jQuery object instead of an id, or even write a plugin ($.fn.resize_bg) if it's a functionality you want to use often.
I'm currently building a site and using the Shadowbox JS plugin to display images.
Because we serve up images via a JSP (rather than linking directly to image files), Shadowbox seems unable to dynamically determine their width and height and so just opens the images in an overlay of ~the screen size.
It's possible to manually pass in widths and heights to the shadowbox plugin using 'rel', so I've got around the problem for FF/Chrome/Safari using the following code:
$('#pic1img').attr("src")).load(function() {
picWidth = this.width;
picHeight = this.height;
});
$(window).load(
function() {
var w = $("#pic1img").width();
var h = $("#pic1img").height();
if( picWidth < w ){ picWidth = w; }
if( picHeight < h ){ picHeight = h; }
$('#pic1').attr('rel', 'shadowbox[pics];height=' + picHeight + ';width=' + picWidth);
}
);
But I can't find any way to do the same in IE.
The code actually worked once I began loading the thumbnails at full size and then setting their width and height after load.
The issue was that I was setting a surrounding div to
display: none
until the images were loaded and IE can't work out the sizes of hidden images.
Resolved this by setting
visibility: hidden
instead.
I've got a web application that loads some content from an external source to the dom via an ajax call, one of the things that comes back is a set of images (different sizes and aspect ratios) to be displayed in an profile photo section. I'd like for each of the images to be resized to fit within a 64px x 64px area and I'd like to maintain aspect ratio. I was able to do this in firefox, chrome, and safari, but I've no luck getting this to work in IE 7 or 8. The problem I've had is finding a jquery event that reliably gets triggered after the image loads since the image was added after the page load. Here's what works in the listed browsers:
$(window).load(function () {
$('.profileThumbnail').each(function (i) {
var divHeight = $(this).height();
var divWidth = $(this).width();
if (divHeight > divWidth) {
$(this).css('height', '64px');
$(this).css('width', 'auto');
}
else {
$(this).css('height', 'auto');
$(this).css('width', '64px');
}
divHeight = $(this).height();
var divParentHeight = $(this).parent().parent().height();
var divNewHeight = (divParentHeight - divHeight) / 2;
$(this).parent().css('top', divNewHeight);
divWidth = $(this).width();
var divParentWidth = $(this).parent().parent().width();
var divNewWidth = (divParentWidth - divWidth) / 2;
$(this).parent().css('left', divNewWidth);
});
});
I'm also trying to center (horizontally and vertically) them which is what the rest of that code does, but I think I've got all of that working if I can find a way to trigger this code after the image loads in IE.
keep in mind this needs to work both on the first visit (not cached) and subsequent visits (cached). I'm looking for a jquery, javascript, or css solution as I want to avoid the roundtrip/bandwidth for each image.
Have you tired to add a load event to the images yourself which triggers when the image is loaded? This is how image preloaders work.
var img = document.createElement("img");
img.onload = function(){ alert('loaded'); }
img.onerror = function(){ alert('error'); }
img.src = "foo.png";
You can add the onload to the image elements themselves if you are not doing the preload approach.
The problem I've had is finding a jquery event that reliably gets triggered after the image loads since the image was added after the page load.
Instead of setting an onload listener for the window, set an onload listener for the images you are loading remotely. Set the listener after you create the image object and before you insert it into the body. The listener can basically be all the stuff insife of the .each() in the code you posted,