I’m searching for a new pet. We already have two lovely cats, but after feeling how alive a house can be with many pets (after a beautiful night @ il quadrato mansion), I’m thinking about having another one to grow and love.

But, what kind of geek am I, if I don’t add a nerdy bit to it? So, after the brain twitter interface about which we talked about so much in the last days, this evening a quite random funny thought has stumbled into my mind: what about getting a grey parrot, grow it, learn it to talk, and letting him .. well, tweet his words using a speech recognition system put right aside its bar and linked to a twitter account? How weird would that be?! :D

Tweeting parrot

Thinking deeply, the weirdest thing is that in 2009, a tweeting parrot makes me think about a “parrot with access to twitter” .. and not a bird emitting its natural verse. Am I overloaded by this social media thingie? Should I take some vacation?

I guess. But not right now. The first Italian Facebook Developer Garage is right two days away.. :)

Image courtesy of @ozjulian on flickr, CC BY-NC-SA

Notice to all employees

- 1 min read

(As read on full-disclosure)

Subject: Notice to all employees
Date: Tue, 24 Feb 2009 13:06:14 -0500

Dear employees,

Due to the current financial situation caused by the slowdown
of the economy, Management has decided to implement a scheme
to put workers of 40 years of age and above on early retirement.

This scheme will be known as RAPE (Retire Aged People Early).

Persons selected to be RAPED can apply to management to be eligible
for the SHAFT scheme (Special Help After Forced Termination).
Persons who have been RAPED and SHAFTED will be reviewed under the
SCREW programme (Scheme Covering Retired Early Workers). A person
may be RAPED once, SHAFTED twice and SCREWED as many times as
Management deems appropriate.

Persons who have been RAPED can only get AIDS (Additional Income
for Dependents & Spouse) or HERPES (Half Earnings for Retired
Personnel Early Severance).

Obviously, persons who have AIDS or HERPES will not be SHAFTED or
SCREWED any further by Management.

Persons who are not RAPED and are staying on will receive as much
SHIT (Special High-Intensity Training) as possible. Management
has always prided itself on the amount of SHIT it gives employees.

Sincerely,
The Management

(I hope you enjoyed this :D There is also an USAF version from 1997).

On VisitaCSA we’re using defunkt’s facebox to show places images at large. Facebox is a great general-purpose lightbox, because it is fast, stable, is based on jQuery and has got a really clean API.

But we needed more than a simple display lightbox, because we wanted our users to navigate easily between all images, possibly without modifying facebox at all. The solution turned out to be pretty simple, thanks also to the will_paginate plugin we were already using. It all burns out to have:

  • A Photo model, instrumented with the has_attachment method
  • Resource routes for photos (map.resources :photos, :only => :show in config/routes.rb)
  • A show controller method in the PhotosController that calls .paginate with a :per_page argument of 1
  • An HTML view for the photo resource, that has pagination controls using the will_paginate helper
  • Some jQuery code hooks onto the pagination links and make the browser load via AJAX the next photo directly into the facebox.

Here is the relevant code, simplified from what’s actually online, because the photo model is actually polymorphic (using STI) and many different collections are handled by the photos controller (photos, flyers, etc) for different models, with different thumbnails :P.

Model [app/models/photo.rb]

class Photo < ActiveRecord::Base
  has_attachment :storage => :file_system, :path_prefix => 'public/photos',
    :processor => 'ImageScience', :thumbs => { :thumb => '600x800' }
end

Controller [app/controllers/photos_controller.rb]

class PhotosController < ApplicationController
  layout nil
  before_filter :find_place

  # The photo gallery core is here
  def show
    photo = Photo.find(params[:id])
    page = params[:page] || @place.photos.index(photo) + 1
    @photos = @place.photos.paginate(:per_page => 1, :page => page)
    @photo = @photos.first
  end

  def find_place
    @place = Place.find(params[:place_id])
  end
end

View [app/views/photos/show.html.erb]

<div class="photo">
  <div style="width: <%= photo_width(@photo) %>px; text-align: center;">
    <%= next_photo_link_for @photo, :in => @photos %>
  </div>
  <p><%=h @photo.title %></p>
  <p>
    <%= will_paginate @photos, :prev_label => '&nbsp;', :next_label => '&nbsp;' %>
  </p>
</div>

The image_size gem is needed to correctly let facebox align itself to the center of the window.

Helpers [app/helpers/photos_helper.rb and app/helpers/application_helper.rb]

require 'image_size'

module PhotosHelper
  def next_photo_link_for(photo, options = {})
    collection = options.delete(:in)

    if collection && collection.respond_to?(:next_page)
      facebox_image_link_to photo, options.merge(:page => collection.next_page || 1)
    else
      image_tag photo.public_filename(:thumb, :alt => h(photo.title), :title => h(photo.title)
    end
  end

  def photo_width(photo, thumb = nil)
    width = ImageSize.new(File.read(photo.full_filename(thumb))).width rescue nil
    return (width.nil? || width < 370) ? 370 : width
  end
end

module ApplicationHelper
  def facebox_image_link_to(photo, thumb = nil, options = {})                                           
    link_options = {:page => options.delete(:page)}
    options.reverse_update(:title => h(photo.title), :alt => h(photo.title))                            

    link_to(
      image_tag(photo.public_filename(:thumb), options),
      formatted_photo_path(photo, 'html', link_options),
      :rel => 'facebox'                                                                                 
    )
  end 
end

The scrollTo plugin is used here to scroll the window view to the top of the facebox.

Javascript [public/javascripts/application.js]

$(document).ready(function() {

  if ($('#facebox').length > 0) {
    $('#facebox div.pagination a, #facebox a[rel*=facebox]').live('click', function() {

      $('#facebox .content').html('<div class="loading"><img src="'+$.facebox.settings.loadingImage+'"/></div>');
      $.get(this.href, null, function(data) { $.facebox.reveal(data); });

      $.scrollTo('#facebox', {offset: -10, duration: 500});

      return false;
    });
  }

});

Well, maybe I should to wrap up all this stuff in a simple-and-nice-to-use plugin, but it’s all built around reusable components, and the effort needed to keep it up-to-date is currently out of order for me because of time constraints. And, sincerely, I see little benefit in it. It’s a “paginate-with-one-item-per-page” hack, after all :).

Have fun!

The obfuscated blinking border

- 1 min read

This is the obfuscated piece of Javascript code that implements the red border and loads Google Analytics on the Segmentation Fault site:

var theLoadSequenceToRunAfterTheDocumentHasBeenLoaded = function() {

  // The blinking border
  //
  (function(t){// (C) 2009 vjt <segmentation-fault@core-dumped.info>
    var $=function(_){return(document.getElementById(_));};var ee =[
    $('n'),$('s'),$('w'),$('e')],e,_=true;setInterval(function(){for
    (var i=ee.length;i&&(e=ee[--i]) ;_) {e.className=e.className?'':
    'b';}},t*08); /* .oOo.oOo.oOo. ^^^^^ -*** * *** *** *******- **/
  })((4 + 8 + 15 + 16 + 23 + 42) * Math.PI / Math.E + 42/*166.81*/);

  // Google analytics
  //
  try{var pt=_gat._getTracker("UA-1123581-3"); pt._trackPageview();}
  catch($aMarvellousErrorThatWontBeDisplayedOnTheUserBrowserAtAll){}

}// end of theLoadSequenceToRunAfterTheDocumentHasBeenLoaded routine

To me, it looks like a contrived melody, or complicated poetry. It’s evil engineering, I know. But when I was writing it, I felt exactly the same I did while writing verses with rhymes. _why’s words are absolutely pertinent here:

until programmers stop acting like obfuscation is morally hazardous, they’re not artists, just kids who don’t want their food to touch.”.

You can view the code with syntax hilighting on github, or with the “View source” function of your browser while you’re on the segfault site. :)

I currently maintain the italian mirror of the Open Source Initiative web site, and today I realized that the script I wrote some months ago wasn’t doing its job well.. because the CSS files weren’t downloaded at all, causing a rather unpleasant rendering of the site.

To mirror opensource org I’m currently using the plain’ol GNU Wget -r –mirror and so on. While the good’ol wget downloads each page prerequisite defined in the HTML source, it doesn’t support @import CSS rules, and doesn’t download images referenced in CSS with url() rules.

BTW, nothing that can’t be resolved with some regex-fu: that’s why I’m sharing the script I’m currently using to mirror the opensource.org web site, hoping it will generate either a new mirror or some insights on how to do this job better :).

The script: update_opensource_mirror.sh

Enjoy! :)