Tag Archive for 'HTML'

Ozone Templating

There have been recurring requests about an in-depth explanation of how Ozone — our in-house OCaml web framework — handles HTML templates. So, here it is.

A template is usually understood by everyone to be « HTML with holes » that is filled using values from the application itself. It is, in a sense, a DSL that is restricted to describing how HTML should be built.

Here is an example of template Ozone could use, stored in file users.htm :

<h1>{t:users.title}</h1>
<ul class="userlist">
  {{list:
    <li id="{v:id}">
      <img src="{v:img}"/>
      <a href="{v:url}">{v:name}</a>
    </li>
  }}
</ul>

<script type="text/coffeescript" params="save_url">
list = @$.find 'ul'

save = =>
  ids = [];
  list.children('li').each ->
    ids.push $(@).attr 'id'
  @ajax save_url, ids

list.children('li').sortable
  change: save
</script>

<style type="less">
.userlist {
  list-style-type: none;
  li img {
    float: left;
    margin-right: 5px;
    width: 50px;
    height: 50px;
  }
}
</style>  

The template for a sortable list of users contains three things:

  • A piece of HTML, which is the actual « HTML with holes » to be filled later. The holes are marked in orange.
  • A piece of CoffeeScript, which will be extracted from the template file, compiled to javascript and appended to a site-wide javascript file. It will be replaced, in the template, by a hole that will call the extracted javascript with additional parameters provided by the application (in orange).
  • A piece of LESS CSS, which is compiled to CSS and appended to a site-wide CSS file.

These are not sections — they can appear in any order as long as the elements and attributes are respected so the pre-build tool can identify and extract the CoffeeScript and CSS bits.

Let’s examine each of them in order.

The HTML Template

This is the meat of the template. In order to improve application performance, loading the templates is a multi-step operation that involves intermediary storage formats.

The first step consists in reading in all the necessary templates, parsing them to determine that no variables are undefined, and storing them as a JSON blog in the underlying CouchDB database. This is a manually triggered operation that happens whenever we modify the templates (it’s part of our deployment procedure). This step may also involve a bit of cleanup, such as removing semantically irrelevant spaces from the HTML (this cannot be done earlier, because some templates are plaintext instead of HTML, and only the application knows which is which).

The second step happens whenever a new instance of our application begins — maybe it died and needed to restart, maybe Apache decided it needed another worker process to handle a surplus of request, or maybe we added a new server to our web farm. The startup process of our application server does not read anything from the disk — instead, it will read in all the template data from the database, along with all the other bits of configuration: internationalization strings, third party API keys, feature branch triggers, and so on. Then, it will compile every template down to optimized closure-based opcodes for a hole-filling virtual machine.

The third step happens whenever a bit of HTML needs to be rendered. The application provides the hole-filling virtual machine with a data object and a « writing stream » which is either the HTTP request stream or a JSON serializer stream, depending on whether the request is normal HTTP or AJAX. This is an extremely fast operation where no parsing or checks are performed.

On the application side, loading a template involves three things:

  • Declaring the type of the data object expected by the template.
  • Declaring the source file from the template (as a function of the language).
  • Declaring the hole-to-value mapping  to be used.

Here’s that loading code for the above template file:

module User = Loader.Html(struct
  type t = <
    id   : Id.t ;
    url  : string ;
    img  : string option ;
    name : string
  > ;;
  let source  _ = "users/list"
  let mapping _ = [
    "id",   Mk.esc (fun x -> Id.to_string (x # id)) ;
    "url",  Mk.esc (fun x -> x # url) ;
    "img",  Mk.esc (fun x -> BatOption.default img404 (x # img)) ;
    "name", Mk.esc (fun x -> x # name)
  ]
end)

module UserList = Loader.Html(struct
  type t = <
    users : User.t list
  > ;;
  let source  _ = "users"
  let mapping lang = [
    "list", Mk.list (fun x -> x # users) (User.template lang)
  ]
end)

One view is defined and loaded for every independent piece of HTML in the template. Here, there is an User view which represents the list item for a single user, repeated zero, one or more times ; and there is the UserList view representing the wrapper in which those list items will be placed.

The {v:foobar} syntax defines a variable hole. The corresponding view MUST define a mapping for that variable, or an error will occur at deployment time.

The {{foobar: }} syntax is a variant: in addition to declaring a variable hole, it also defines such a sub-view, which can be loaded using template/foobar as the path.

The {t:foobar} syntax defines a translation hole. The template engine will automatically load the corresponding term from the internationalization dictionary used to render the template.

The Mk.esc and Mk.list are binding instructions which are used to compile the template to a virtual machine. The common binding instructions are:

  • Mk.esc f applies f to the data object, which returns a string. That string is then HTML-escaped and output.
  • Mk.str f is the same as above, but the string is not HTML-escaped.
  • Mk.i18n f is the same as above, but the string is translated as an internationalization term.
  • Mk.list f t applies f to the data object, which returns a list of data objects compatible with template t. That template is then used to render those data objects in order.
  • Mk.list_or f t e is the same as above, but if the returned list is empty, it instead uses template e to draw a « list is empty » message.
  • Mk.sub f t applies f to the data object, which returns a single object compatible with template t. That template is then used to render the object.
  • Mk.sub_or f t e is the same as above, but f returns an optional type. If it is missing, then template e is used to render an « object is missing » message.
  • Mk.text f provides f with the current writing stream and internationalization object, so that it may directly write HTML to the output. This is how most rendering helpers such as « render a currency amount » are used.
  • Mk.box f is the same as above, but the writing stream supports the addition of arbitrary javascript code to be executed by the client as part of rendering the template. This is how javascript-dependent rendering helpers such as « render a datepicker » are used.

The data type is defined in the view itself, either explicitly (as I did above for the sake of clarity) or by using an existing type from your application — if the application already had an user module with the appropriate data type, I could have used that type instead.

By specifying views in this way, the data required to render a template is made available to the compiler for type-checking, and missing bindings are detected during deployment (usually to a local test server). This has made template-related errors exceedingly rare — once the HTML is done, it becomes extremely hard to use it wrong.

Although this feature is not currently in use, the virtual machine semantics also allow compiling it down to JavaScript. This would allow us to send the rendering code to the client as a one-time cost, and send a much smaller data package through AJAX whenever something new needs to be rendered.

The CoffeeScript Layer

We use CoffeeScript because it’s more elegant, shorter, and includes a compiling-to-javascript step that lets us detect syntax errors at deployment time. Yes, compile- and deployment-time are my favorite buzzwords, because I enjoy the feeling of safety that they bring.

As mentioned above, the actual CoffeeScript is removed from the template in a pre-processing step, and replaced with a hole that says « call JavaScript function #33 now » that happens to define a list of parameters matching the params attribute of the original script element.

So, starting with the script element from the example above:

<script type="text/coffeescript" params="save_url">
list = @$.find 'ul'

save = =>
  ids = [];
  list.children('li').each ->
    ids.push $(@).attr 'id'
  @ajax save_url, ids

list.children('li').sortable
  change: save
</script>

If this is the 33rd script tag encountered by the preprocessor, then it would append the following to the complete CoffeeScript file:

@j33 = (save_url) ->
  list = @$.find 'ul'

  save = =>
    ids = [];
    list.children('li').each ->
      ids.push $(@).attr 'id'
    @ajax save_url, ids

  list.children('li').sortable
    change: save

And it would be replaced in the template file with this:

{j:j33:save_url}

This syntax (which can be used manually, although it should be avoided) is a javascript hole, it runs the specified function and provides by-name values for the arguments. The parser would notice that we are declaring an HTML view instead of a JS/HTML view and complain about it, so we would have to go back and re-define it:

module UserList = Loader.JsHtml(struct
  type t = <
    users : User.t list ;
    save_url : string
  > ;;
  let source  _ = "users"
  let mapping lang = [
    "list", Mk.list (fun x -> x # users) (User.template lang)
  ]
  let script  _ = [
    "save_url", (fun x -> Json_type.String (x # save_url))
  ]
end)

I have used Loader.JsHtml instead of Loader.Html, and defined a secondary mapping that is specific to JavaScript parameters, and which uses the data object to return JSON values.

How is the JavaScript called? Well, it really depends on how your JavaScript library handles it. On non-AJAX HTTP, Ozone will try to inject all JavaScript calls in a script element at the end of the HTML body. In AJAX mode, Ozone allows you render a template to a JSON object representing both the HTML and the JavaScript together, and it is the responsibility of the code that made the AJAX request to receive that object, place the HTML wherever applicable, and then “run the JavaScript”.

By convention, the JavaScript is called using a client context as itsthis value. The client context is an object which may contain whatever the caller finds interesting to place there, along with a variable named $ which should be a jQuery selection containing the root element of the previously rendered HTML. Hence, @$.find 'ul' would select the list in the rendered HTML, instead of all the lists on the page.

The LESS CSS Layer

This is the least interesting of all three layers. The LESS CSS code is extracted, appended to a single file, and compiled to CSS (which, again, is an useful deployment-time syntax check). The point of this feature is simply to let the designer place element-specific CSS next to the element, instead of having it exist in an external file and cause trouble with asset garbage collection (can I remove this rule or is it still used anywhere?) External files still exist, though, for CSS rules that are not limited to a single template.

Bonus : the triple hash

How do I define some code that should be called when a button is clicked? Defining it directly in the onclick method is ugly, hard to read and does not let the application provide parameters, so what else can I do?

The solution is to use an intermediary global object that happens to be the same for the entire file — a pattern that stores any template-related JS in a global variable named after __FILE__ !

Yes, it is a hack, but it’s a simple and useful one.

The only difference is that __FILE__ is spelled ###.

<button type="button" onclick="###.frobnicate()">{t:frobnicate}</button>

<script type="text/coffeescript" params="message">
###.frobnicate = ->
  alert message
</script

Article Image © gdbg12 — Flickr

On Escaping HTML

A common issue with web software is cross-site scripting attacks — the ability for a third party to inject HTML elements into pages displayed to other users, using scripts contained in those elements to capture user cookies or perform operations on their behalf.

The technical challenge in solving this is that whenever data is being output through a HTML page, it should be escaped — any special HTML characters should be turned into their non-special versions in order to be displayed verbatim. This is an ongoing effort: each new page and each new variable on a page involve the same amount of effort to be done.

Of course, the solution would be to decide that escaping string output should be a default behavior that must be explicitly overriden. This does create issues where HTML is escaped when it should not have been, but:

  • These issues cannot be used to perform attacks.
  • They are usually easier to reproduce and consequently to solve.
  • HTML usually comes from template files, which can be handled with a different default.

Indeed, I can guarantee that my software has zero vulnerabilities related to escaped HTML, because I have built into the type system the fact that HTML always comes from templates, and the method that injects variables into templates escapes them. If I try to use a string as if it were HTML, I get a compiler error.

Even without a type system, one can guarantee that the system would rather break at runtime than allow an injection, using the exact same design, with incompatible data structures for templates and strings that blow up when a string is used as a template:

class FilledTemplate {
  function __construct($html) {
    $this->_html = $html;
  }
  function html() {
    return $this->_html;
  }
}

class Template {
  function __construct($file) {
    $this->_template = file_get_contents($file);
  }
  function fill($values) {
    $replace = array();
    $with    = array();
    foreach ($values as $key => $value) {
      $replace[] = '{'.$key.'}';
      if ($value instanceof FilledTemplate) 
        $with[] = $value->html();
      else 
        $with[] = htmlspecialchars($value);
    }
    return new FilledTemplate(
      str_replace($replace,$with,$this->_template)
    );
  } 
}

Obviously, many languages and frameworks use non-escaped string output as the default behavior. This, in my opinion, is pure, broken insanity — I can certainly see that designing a safe way of constructing HTML is harder than just following the «HTML is strings, just use string functions» approach and telling the programmer to «always escape your variables, kid» but I still find it quite irresponsible for self-proclaimed Web Languages to rely on such a primitive and dangerous paradigm. The stupid kind of irresponsible. Yes, PHP, I’m looking at you.

Article Image © Freedom II Andres — Flickr

Does this repository make me look fat?

The main RunOrg SVN repository contains:

  • 38490 lines of OCaml implementation code spread over 273 *.ml files.
  • 5134 lines of OCaml signature code spread over 156*.mli files.
  • 4776 lines of HTML template code spread over 271 *.htm files.
  • 1971 lines of CSS in 6 files.
  • 1898 lines of JSON configuration in 26 files.
  • 1172 lines of JavaScript in 5 files.

That’s a total 53441 lines in 837 files.

Here’s a plot of how the 38490 lines of OCaml code came into being over the last eight months.

That is all.

PHP 5.3 Closures as Block Literals?

I explained earlier a few things about writing reusable CSS code, and how it interacted with PHP. Let’s start with this basic HTML for generating two columns, with the right one being flexible and resizing to fill all available space:

<div class="col2">
  <div class="col2-l">
    [Content of left column]
  </div>
  <div class="col2-r">
    <div class="col2-ri">
      [Content of right column]
    </div>
  </div>
  <div class="clearer"></div>
</div>

.col2    { }
.col2-l  { float: left ; padding: 0 ; margin: 0 ; width: 120px }
.col2-r  { padding: 0 0 0 120px ; margin: 0 ; width:auto }
.col2-ri { float: left ; width : 100% }
.clearer { clear: both }

Elementary PHP

How does this translate to PHP? Basically as a series of constants (plus documentation detailing what the column HTML should look like):

class CSS_Col2
{
  const ROOT = "col2";
  const LEFT = "col2-l";
  const RIGHT = "col2-r";
  const RIGHT_INNER = "col2-ri";
}

This serves both as documentation for the existence of this component, and as an entry in the auto-completion tool to avoid typing incorrect classes by mistake. However, you still have to get the actual code right:

<div class="<?=CSS_Col2::ROOT?>">
  <div class="<?=CSS_Col2::LEFT?>">
    [20 lines of left column here]
  </div>
  <div class="<?=CSS_Col2::RIGHT?>">
    <div class="<?=CSS_Col2::RIGHT_INNER?>">
      [40 lines of right column here]
    </div>
  </div>
  <?CSS::CLEARER?>
</div>

Did I write everything correctly? Did I forget or misplace a clearer? Forgetting about the inner container in the right column is an easy mistake, and you won’t notice it until you put a clearing element in that column. And if your script is long enough, you won’t be able to see which opening tag matches which closing tag. Surely there must be a way to improve this.

Using HTML constants

A possibility is using constants to contain the relevant HTML:

class CSS_Col2
{
  // as above ...
  const _BEGIN_LEFT = '<div class="col2"><div class="col2-l">';
  const _BEGIN_RIGHT = '</div><div class="col2-r"><div class="col2-ri">';
  const _END = '</div></div><div class="clearer"></div>';
}

This makes code shorter, and you can’t mismatch or misplace tags as easily:

<?=CSS_Col2::_BEGIN_LEFT?>
  [20 lines of left column here]
<?=CSS_Col2::_BEGIN_RIGHT?>
  [40 lines of right column here]
<?=CSS_Col2::_END?>

However, all benefits of a nice and clean HTML editor are lost, because HTML constants don’t react as code, and there is therefore no validation performed. At least Eclipse could detect mismatching open/closing tags on raw HTML. Now, if you forget to “_END” your columns, your life is pain.

Using helpers

A common technique is to use a helper function for such rendering tasks. The function accepts some arguments that let it configure what ought to be displayed, then renders the wrapper HTML and inserts the data. Staying within the previous code:

class View_Helper_Col2
{
  static function Render($left, $right)
  {
    ?>
<div class="<?=CSS_Col2::ROOT?>">
  <div class="<?=CSS_Col2::LEFT?>">
    <?php call_user_func($left); ?>
  </div>
  <div class="<?=CSS_Col2::RIGHT?>">
    <div class="<?=CSS_Col2::RIGHT_INNER?>">
      <?php call_user_func($right); ?>
    </div>
  </div>
  <?CSS::CLEARER?>
</div><?
  }
}

I used callbacks here to do the rendering, because they are the most versatile (it sure beats having to instantiate a “renderable” class for each column). This approach provides the obvious benefit that now the entire rendering is taken care of by a single function, so there is no risk of forgetting or misplacing a tag, and the auto-completion tool can now help check which arguments are provided and in what order.

Still, this means that one should create two functions to render the two columns, and that any necessary data should be made available to them (due to the absence of closures in PHP < 5.3, this often means calling a member function of a view object containing the appropriate data). In the Zend Framework, for instance, one would just write two helpers, and provide them as callbacks knowing that they will have access to the data of the current view:

<?php
  $this->render2col(
    array($this,'myLeftCol'),
    array($this,'myRightCol')
  );
?>

Of course, it’s questionable whether moving a three-line for-each loop to a helper of its own actually increases the readability of the code. If defining a new class for every view, there’s the possibility of defining the columns as member functions within that same class, but it’s still somewhat awkward.

Helpers and Closures

PHP 5.3 introduces closures and optional arguments. This means that one can now write the behavior inline:

<?php
 $self = &$this;
 $this->render2col(
   function() use($self)
   {
     ?><h1><?=esc($self->user->name)?></h1><?php
   },
   function() use($self)
   {
     ?><ul><?php foreach ($self->items as $item): ?>
       <li><?php $self->render($item); ?></li>
     <?php endforeach; ?></ul><?php
   }
 );

However, making those functions inline creates a new issue: its not so obvious anymore what exactly a function is doing (because it’s too far away from the original call to the helper function). This can be solved by using a command pattern (while simultaneously noticing that one can get rid of the use keyword by providing $self as an argument (the helper does that):

<?php
 View_Col2::start($this)

 ->left(function($view){
   ?><h1><?=esc($view->user->name)?></h1><?php
 })

 ->right(function($view){
   ?><ul><?php foreach ($view->items as $item): ?>
     <li><?php $view->render($item); ?></li>
   <?php endforeach; ?></ul><?php
 })

 ->render();

Labels are now clearly mentioned, allowing empty lines to be inserted to separate the columns without forgetting what they are, so that the code looks cleaner overall.

Reusable CSS

Woe unto CSS, for it provides no refactoring-friendly tools! The CSS beast has neither functions nor variables, and its definition of inheritance is perverted beyond words. Pain and suffering await those who hope to keep their CSS from one project to the next, or even share the CSS between pages on a single website!

Consider two simple pages: the home page has a small navigation bar (selected by #navig) at the top of the screen, while the catalog page as a larger navigation (still selected by #navig). Each page includes a different layout.css stylesheet, so everything’s fine. Except that now, anything defined in a layout has to be copied over by hand to the other layouts if you want to reuse them. Ouch.

Does that example sound extreme? It certainly is! But the danger of page-specific stylesheets remains: if you won’t be stepping on your own toes with something as trivial as #navig, perhaps .book will mean two different things on two different pages?

Rule Zero : Keep all your CSS Together

This might seem a bit harsh, especially if you have truckloads of CSS floating around and don’t want to slow down the initial loading time of your page, or the time spent resolving collisions. However,

  • This rule will make it easier to factor out common bits of CSS, leading to an overall smaller set of stylesheets.
  • The number of HTTP requests matters as much as the bandwidth, so delivering all your CSS as a single, minified, gzipped blob is often a good performance idea.
  • The entire point is to make it harder to create page-specific rules, so that you don’t make a rule page-specific by mistake, and strive to make most of your rules page-independent.

I usually place all of my CSS in correctly named files in a directory on my server, then have the server generate a single, all.css master file that @imports the other stylesheets by path. This means Firebug’s CSS browser will correctly identify the source file for any given rule. When the code moves to a production server, the auto-generated master file becomes a pre-generated/minified/gzipped resource, and can even be moved to a CDN for improved performance.

On the other hand, keeping all your code in one place will only help you see collisions, it will not actually help you solve them.

Fortunately, we can look to other languages for tips and trick on how to make code easier to reuse. The fundamental observation is that you cannot use something if you don’t give it a name. One would expect CSS identifiers and classes to serve the same function, and indeed it does work in simple cases:

a.important { font-weight: bold }

Now, you have the important «function», that you «call» on an anchor element to make it appear important. Bam! Instant reusability. Using an identifier instead of a class still allows reuse on distinct pages, but restricts reuse within a single page.

Rule One : Document your «Functions»

You cannot reuse code if you cannot find it, and even if you don’t forget about it someone else on the team might be completely unaware that it even exists. So you should somehow document that the important class exists. My personal, PHP-friendly preference, is to have a “Css” class with all those nice classes available:

class Css
{
  /* a.important : make a link important */
  const IMPORTANT = "important";
}

Then, you can reuse them when you see fit to do so:

Click <a href="<?=$url?>" class="<?=Css::IMPORTANT?>">here</a>

That’s just personal preference—any way of documenting your CSS classes is fine as long as it’s somewhere everyone can see it. In fact, I have a nice set of PHP helpers lying around to bind jQuery UI CSS effects to my code, thereby documenting what jQuery UI can do without having to dive into the stylesheets every single time.

The real problem appears when you have more than one «argument». A typical example is the list of links with a “selected” link: the graphical effect applies to the list, to the elements of that list, and to the content of those elements, which leads to several rules selecting different elements.

ul#navig { margin: 0 ; padding: 0}
ul#navig li { list-style-type: none }
ul#navig li.selected a { font-weight: bold ; color: black }

This kind of structure cannot be documented simply by stating that the ul#navig element is going to become a pretty list, because without the li.selected in there there will be no «pretty» worth mentioning.

I document this as follows:

/*
  <ul id="navig">
    <li><a>Item</a><li>
    <li class="selected"><a>Item</a><li>
    <li><a>Item</a><li>
  </ul>
*/
ul#navig { margin: 0 ; padding: 0}
ul#navig li { list-style-type: none }
ul#navig li.selected a { font-weight: bold ; color: black }

Why not document it in the PHP code, then? IMO, a CSS designer to write a quick const FOO = "bar"; line in PHP, but not an HTML helper that turns an array of links into pretty list HTML. CSS designers write the CSS (with documented HTML) and PHP developers turn that into HTML helpers.

</acronym soup>

Another important element of code reuse is the notion of encapsulation, and in particular the existence of “private data” that is part of the program, but can only be accessed by some parts.

There is no such thing with CSS. There are two reasons for this. The main reason is that being sloppy with selectors is commonplace:

/*
  <div id="userList">
    <ul class="users">
      ...
    </ul>
    <a>New</a> |
    <a>Edit</a> |
    <a>Delete</a>
  </div>
*/
#userList a { color: #FF9900 ; text-decoration: none }
#userList a:hover { text-decoration: underline }

The three links in the user list component («new», «edit» and «delete») will appear in orange without underlining, as expected and documented. The unexpected and non-documented consequence of this code is that all links within the list of users will be orange without underlining as well.

Rule Two : Only Select what you Need to Select

The typical consequence of sloppy selectors is that «insert component A into component B» operations utterly destroy the formatting of component A. The typical designer reaction to such graphicalypse is «Darn, component B destroyed some property of component A, so let’s add some rules to component A to reverse the damage!»

Bad idea. It makes the code longer, and only hides the actual problem (along with any symptoms that only appear in specific cases). The real solution is to make sure selectors only select what they need to select.

One way of doing so is to use the «>» selector, as it restricts the selection to only children of the initially selected element. This would work:

#userList > a { color: #FF9900 ; text-decoration: none }
#userList > a:hover { text-decoration: underline }

Of course, it wouldn’t work in IE6, but who cares about IE6 anymore?

The general approach is to use specific classes for those elements that must be affected:

/*
  <div id="userList">
    <ul>
      ...
    </ul>
    <a class="userList-link">New</a> |
    <a class="userList-link">Edit</a> |
    <a class="userList-link>Delete</a>
  </div>
*/
a.userList-link { color: #FF9900 ; text-decoration: none }
a.userList-link:hover { text-decoration: underline }

If anyone uses that userList-link class in their code (and your naming conventions were clean enough), they had it coming.

Rule Three : Choose Proper Naming Conventions

It is quite important to remain consistent in your naming practices, especially since you now need to identify, for any given identifier and/or class:

  • If it represents a «function» (#userList), or if it helps select a specific «argument» (.userList-link).
  • In the latter situation, what function the argument corresponds to (so that you can look for its definition).

My preference is to use camelCase names (classes or identifiers) for functions, and camelCase-camelCase names for arguments, where the first half is the name of the function. The CSS would then be gathered in a camelCase.css stylesheet named after the function, with a documentation of the expected HTML at the top, hence making it much easier to find and reuse.

Now that you have access to functions, you will probably want to use them to implement reusable «components» — standalone pieces of HTML and CSS that represent atoms of information.

At some point, you will have to make components interact (if only to respect each other on the page layout). All of this will be hell if component A uses normal block layout rules, component B is floating to the left and component C is positioned absolutely.

Rule Four : a Component Should only Care about its Inner Layout

As soon as a component starts to care about outer layout concepts such as margin, position, floating or clearing, you will be in a world of pain. This is because such concepts depend on where the component appears, and as such are not easy to reuse.

I split my CSS code into components and bones:

  • Components. These are reusable atoms. They do not care about their outer layout at all, so they never specify anything like margin, position, floating, clearing, display mode or anything that might cause them to interact differently with their surroundings on the page.

    They may specify a width and height if they wish, but it is discouraged (a component that can adapt to any geometry is easier to use). They can specify anything they want in terms of border, padding, font, color, background, font, and any inner properties they need.

  • Bones. These are elements found inside the components that handle the layout of the component contents themselves. They can and should make appropriate assumptions about what bones can be found within a component and how they should interact to result in the layout you need to see.

A nice finishing touch is to make the component overflow : hidden, because the last thing you need is a component’s skeleton sticking out from its skin and interacting with other elements.

I repeat: never allow the contents of a component to stick out of that component!

In particular, if you have a component with floating elements inside, make sure you add a clearer element at the bottom of the component to have it resize with its contents.

In practice, I assume every function argument to be a bone, and every function to be a component. The situations where a function acts as a bone are so rare, and the results so difficult to reuse (so you’ve added a float:left to an element, where are you going to put it?), that I don’t really take them into account. The Component-Bone approach tends to solve almost everything elegantly, as long as you’re clever about where a component begins and a bone ends.

For instance, if you’re laying out a list of comments for a blog, you are probably going to have a «comment list» component with «comment» bones that are laid out on top of one another with appropriate margins, borders and paddings. The contents of every «comment» bone will be a «comment» component, with bones representing the picture, name, date and comment body, laid out cleanly without that component.

Whether the .commentList-comment is placed on the same element as .comment is something you can decide for yourself. What is essential is that, in order for the comment style to be reusable independently of the comment list style, all outer layout information should be in .commentList-comment, not in .comment.

Good.

Now, before I finish, do you remember when I said earlier that component B could be mangled by component A for two different reasons? The second reason happens to be inheritance. Everyone knows inheritance is bad for reuse. Right?

What happens is that, if you define a font size, color or family in a given element, then all descendants of that element will get the same font size, color and family (unless some CSS rule changes them). That’s inheritance: the value of the property in the child element is inherited from the parent element.

Rule Five: Only Change Inheritable Properties on your own Content

It’s impossible to define the entire list of inheritable properties at the root of every single component in your web side, however convenient it may be. Keeping everything in sync is very difficult, if not impossible. It is far easier, by comparison, to restrict such changes to only those areas of a component where the content is closely controlled and guaranteed not to contain any other components.

I believe there are basically three kinds of areas in any given page that are actually worth being paid attention to. These are:

  • Layout areas. These are those component-in-component-in-component places where touching an inheritable property can get you killed annoyed.
  • Text areas. Those contain no components, but they might still contain paragraphs, links, headings, images in a typical «rich text editor» fashion. If you change one property (such as the color of text), be ready to change all the related properties (the color of links) to keep a consistent appearance.
  • Line areas. These contain a short bit of text without any other tags. You don’t have to worry about changing properties here.

Every component should document, for every piece of content that should be filled from outside the component, whether it is a layout, text or line area. For instance:

/*
  <div class="comment">
    <span class="comment-author">...</span>
    <div class="comment-contents"><p>...</p></div>
    <div class="comment-reply">
      ...
    </div>
  </div>
*/

Here, a span (can only contain inline elements or text) represents a line area, a div-with-paragraph represents a text area (may contain several paragraphs, of course) and a normal div represents a layout area. This tells me, for instance, «don’t even think about putting a component in the comment contents, or I’ll clobber their stylesheet beyond recognition.»

Depending on the kind of web site you are building, other kinds of areas may be useful to you, such as forms.

DOM removal and events

Let’s try something… go to a page with jQuery enabled (such as this one), and run the following code in your Javascript debugger console (such as Firebug):

var button =
  $('<button>Click me</button>')
  .click(function(){alert('Clicked!')})
  .appendTo('body')

In case you were wondering, this creates a brand new button, causes it to display a “Clicked!” message box when it’s clicked, and appends it to the document you are viewing.

Click on the button that just appeared : the message box appears. Not very surprising.

Now, run the following code on the same page :

$('body').html('');
button.appendTo('body')

As expected, everything on the page, including the button, disappears. However, the button is still referenced by the button variable, so it sticks around and we can append it back to the document. And indeed, it does appear on the page.

Click on the button again. This time, no message box appears.

I honestly have no idea why.

Last Minute Skin

Right now, we render our page layout on the server, thus wasting precious bandwidth sending the same header, footer and menus all over again every single time. AJAX techniques have evolved to reload only the inner part of every page, but they require clever URL manipulation or ‘back’, ‘refresh’ and bookmarks won’t work, and they impose strong constraints on page layout and on the way the server responds to requests.

Why not do it the other way around? Have every page include the same layout-generating JavaScript file (kept in the browser cache for optimum performance) ! This is the idea behind the last-minute-skin pattern.

Empty Lists

We have all written this code before :

<ul>
  <?php foreach ($list as $element):?>
    <li><?=htmlspecialchars($element)?></li>
  <?php endforeach; ?>
</ul>

What happens when the list is empty? What is generated is an empty UL element :

<ul></ul>

This would be perfectly fine, if it wasn’t completely wrong. Quoth the XHTML DTDs (any of them) :

<!ELEMENT ul (li)+>

There must always be at least one list item in a list (what kind of insanity would have led to preventing empty lists from existing is beyond me, although I’m certain they must have had a good reason), which means a document will not validate if it contains the aforementioned empty UL element. This is also the case for HTML 4, though HTML 5 does currently allow empty lists.

So, to circumvent the empty list case, the code becomes:

<?php if (count($list) > 0): ?>
  <ul>
    <?php foreach ($list as $element): ?>
      <li><?=htmlspecialchars($element)?></li>
    <?php endforeach; ?>
  </ul>
<?php endif; ?>

While it might be possible to abstract these details away behind a function that prints a list of elements, the ultimate point of such an abstraction would be to free the developer’s mind of the issue of empty lists not being allowed in XHTML. And such a thing would be ill advised : since the correct behavior is to remove the empty list from the document, the developer should be aware that no UL element will be generated for an empty list, especially since this has implications on the CSS side (which has to accomodate the absence of the list) and the Javascript side (which has to create the element if it doesn’t exist before adding elements to it).

An important quality of any developer is their ability to identify and handle any corner cases of their domain. An important quality of any domain is to have as few corner cases as possible.

Bored CSS

I had some free time on my lunch hour today, so I decided to answer a plea for help on the GameDev.net forums.

I am absolutely horrible with CSS. I need something to launch my site with (server is not available ATM)

If you can make this page look presentable i’ll be very happy. Please build on each other work so instead of msging me paste a link in the thread so everyone can see what you done and hopefully make it better.

It took me a few minutes to review the page structure, think of a classic left-right page structure, and write the corresponding CSS. I didn’t have a lot of time, so I couldn’t make the stylesheet fully portable (for instance, the rounded corners only work in Firefox, and some CSS selectors seem to confuse Internet Explorer) thus illustrating the classic conundrum that designing the stylesheet is 99% of the work, and making the stylesheet work across all browsers is the remaining 99% of the work.

And then there’s the 99% of adding jQuery to the page ;)

You can check out the re-designed page, or look at this screenshot to see what it looks like in my FireFox:

HTML Alignment

LE PORTIER (le poursuivant):
Holà ! vos quinze sols !

LE CAVALIER:
Holà ! vos quinze sols !J’entre gratis !

LE PORTIER:
Holà ! vos quinze sols ! J’entre gratis ! Pourquoi ?

LE CAVALIER:
Je suis chevau-léger de la maison du Roi !

I can guarantee that, regardless of your font size or face, “J’entre gratis!” will be aligned horizontally in-between “Holà ! vos quinze sols !” and “Pourquoi?”, as it is expected to be (this is an excerpt of Cyrano de Bergerac, written in verse, and since the three sentences are part of the same verse they have to be written this way for better understanding).

How and why do I guarantee this? What I wrote is actually:

LE PORTIER (le poursuivant):
Holà ! vos quinze sols !

LE CAVALIER:
Holà ! vos quinze sols ! J’entre gratis !

LE PORTIER:
Holà ! vos quinze sols ! J’entre gratis ! Pourquoi ?

LE CAVALIER:
Je suis chevau-léger de la maison du Roi !

Then, I simply set the style to “visibility:hidden” on the redundant parts. They are invisible, but still taken into account for the page layout. So, the horizontal offset of “J’entre gratis!” will be the width of the “Holà! vos quinze sols!” sentence repeated above.



1170 feed subscribers
(readers who polled a feed this week)