New Website: NHL Player Graphs

When I look at NHL player stats, I usually see season totals in the same sort of table format. There needs to be more variety. Alternate data representations can tell different stories so I gathered NHL player game stats from the last complete season and graphed them.

Look at Mason Raymond of the Vancouver Canucks. He transitioned from a power play regular in the first half of the season into short handed duty. Additionally, his +/- dipped in the second half of the season - corresponding with less shots and ice time. A definite role change for him. You could also look at Ovechkin whose graphs readily shows he shoots, scores and hits an incredible amount.

There are still lots of stats to add to the site but it is quite useful already. If there is interest, I'll cover more stats and monitor the 2009-2010 season.

Hockey. November 02, 2009 - 01:50AM. 0 Comments

New jQuery Plugin: Pliable Photo Gallery

I've created a jQuery plugin that would convert a list of images into a photo gallery. It'll automatically scale everything within to fit so it is easy to cram into any leftover space or to enlarge for full glory.

I've also experimented with applying a vignette effect to the preview images. Absolute positioning a partially transparent .png over content is a great way to create basic lighting effects.

One challenge was progressive enhancement. With javascript turned off, it should still display the images half decently. I choose to add some CSS rules so that the images don't bleed over the rest of the page content. Hey, you set the parent container to specific dimensions and it should respect that.

For download and installation instructions, please visit the Pliable Photo Gallery demo.

Javascript. September 29, 2009 - 10:32PM. 0 Comments

Custom Website Rolled Out

I've replaced the website from Typo to a custom solution. Typo is great but I plan to add more content than just blog entries and did not want to work around it. Going custom, I can keep it lean and experiment with it on the side. Also, the theme changed from dark and moody to light and minimalistic.

So, starting fresh with a renewed focus. So far, I've converted over the old blog posts over but expect to see more content soon.

Misc. September 27, 2009 - 09:46PM. 0 Comments

What if the graphic design hue was adjustable in production?

In my current project, I needed to come up with a way to visually differentiate subdomain accounts. Adding rich theming support didn't make sense since:

  • End users are not responsible for the site design and hiring a graphic designer is low priority
  • The web application is for automating a workflow as much as possible. Less options and configuration means less maintenance and manual intervention

In order to meet these guidelines, I wondered about the possibility of asking end users to choose just one site color. Could the web application do something meaningful and seamlessly with that single choice?

Game Plan

Every time one of the stylesheets is linked to in the view:

  • open up the stylesheet
  • find all RGB color values and convert to match the requested color
  • save stylesheet to a cache directory

We'll be using the HSL color model. It breaks down a color into three components: hue, saturation, and lightness. Hue is what we're interested in. By shifting only a color's hue, we can, for instance, turn a red color to yellow without breaking the design legibility or contrast.

Conveniently, CSS3 allows us to adjust the hue by specifying an angle in degrees on a color wheel where red is both 0 and 360. Using this method, we only need to do basic substitution without any math conversions.

The bad news is HSL color values are not supported by older browsers or Internet Explorer 8. It is reassuring that modern versions of the other major web browsers (Safari, Firefox, Opera, and Chrome) do support the HSL model but we'll have to play the waiting game for legacy browsers to go out of use. To be safe, our color values will start off and end up as RGB values.

Finally, once we convert the stylesheets, we'll need to cache them somewhere. I'm storing them in #{Rails.root}/public/stylesheets/hue#{hue_value} because:

  • reuse: it is possible for several subdomain accounts to share the same hue value
  • it'll be served as a static file by Apache
  • free cache sweeping: upon deployment via Capistrano, old cached files are not carried over

Implementation Limitations

The colors in my stylesheets are RGB hex strings such as #1234AA and #123. There is no support for color names like 'red' in my implementation since I don't use them.

Another consideration are the graphic design constraints. Since only a dominate hue is allowed, image usage should be minimized or you'll have to worry about image conversions (not covered in this tutorial). Shoot for a minimalist design with blocks of solid color.

Implementation

install the Color gem. It is used to handle our color model and hue conversions.

# config/environment.rb config.gem 'color', :version => '1.4.0' rake gems:install

We're going to add several methods into ActionView::Helpers::AssetTagHelper. First, use alias_method_chain() to append our manipulation logic to run just before the original stylesheet_link_tag().

def stylesheet_link_tag_with_hue(*sources) options = sources.extract_options! sources.map! do |stylesheet_path| if stylesheet_path.starts_with?('/') || stylesheet_path.starts_with?('http') stylesheet_path else stylesheet_path = stylesheet_path + '.css' if File.extname(stylesheet_path) == '' ensure_stylesheet_for_hue(HUE, stylesheet_path) "hue/#{HUE}/" + stylesheet_path end end sources << options stylesheet_link_tag_without_hue *sources end alias_method_chain :stylesheet_link_tag, :hue

It'll run through the list of stylesheet sources. If any source is a candidate for hue conversion, ensure_stylesheet_for_hue() is called and the source is prepended with the hue directory path.

Here is where the file operations and hue conversions take place:

def ensure_stylesheet_for_hue(hue, path_suffix) source_path = Rails.root.join('public', 'stylesheets', path_suffix) destination_path = Rails.root.join('public', 'stylesheets', 'hue', hue.to_s, path_suffix) return nil unless File.exist?(source_path) return nil if File.exist?(destination_path) && Rails.env != 'development' File.open(source_path) do |file| output = file.read.gsub(/#([0-9a-f]{6}|[0-9a-f]{3})/i) do color = hsl_color_from_rgb_hex_string($1) color.hue = hue color.html end FileUtils.mkdir_p(File.dirname(destination_path)) File.open(destination_path, 'w') {|output_file| output_file.write(output)} end end

The color library doesn't have a constructor for our RGB color hex strings so we'll add one here.

def hsl_color_from_rgb_hex_string(hex) args = case hex.length when 3: [hex[0,1]*2, hex[1,1]*2, hex[2,1]*2] when 6: [hex[0,2], hex[2,2], hex[4,2]] end args.map! {|arg| arg.to_i(16)} Color::RGB.new(*args).to_hsl end

Results

Overall, I'm satisfied with the functionality. The biggest issue is the connotations we give to various colors and their shadings. For my site, it is hard to select an orange hue since dark orange doesn't look like orange. Also, it's not pink, it's lightish red. Some minor tweaking of saturation and lightness helps to make it work well with all hues though.

Design Ruby on Rails. June 01, 2009 - 10:10AM. 0 Comments

Exception Notifier Plugin Fix for Rails 2.2.2+

For those of us who are still using the Exception Notifier Plugin, be careful when upgrading to a recent version of Rails. Doing so with Rails 2.2.2+ and the configuration is in an environment file (#{RAILS_ROOT}/config/environments/production.rb for instance) will not send notification emails. Instead, it'll fail with:

Net::SMTPSyntaxError (501 5.1.3 Bad recipient address syntax ): /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/1.8/net/smtp.rb:679:in `check_response' /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/1.8/net/smtp.rb:652:in `getok' /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/1.8/net/smtp.rb:634:in `rcptto' /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/1.8/net/smtp.rb:545:in `send0' /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/1.8/net/smtp.rb:544:in `each' /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/1.8/net/smtp.rb:544:in `send0' /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/1.8/net/smtp.rb:471:in `sendmail' /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/1.8/net/smtp.rb:378:in `start'

Several ways to work around this problem. You could wrap the configuration inside an after_initialize block:

config.after_initialize do ExceptionNotifier.exception_recipients = %w(joe@schmoe.com bill@schmoe.com) ExceptionNotifier.sender_address = %("App Error" ) ExceptionNotifier.email_prefix = "[APP] " end

The other solution is to put the configuration in an initializer file.

Of course, there is the option to instead use Hoptoad or Exceptional.

There is a lighthouse ticket if you want to follow the discussion.

Ruby on Rails. March 23, 2009 - 07:45PM. 0 Comments