1.29.2008

Another take on a jQuery.equalizeCols plugin

Using CSS, it is very difficult to create multiple columns with the same height. One must use Javascript to modify <div> height so multiple div share the same height.

This blog post offer a jQuery plugin to do that. However, this particular script cannot be applied many time to the same elements. I had to adjust the height of multiple column that have their content updated with some Ajax requests. So I needed to be able to readjust the height of the columns after the content has been updated. Using the script from the post, my column would grow after each update.

I did like how it was adjusting the height of the column. It add a div with the missing height to all the columns that needs to be adjusted.

So I came up with the following script. This script can be applied many times to the same elements without any adverse effects.

   1: jQuery.fn.equalizeCols = function() {
   2:     jQuery(this).filter(function() {return jQuery(this).find(".auto_fill").length == 0;}).each(function() {
   3:         jQuery(this).append(jQuery("<div class='auto_fill'></div>").height(0));
   4:     }).css("height", "auto");
   5:     
   6:     var max_height= 0;
   7:     jQuery(this).each(function() {
   8:         var self= jQuery(this);
   9:         var height= self.height() - self.find(".auto_fill").height();
  10:         max_height=height > max_height ? height : max_height;
  11:     });
  12:     
  13:     jQuery(this).each(function() {
  14:         var self= jQuery(this);
  15:         var height= self.height() - self.find(".auto_fill").height();
  16:         self.find(".auto_fill").height(max_height - height);
  17:     });
  18: }
 

On line 2-3, an empty <div> is added to each element that may have their height adjusted. The <div> has an initial height of 0 pixels. Note that then <div> will be added only if the containing <div> does not already have this empty <div>.

On line 6-11, the maximum height is calculated.

On line 13-17, the empty div height is adjusted so the total height of the containing div is equal to the previously calculated maximum height.

So to adjust the height of some elements, you just have to do this :

   1: $(".columns").equalizeCols();

1.18.2008

Fixing attachment_fu on Windows

Like many others, I've encountered issue when developing Rails applications using attachment_fu on Windows. After doing some research, I've come up with the following solution to the problem.

The problem has two parts :
  1. Size is not included in the list error message,
  2. Timeout error when uploading to S3.

Fixing "Size is not included in the list" error message

Some people have reported that there is a timing issue, when trying to get the file size, with Tempfile on Windows. It seems that the size of the file is not properly reported by Windows after writing data to it. Proposed solutions for this problem include :
  1. Sleeping in a loop as long as the file size is 0,
  2. Reading back the entire file in memory.

I think I found a better and less patchy solution for this issue: forcing the OS to flush the file to disk before reading it's size.
Here is the code to do it :
require 'tempfile'
class Tempfile
def size
if @tmpfile
@tmpfile.fsync # added this line
@tmpfile.flush
@tmpfile.stat.size
else
0
end
end
end

Doing a flush is not enough... flush will flush the Ruby buffer but the file may not be immediately written to the disk by the OS. Doing the fsync ensure that the file is written to disk by the OS before continuing. After that, Windows will properly report the actual file size.

Fixing the Timeout error when uploading to S3

This issue is related to opening files for reading on Windows. On Windows, you have to open the file in binary mode. So patching attachment_fu is simple :
require 'technoweenie/attachment_fu/backends/s3_backend'
module Technoweenie
module AttachmentFu
module Backends
module S3Backend
protected
def save_to_storage
if save_attachment?
S3Object.store(
full_filename,
(temp_path ? File.open(temp_path, "rb") : temp_data), # added , "rb"
bucket_name,
:content_type => content_type,
:access => attachment_options[:s3_access]
)
end

@old_filename = nil
true
end
end
end
end
end

I've also included a fix from someone else (which was not enough in itself to solve my S3 upload problem):
module Technoweenie
module AttachmentFu
# Gets the data from the latest temp file. This will read the file into memory.
def temp_data
if save_attachment?
f = File.new( temp_path )
f.binmode
return f.read
else
return nil
end
end
end
end

Wrapping it up

So I put all this code in lib/attachment_fu_patch.rb and required it in environment.rb.

Problem fixed!

Note, I did not test it on other OSes, but these fixes should not have any adverse effects.

AdSense Links