user1645438
user1645438

Reputation: 23

jQuery: add classes according to image proportions

Hello,

I am trying to add classes to each image depending to its proportions (landscape/portrait/square). This code works in JSfiddle but not on the website (locally or on server):

$(document).ready(function()
{
    $('img').addClass('wide');
    $.each($('img'), function()
    {
        var image = $(this);

        if (image.height() > image.width()) {
            image.removeClass('wide');
            image.addClass('tall');
        } else if (image.height == image.width()) {
            image.removeClass('wide');
            image.addClass('square');
        }
    });
});​

Here is my JSfiddle: http://jsfiddle.net/LYxv6/ .

Upvotes: 2

Views: 1682

Answers (6)

Nathan
Nathan

Reputation: 11149

I would do something like this:

(function ($) {
    $.fn.proportions = function (options) {
        options = $.extend(options, {
            wideClass : 'wide',
            tallClass : 'tall',
            squareClass : 'square'
        });
        addProportions = function () {
            img = $(this);
            var ratio = img.width() / img.height();
            if (ratio > 1) {
                return img.addClass(options.wideClass);
            }
            if (ratio === 1) {
                return img.addClass(options.squareClass);
            }
            return img.addClass(options.tallClass);
        };
        return this.each(function () {
            if ($(this).width() !== undefined) {
                addProportions.call(this);
            } else {
                $(this).on('load', addProportions);
            }
        });
    };
}(jQuery));

jQuery(function ($) {
    jQuery('img').proportions();
});​

Putting it in a plugin makes it re-usable. And instead of using window.load as jsfiddle is doing, I've attached the function to each image's load event, so that the class is added immediately.

Upvotes: 0

Alnitak
Alnitak

Reputation: 339836

The reason your code works on jsfiddle is because the site has (by default) wrapped your code in an onload handler. This handler is called once all the images have loaded, unlike $(document).ready() which only waits until the DOM structure is complete.

The function to change the classes is trivial if you take advantage of the version of addClass that takes a function parameter instead of a string:

$(window).on('load', function() {
    $('img').addClass(function() {
        if (this.height === this.width) {
            return 'square';
        } else if (this.height > this.width) {
            return 'tall';
        } else {
            return 'wide';
        }
    });
});

In the callback this is the <img> element itself, and you can directly access its .width and .height properties without having to use jQuery.

This should be far more efficient than repeatedly calling jQuery functions inside a .each() loop.

Upvotes: 5

jtheman
jtheman

Reputation: 7491

Changed to $('img').each and missing paranthesis at image.height() (this is a function)

$(window).load(function() {

$('img').addClass('wide');

$('img').each(function() {
    var image = $(this);

    if (image.height() > image.width()) {
        image.removeClass('wide');
        image.addClass('tall');
    }
    else if (image.height() == image.width()) {
        image.removeClass('wide');
        image.addClass('square');
    }

});

});

Upvotes: 1

sajawikio
sajawikio

Reputation: 1514

On your server on local system, make an .html file.

Change it to document load, put in missing braces for one of the width parts - and make sure the .html file looks like the below:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset=utf-8 />
    <title></title>
    <script>
       $(document).load(function() {

    $('img').addClass('wide');

    $.each($('img'), function() {
        var image = $(this);

        if (image.height() > image.width()) {
            image.removeClass('wide');
            image.addClass('tall');
        }
        else if (image.height() == image.width()) {
            image.removeClass('wide');
            image.addClass('square');
        }

    });

});​
    </script>
    <style>
    img{
height:250px;
}
.wide{
border:10px solid #aed;

}
.tall{
border:10px dashed #dea;

}
.square{
border:10px dotted #ade;

}​
    </style>
    </head>
    <body>
    <img src="http://24.media.tumblr.com/tumblr_m9t0dwyu0P1qjfsubo1_500.jpg"/>
    <img src="http://24.media.tumblr.com/tumblr_m9iqv8oQl01qcpwsso1_500.jpg "/>
    <img src="http://25.media.tumblr.com/tumblr_m9n4kyf8aA1r1thfzo5_1280.jpg"/>  
    </body>
    </html>
​

You may replace <style></style> and <script></script> with <link rel="stylesheet" type="text/css" href="yourstyle.css"/> and <script type ="text/javascript" src="jquerywhatever.js"></script><script type ="text/javascript" src="YOURSCRIPT.js"></script>

Upvotes: 0

Barlas Apaydin
Barlas Apaydin

Reputation: 7315

Try to use variables in if else if statements:

Here is jsFiddle.

    var biggerVal = image.height() > image.width();
    var equalVal = image.height() == image.width();

    if ( biggerVal ) {
        image.removeClass('wide');
        image.addClass('tall');
    } else if ( equalVal ) {
        image.removeClass('wide');
        image.addClass('square');
    }

Same problem on this question: How to build simple sticky navigation with jQuery?

Upvotes: 0

Dr.Molle
Dr.Molle

Reputation: 117334

You should run this script on

$(window).load()

...otherwise(on ready) it may happen that the images are not loaded yet and the size is still unknown when you access them.

You also forgot some parentheses here:

else if (image.height == image.width()) {

should be

else if (image.height() == image.width()) {

Upvotes: 1

Related Questions