0

This code is supposed to reposition gallery images inside of their square div boxes. All the images have a set height e.g. 100px. But their widths are different. Rather than only show the left-most 100px of every picture, I'd rather it show the center.

All I need is to go through each img and change the left property to shift the images left.

$('img.gall_imgs').load(function() {

    var $imgWidth = parseInt($(this).width); // "$(this)" or "this"? parseInt() needed?
    var $divWidth = parseInt($(this).closest('div').width);

    if($imgWidth > $divWidth) { // if img is wider than its containing div, we'll shift it left
        var $position = -1 * ($imgWidth/2 - $divWidth/2); // will give decimals?
        $position = parseInt($position) + "px"; // make $position format "123px". parseInt() needed here?
        // var $position = '-50px'; // tested with pre-set position
            this.css("left", $position); // "$(this)" or "this"?
        }
    //}
});

Also, I don't even know how to test variables values inside of jquery. I tried putting in an alert($imgWidth) but it obviously didn't work.

EDIT: Here is the CSS and HTML I have now:

.gall_thumb_img { // the div surrounding the img

    width:200px;
    height:200px;
    margin-left:auto;
    margin-right:auto;
    overflow:hidden;
    text-align:center; // just added this per suggestions. No effect

}
.gall_thumb_img img{ // the img
    position:absolute;

    display:block;
    height:200px;
    min-width:200px;

}

HTML:

<div id="gall_box">
    <div class="gall_thumb_box" id="gall_thumb_box_0" >
            <div class="gall_thumb_img" id="gall_thumb_img_0" >

                <a href="?c=ecards&v=single&idx=23&img_dir=nature">

                <img class="gall_img" id="img0" src="http://example.com/small.jpg?20111211044810"></a>
                </div>
    </div>
</div>

EDIT2: Here is what I've changed the jquery to based on various suggestions. Still no change in end result.

$(window).load(function() {
    $('img.gall_imgs').each(function() {
        var imgWidth = $(this).width(); // "$(this)" or "this"?
        var divWidth = $(this).closest('div').width();
        alert(imgWidth);
        if(imgWidth > divWidth) {
            var position = -1 * (imgWidth/2 - divWidth/2); // will give decimals?
            position = position + "px"; // make position format "123px". 
            // var position = '-50px'; // tested with set position
                this.css("left", position); // "$(this)" or "this"?
            }
    });
});

Text-align center is a good idea that I will use if I can get it to work, but I would still like to know why my jquery code is not working. Thank you.

Buttle Butkus
  • 9,206
  • 13
  • 79
  • 120

5 Answers5

1

Something like this

$('img.gall_imgs').each(function() {

var $imgWidth = parseInt($(this).width());
var $divWidth = parseInt($(this).closest('div').width());
Sudhir Bastakoti
  • 99,167
  • 15
  • 158
  • 162
  • But since they are images this has to be done after load. So would I just wrap $('img').load(function() {}); around the each function? – Buttle Butkus Dec 11 '11 at 12:43
  • Use $(window).load(function () { } ); instead, img.load would mean it repeats the each function after every image has loaded. – Dormouse Dec 11 '11 at 12:56
1

You can use the jQuery $.each function to go over all img tags and modify them.

You could also use a div with a background-image and background-position of 'top center' ? I think it would work as well for you with showing the "center" part of the image.

By the way, why are you using the $ sign in your vars?

Shai Mishali
  • 9,224
  • 4
  • 56
  • 83
  • 1
    "By the way, why are you using the $ sign in your vars?" Did I happen to mention that I have absolutely no idea what I'm doing? – Buttle Butkus Dec 11 '11 at 12:38
1

You need to .append the <img /> first, then try to get/set it's properties.

As stated in the comments below, If they are already on your page, you don't need to listen on the onload event. You should use jQuery.each to iterate through them.

Like so:

$(function(){
    $('img.gall_imgs').each(function() {

        var that = $(this);

        var $imgWidth = that.width();
        var $divWidth = that.parent().width();

        if($imgWidth > $divWidth) {
            var $position = -1 * ($imgWidth/2 - $divWidth/2);
            $position = $position.toString() + "px";
            that.css("left", $position);
        }
    });
});
Pierre
  • 18,643
  • 4
  • 41
  • 62
  • I don't think I need to append anything. There are multiple pictures per page. Each is in the class "gall_imgs". I need to modify them, not append anything. – Buttle Butkus Dec 11 '11 at 12:39
  • 1
    If they are already on your page, why listen on the `onload` event ? You should use `jQuery.each` to iterate through them. – Pierre Dec 11 '11 at 12:43
  • I need this to run as soon as the page is loaded, so I have to tie it either to .load or .ready, right? From what I've read, you can't get an img's width property until all the imgs are downloaded. ".ready" runs before imgs are downloaded, so it wouldn't work. Either way, though, I don't think .load vs .ready is my problem, is it? It's something else. – Buttle Butkus Dec 11 '11 at 12:58
  • this might help you: http://stackoverflow.com/questions/263359/how-can-i-determine-if-an-image-has-loaded-using-javascript-jquery – Pierre Dec 11 '11 at 13:02
  • +1 for posting the .each() function, but I tried your code and it did not work. I'm not sure why, but are you sure you can use that.closest().width??? Isn't that mixing jquery "closest" with javascript "width". I've found the solution and will post it myself. – Buttle Butkus Dec 12 '11 at 07:26
  • I was based on your code, answer updated. I think you meant to use `parent()` rather than `closest()`. – Pierre Dec 12 '11 at 08:50
  • Thanks, but my code was wrong, which is why I was asking the question! The code in my answer works perfectly. – Buttle Butkus Dec 12 '11 at 09:09
0

You don't needed intParse and width is a jQuery function so you must write 'width()':

$('img.gall_imgs').load(function() {

    var $imgWidth = $(this).width();
    var $divWidth = $(this).closest('div').width();

    if($imgWidth > $divWidth) {
        var $position = Math.round(-1 * ($imgWidth - $divWidth) ) + "px";
        $(this).css("left", $position);
    }
});

A different (and better) option is to use the css attribute "text-align: center;". Inside the divs the images are inside so it works because the images displays inline into its container.

P.D.- "alert($imgWidth);" must show you its value, otherwise the execution is not reaching this line of code.

francadaval
  • 2,451
  • 3
  • 26
  • 36
  • Thanks, I added text-align: center to the CSS as shown above, to no effect. I will gladly use it if it works, but even so I would still like to find out why the jquery isn't working. – Buttle Butkus Dec 11 '11 at 12:56
  • The alignment will not work while image position is absolute. – francadaval Dec 11 '11 at 14:16
  • In your edit you have not used Math.round() to avoid decimals and you are doing 'this.css(..' instead of '$(this).css(...' Have you tested 'position' value before call to css? – francadaval Dec 11 '11 at 14:20
0

The other answers on here had some clues, but they hardly changed the code I supplied and none of them worked. So I am going to answer my own question and post what worked.

This function will center images horizontally inside a div that has fixed width with overflow set to hidden, and it activates upon image load. Without this function, only the left N pixels, where N is the width of the containing div, would be visible. With this function, the center N pixels are visible instead.

$(window).load(function() {
    $("img.gall_img").each(function() {
        var imgWidth = $(this).width(); // use "$(this)" b/c "width()" is jquery
        var divWidth = $(this).closest('div').width();
        //alert(imgWidth + " and " + divWidth);
        if(imgWidth > divWidth) {
            var position = Math.round(-1 * ((imgWidth/2) - (divWidth/2))); // round up to next integer
            position = position + "px"; // make position format "123px". parseInt() needed here?
                $(this).css("left", position); // use "$(this)" b/c "css()" is a jquery function (otherwise, could use "this")
            }
    });
});

Things I learned.

  1. "$(document).ready" does not work here. Must use "$(window).load" because the ready function triggers before images are loaded. To manipulate image position and size, you have to wait till they are fully loaded.
  2. $(this) = this, except that you use $(this) when you want to access jQuery functions (like width() and css()) and properties.
  3. $("tag").each: loops through the collection of tags (or other objects) specified, applying the code within "each()" to each member of the collection in turn. Use "this" or "$(this)" inside to refer to the current member.
  4. It's hard to debug jQuery using Google Chrome.
Buttle Butkus
  • 9,206
  • 13
  • 79
  • 120