Pragmatic CSS and Javascript in Seaside
By Ramon Leon - 23 October 2006 under Programming, Seaside, Smalltalk
I see a lot of confusion about how to use CSS and Javascript with Seaside, so here's quick rundown of how things work, and what you should do.
There are several ways to include CSS and Javascript for use with a Seaside component. Unfortunately, the most pragmatic method, isn't the first one you run into when you play with the tutorials.
Method One: On Component Accessors
Seaside allows one to edit both a components Smalltalk code, and its CSS code, via the web browser. Every component includes an accessor for #style and #script that you can override to return CSS and Javascript respectively. This is what the built in web browser CSS editor edits. This is very misleading, because it makes you think you "should" do this, but you shouldn't. It's one of those fancy things that looks cool in a demo, but isn't very practical in the real world. I think this editor was meant to show off the power of Seaside and Smalltalk, and even to hide Squeak a little for newbies, but this isn't how real world code is written. This is a method to avoid.
- Don't edit CSS or Smalltalk in the web browser!
Method Two: File Libraries
A slightly more advanced version of the previous method, one can create subclasses of WAFileLibrary for Javascript and CSS, and create as many accessors as one wants, breaking up CSS and Javascript libraries into more manageable chunks. You provide a #selectorsToInclude method that returns a list of the selectors to include and the framework uses reflection to find them within these classes and includes them in your document. You can install the libraries via the application's libraries drop down in the configuration editor.
Both of the previous methods create an include in the HTML document head, pointing to a dynamically generated cachable URL like so...
<link rel="stylesheet" type="text/css" href="http://yourServer/?_s=oOrPOVQrSYfGdvMT"> <script type="text/javascript" src="http://yourServer/?_s=aIoExcjtxfXNLNHA"></script>
This method is satisfactory for Javascript libraries, since once developed, they usually require little if any editing. This also works well for wrapping existing Javascript frameworks so all necessary code is included in the Smalltalk package. But this method is also not practical for CSS development, because it puts CSS into accessors as hard coded strings in Smalltalk classes, the last place your CSS designer wants to look. CSS editors don't work on Smalltalk classes.
- Don't use libraries for CSS, I know it'll work, just don't do it, unless of course the developer is the designer and you don't mind keeping your CSS in Smalltalk.
Method Three: File Includes
This is the only practical method of mixing CSS, Javascript, and Seaside, traditional manual link and script statements in the head tag, pointing to static CSS and Javascript files served up by the web server, directly off the hard drive.
CSS belongs in *.css files on the disk, where a designer can easily use his existing tool set, whatever that may be, to edit the files directly. This keeps the programmer and the designer squarely in their respective comfort zones, using tools of "their choosing", to edit "their" code. Even if you don't have a designer, and you edit the CSS yourself, it's a much easier task to do with a real editor on a real file.
This method is simple to use, just override #updateRoot: on your component and link to the files like so...
updateRoot: aRoot super updateRoot: aRoot. aRoot javascript url: '/yourServer/someJsLibrary.js'. aRoot stylesheet url: '/yourServer/someCSSLibrary.css'
This will generate...
<link rel="stylesheet" type="text/css" href="/yourServer/someCSSLibrary.css"> <script type="text/javascript" src="/yourServer/someJsLibrary.js"></script>
in your head tag, just as you'd normally have done in any other web framework.
Just because everything "can" be put into Smalltalk classes, doesn't mean it should be. Sometimes Seaside features and flexibility lead one down the wrong path and make you think you "have" to do everything differently than you used to. But Seaside is fully capable of doing most things several ways, including the old fashioned way, when it's the pragmatic alternative.
There are times when it's convenient to use method one, prototyping for example, when you're in a hurry and just want it to work fast. Maybe you need to generate some dynamic Javascript for a Google map from a collection of points, in which case the #script accessor comes in very handy. However, for static CSS and static Javascript, I would choose the third method in almost every case.
As with most things in programming, context means everything, and which method you choose depends on the circumstances at hand, so choose wisely.
Comments (automatically disabled after 1 year)
Yes, you're correct, but this is an add on, it's not part of the core Seaside package.
Not any more ;)
[...] Seaside lets you code your CSS in a number of different ways but I concur with Ramon Leon’s conclusions that externalising CSS to a file is best. So here’s our CSS… body { background-color: #fff; font-family: “Trebuchet MS”} div{ padding: 2px; } .row1 { background-color: #99d ; color: #fff; } .row0 { background-color: #67d ; color: #fff; } .row { background-color: #67d ; color: #fff; } a{ color: #ccf; font-weight: bold; text-decoration: none; } h1{ color: orange; } .field{ margin-left:30px } [...]
Totally agree. Files are cheaper to manage traditionally.
Just slowly reading your way through all the old posts eh?
Hi Ramon, It looks like some of the details in this post are now quite out-dated. You've listed the changes needed for recent releases of Seaside at another post, but it's worth clarifying the specific changes needed here.
At method Two, WAScriptLibrary is now deprecated (not even included in latest releases) - WAFileLibrary is now the preferred approach.
In method Three, the updateRoot: approach, 'linkToScript:' should now be replaced with 'javascript url:' and 'linkToStyle:' should be 'stylesheet url:'.
Cheers, Michael
Updated, thanks for pointing this out.
Well there is a fourth: FileLibrary. It tries to combine the advantages of two (distributable with the code) and three (style sheets or scripts can reference images).