views:

117

answers:

2

I am using a function to equalise the height of li tags returned from a database. I am also using jquery to assign certain li new classes dependant on their position in a row.

Basocally my problem is that the positioning part of the jquery statement always works but the equal heights part will sometimes not fire, in fact it generally doesn't work on an empty cache - it will however always fire on refresh or second visit to the page.

Live example here Link here!(let me know if it works for you!)

The jquery code I am using is listed below.

    jQuery.fn.equalCols = function(){
    //Array Sorter
    var sortNumber = function(a,b){return b - a;};
    var heights = [];
    //Push each height into an array
    $(this).each(function(){
     heights.push($(this).height());
    });
    heights.sort(sortNumber);
    var maxHeight = heights[0];
    return this.each(function(){
     //Set each column to the max height
     $(this).css({'height': maxHeight});
    });
};

jQuery(document).ready(function($) {
        $(".thumbs").each(function(i) { 
        if (i % 4 == 0) 
           $(this).addClass("start");
        if (i % 4 == 3) 
           $(this).addClass("end");
    });
    $(".thumbs").each(function(i) { 
        if (i % 3 == 0) 
           $(this).addClass("start");
        if (i % 3 == 2) 
           $(this).addClass("end");
        });
    $(".event_thumbs").each(function(i) { 
        if (i % 2 == 0) 
           $(this).addClass("start");
        });
$('.thumbs, .end, .start').equalCols();
});

If you have an better suggestions for the code or methods to achieve the aim please shout out or if you know how to make it work - I love you.

+2  A: 

Perhaps an issue with not wrapping this in jQuery on the last loop? Also, you only need to keep track of the maximum seen so far as you iterate. Putting the heights into an array and sorting it seems inefficient.

jQuery.fn.equalCols = function(){
    var maxHeight = 0;
    $(this).each(function(){
        var height = $(this).height();
        if (height && height > maxHeight) maxHeight = height;
    });

    return $(this).each(function(){
        //Set each column to the max height
        $(this).css({'height': maxHeight});
    });
};

Update: Since you have images on the page, it's not enough to wait until the document is loaded, you also need to wait until the images are loaded as well. Or, better yet, simply equalize after every image is loaded -- that way you're certain to do so after all of them are. Since the load handler won't be called if the image is loaded before it is applied (e.g., it may be in the user's cache and load more quickly than the javascript executes), set up a timer to fire the equalCols function after a specified amount of time to cover the case where the load handler isn't invoked for any image. Leave the load handler on the image, then if you change the source to the image it will be reapplied and the page equalized again.

 $(function() {
     $('img').load( function() { /* equalize after every image load */
          equalize();
     });
     setTimeout( equalize, 2000 );  /* wait 2 secs, then equalize */
 });

 function equalize() {
     $('.thumbs, .end, .start').equalCols();
 }
tvanfosson
this appears to work initially although I will do some more in depth testing when I get home - work kinda sucks for browsers and testing! Many thanks!
DanC
unfortunately this doesn't seem to have solved the issue - just checked on a new browser with a clear cache and the problem is still there - damn!
DanC
Is it possible that the "columns" hold images? If so, you'd need to delay firing the equalCols function until all the images have finished loading. With a collection you'll need to keep track of how many loads you expect and also trigger the resizing after some amount of time just in case the loaded event fires before your handler has been applied.
tvanfosson
The reason to wait is that the div will change size as the images are loaded. If you fire on document load and the images aren't loaded the size of the divs may be 0. Waiting until after the images have loaded will wait until the divs are their final size.
tvanfosson
that makes sense - how would I delay the firing till the images have loaded?
DanC
I added to my answer -- I think the easiest way is to equalize after every image is loaded **and** equalize after the handlers have been applied (to cover the case where images were loaded before the handlers were applied). I'm doing it with a timeout to avoid any race conditions since I'm not sure if a load handler works if applied while the image is loading. You might experiment with using the timeout or not to see if there is a difference.
tvanfosson
+1  A: 

I did somehting like this for auto-heights to match based on class... works cross browser, though it may need to be updated or plunized.

 function level_it(elem_class)
 {
      var s = 0;
      var t  = 0;
      $('.'+elem_class).each(function(){
      if($(this).height() < s)
      {
         s = $(this).height();
      }
      if($(this).height() > t)
      {
           t = $(this).height();
      }
  });
  $('.'+elem_class).each(function(){
    $(this).height(t);
  });
}
$(document).ready(function(){
  level_it('pricing');
});
Phil Palmieri