Archive for May, 2007

Odd ‘document’ behavior With Prototype.js 1.5 in Safari 2.0.4

Saturday, May 19th, 2007

I ran in to an annoying bit of behavior while working on a generic hovering element effect in Safari, using Prototype.js 1.5. Firstly, I’m not well-studied in the general quirks of the onload and unload events, how they work and should work etc, but this issue seems to stand outside that.
The code I’m working on uses the wonderful document.getElementsByClassName to locate the exact element to operate on. Everything was working smoothly, save for the usual and expected cross-browser kinks to be sorted out. Basically I have an element structure like this:

<div class='news-summary'>
    <div class='title'>Today's News</div>
    <div class='date'>5/18/2004</div>
    <div class='summary'>This is a great post...</div>
    <div class='admin-toolkit-canvas'>
	    <a>Edit</a>
    </div>
</div>

This represents a simple news preview or summary, possibly one in a list that you might find on a news post index or a side element or portlet. Now if you are logged in as an admin, hovering over the summary should cause a translucent canvas to appear over it, containing easy to access admin functions (like edit). The css class news-summary is a top-level container for summary content, and contained in this is an element of class admin-toolkit-canvas. This element is invisible, and is positioned absolutely within the parent news-summary element. When any child element of the summary element is hovered over, the canvas is rendered. I use document.getElementsByClassName to locate the actual canvas element in various contexts, mainly for showing/hiding it. I had no serious issues until navigating away from the page in the same window, and then using the ‘back’ button in Safari to return to it.
It seemed that the hover events over the summary containers were no longer being handled properly, or more likely that the code I had written to locate the child canvas was breaking.
After some precursory investigation I had assumed this was a side affect of Safari’s handling of the onload event, but further experimenting proved otherwise.
Prototype does some things that some call bad practice, like augmenting core objects and classes provided by the browser environment. One such victim is the global document object, which it equips with the getElementsByClassName method. It works fine… until you return to a page using this method via the back button. So what’s the problem? The augmentations to core objects (not classes), specifically on document made by prototype are apparently reverted. That’s right. No more getElementsByClassName. Why? I’m not sure. This seems to be how WebKit is designed - to blindly (re)initialize the core objects on any page visit.

Is this a bug or a feature? I’m not yet sure. I haven’t done any other tests outside this, nor have I tried the WebKit nightlies. IE and FF seem to work as expected. More to come on this, no doubt. Share some input if you have any!

CakePHP and Persistence, Part 1: Why not Objects?

Thursday, May 17th, 2007

Cake is a decent framework. In fact I have very little gripes about it all around - plently of little picky things, but only one that really bugs me: cake’s model implementation.

Cake’s finders inherited by all models (find, findAll, etc) return 3d hashes, keyed at the top by the model class name, the middle with field names (model properties), and the bottom with the field values. This is a nice simple way of handling things, and does indeed work well for smaller applications. I’ve worked on several that attest to its usefulness (http://rosaloves.com for one).

Now for the rant: This Does Not Scale. Because we must deal in arrays instead of objects, we lose two very important OOP abilities - encapsulation and polymorphism. Our result models are not objects, so they are incapable of such notions. We have no typing, no method signatures, and therefore no effective interface. All entities must then have intimate knowledge of how our model is composed. There’s no point in getting into why this is bad - it has been documented over and over since the inception of OOP.

Why arrays? I am not involved in Cake’s development (though I hope to be an accepted contributor soon), so I can’t speak for them. In comparison with Ruby on Rails, I will wager a guess. Firstly, Rails’ finders are basically static methods (static as in Java), called class methods in Ruby, if I’m not mistaken. These methods only exist once in memory, as opposed to instance methods, which exsist per object instance. Static/class methods cannot operate on instance data (at least in Java, where ‘this’ is invalid). I’d wager that Rails’ finders/savers, as well as all relational mapping metadata, are static class members. This way model instances don’t carry (duplicate) this data per instance.
Php 4 can’t do this, not cleanly or naturally anyway, so Cake uses model instances singularly, probably to emulate the feel of executing finds in Rails. If Cake returned model instances (which it should), each instance would carry copies of the relational mapping data. If Cake exploited php 5, this metadata could be static and therefore shared between all instances of the model class. This could be achieved in a few ways in php 4, but it would be messy to say the least.

I’m only guessing that this is one of the reasons Cake does what it does. I’ll continue with a later post going further on thsi topic, as well as get into a project I’ve started on CakeForge called Object Model (http://cakeforge.org/projects/object-model/).