2 things I like in prototype 1.6.1

March 31st, 2009 by Andrea Franz

The stable version of prototype is 1.6.0.3. I just fiddled around with the edge version (1.6.1_rc2) and I found 2 new features I really like. The first one is the Element#clone method. At last I can easily clone an element, or make a deep clone of it passing true as first argument:

<div id="genres">
  <div class="genre">
    <select name="genre[]">
      <option>Your favorite genre...</option>
      <option>Death Metal</option>
      <option>Black Metal</option>
      <option>Speed Metal</option>
    </select>
  </div>
</div>
<a id="add-genre" href="#">Add</a>
document.observe("dom:loaded", function() {
  $("add-genre").observe("click", function(event) {
    event.stop();
    var genres = $("genres"); 
    genres.insert(genres.down(".genre").clone(true));
  });
});

Just click the Add link to add a new the select tag.

Another cool new feature is the Element Storage. You can store any kind of data inside a element, and retrieve it when you need it.

Here an example:

<div id="items">
  <div class="item" id="item-1">
    <h1>Item 1</h1>
    <a href="#" class="save">Save</a>
  </div>
  <div class="item" id="item-2">
    <h1>Item 2</h1>
    <a href="#" class="save">Save</a>
  </div>
</div>
document.observe("dom:loaded", function() {
  var item = $("item-1");
  var data = item.retrieve("data", {});
  data.url = "http://cowboys.from.hell/items/1";			
 
  $("items").select("a.save").invoke("observe", "click", function(event) {
    alert(event.target.up(".item").retrieve("data").url);
  });
});

Just click the first save link and an alert will display the url I previously stored inside the first item element.

Given what I’m seeing I’m pretty excited about the upcoming version of prototype.


Terror the micro aggregator

March 17th, 2009 by Andrea Franz

Terror is a micro feed aggregator made with sinatra and bundled as a gem. It’s very simple to use, just install the gem:

gem sources -a http://gems.github.com
sudo gem install pilu-terror

Create a new project

terror new_aggregator_name
cd new_aggregator_name 

Start the server

thin start -C config/thin.yml

Run the feeds fetcher

rake feeds:fetch # run it as a cron job

You can browse the source and fork it on github.


Radiant Gallery on Dreamhost with Ruby 1.8.7

January 15th, 2009 by Andrea Franz

Some people in the past had problems using the Gallery extension on Dreamhost. I didn’t try Dreamhost but someone from the Radiant list solved that problem following these instructions. Check it out if you are on Dreamhost too.


Radiant iPhone extension 0.0.1

October 9th, 2008 by Andrea Franz

After some works for iPhone I decided to create an extension for Radiant that adds an iPhone tailored ui for the admin panel. It’s the first version and for now it just allows to edit existing pages and add new page parts.

You can find more info in the README file on github.

Radiant iPhone extension


Getting Exif data using ImageScience

May 2nd, 2008 by Andrea Franz

In my current rails project I need to upload photos and save some exif data taken from them. I use attachment_fu as uploading system that let me choose which image processor to use. Using rmagick and mini_magick I can extract exif data with the following code:

# rmagick
image = Magick::ImageList.new(filename).first
puts image['EXIF:Model'] # The camera model used to take the picture
 
# mini_magick
image = MiniMagick::Image.from_file(filename)
puts image["EXIF:Model"]

The problem is that I can’t do the same thing with image_science, because it has no methods that return exif data, so I want to add a method to the ImageScience class to do that.
Looking the FreeImage documentation I found some helpful functions, FreeImage_GetMetadata and FreeImage_TagToString. With these 2 functions I’m able to get an exif tag and convert it to a readable string. Each one of the available tags belongs to one of the following meta models:

FI_ENUM(FREE_IMAGE_MDMODEL) {
  FIMD_NODATA         = -1,
  FIMD_COMMENTS       = 0,	// single comment or keywords
  FIMD_EXIF_MAIN      = 1,	// Exif-TIFF metadata
  FIMD_EXIF_EXIF      = 2,	// Exif-specific metadata
  FIMD_EXIF_GPS       = 3,	// Exif GPS metadata
  FIMD_EXIF_MAKERNOTE = 4,	// Exif maker note metadata
  FIMD_EXIF_INTEROP   = 5,	// Exif interoperability metadata
  FIMD_IPTC           = 6,	// IPTC/NAA metadata
  FIMD_XMP            = 7,	// Abobe XMP metadata
  FIMD_GEOTIFF        = 8,	// GeoTIFF metadata
  FIMD_ANIMATION      = 9,	// Animation metadata
  FIMD_CUSTOM         = 10	// Used to attach other metadata types to a dib
};

Ok, now I can extract the model of the camera:

FreeImage_GetMetadata(FIMD_EXIF_MAIN, bitmap, "Model", &tag);
printf(FreeImage_TagToString(FIMD_EXIF_MAIN, tag, NULL));

As you can see, I need to pass the model of the “Model” tag. But if I don’t know which model to use, I can loop through all of them until the returned value of the FreeImage_GetMetadata function is not NULL:

for(model = 0; model < 11; model++) {
  if(FreeImage_GetMetadata(model, bitmap, tagName, &tag))
    return rb_str_new2(FreeImage_TagToString(model, tag, NULL));
}

Finally I can write a ruby module that extends ImageScience and adds the ability to get an exif tag:

module ImageScienceExifData
 
  def [](key)
    if key =~ /^EXIF:(\w+)?/    
      get_exif($1)
    end
  end
 
  inline do |builder|
    if test ?d, "/opt/local" then
      builder.add_compile_flags "-I/opt/local/include"
      builder.add_link_flags "-L/opt/local/lib"
    end
    builder.add_link_flags "-lfreeimage"
    builder.add_link_flags "-lstdc++" # only needed on PPC for some reason. lame
    builder.include '"FreeImage.h"'
 
    builder.prefix <<-"END"
      #define GET_BITMAP(name) FIBITMAP *(name); Data_Get_Struct(self, FIBITMAP, (name)); if (!(name)) rb_raise(rb_eTypeError, "Bitmap has already been freed")
    END
 
    builder.c <<-"END"
      VALUE get_exif(char *tagName) {
        GET_BITMAP(bitmap);
        FITAG *tag = NULL;
        const char *value;
        int model;
 
        for(model = 0; model < 11; model++) {
          if(FreeImage_GetMetadata(model, bitmap, tagName, &tag))
            return rb_str_new2(FreeImage_TagToString(model, tag, NULL));
        }
 
        return Qnil;
      }
    END
 
  end
end
ImageScience.send(:include, ImageScienceExifData)
 
ImageScience.with_image(filename) do |img|
  puts img["EXIF:Model"]
end

The output with the picture I used is the following :

NIKON
COOLPIX S3
2006:12:10 12:09:17

It doesn’t work with all the exif names but for now it’s ok for my needs. The next step is to add the code above in my rails application and use it with attachment_fu. I’ll write another post about that soon.