Decorators – NextGen Markup pt.2

Not sure what this is about? Have you read the first part?

Decorators are the second piece from the Web Components that we are going to focus on. They are elements named after the decorator programming pattern and rightly so. For those who are not familiar with the pattern, here is a short definition from the wikipedia article:

decorator pattern is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class

Unfortunately there is no browser supporting decorators at the time this article is written (not even Chrome Canary), so we can only take a theoretic view on them. And, contradicting as it may sound, we will do that with an example.

Lets suppose we have a list of cars. And each car has the following info: model and brand, description, and image. We put everything in a nice markup and the end result would look something like this (showing with only one car):

<li class="car-item">
   <img class="car-image" title="Seat Ibiza" src="images/seat-ibiza.jpg" />
   <h3 class="car-model">Seat Ibiza</h3>
   <p class="car-description">The SEAT Ibiza is a supermini car manufactured by the Spanish automaker SEAT. It is SEAT&#039;s best-selling car and perhaps the most popular model in the company&#039;s range.</p>
</li>

Simple enough. Now lets suppose, that we want to put all the images inside something like a window frame. Where it would have 2 buttons: one to remove the image entirely and one to toggle show/hide. The normal way to do that is actually to go in the DOM, wrap the image with more divs, and end up with something as ugly as this:

<li class="car-item">
   <section class="window-frame">
      <header>
          <a class="frame-toggle" href="#">Min/Max</a>
          <a class="frame-close" href="#">Close</a>
      </header>
      <img class="car-image" title="Seat Ibiza" src="images/seat-ibiza.jpg" />
      <h3 class="car-model">Seat Ibiza</h3>
      <p class="car-description">The SEAT Ibiza is a supermini car manufactured by the Spanish automaker SEAT. It is SEAT&#039;s best-selling car and perhaps the most popular model in the company&amp;#039;s range.</p>
   </section>
</li>

Ugly, right? And you can imaging how bloated our source code gets. And try to inspect your page in the browser… nightmare!

So, what can decoratos do to help? Well, using a decorator, you can define that specific items in your DOM will be wrapped with some more markup, some styles and some functionality. Essentially extending their base functionality, but having the options of doing that only for a subset of elements. Lets see how a decorator for the above example would look like.

<decorator id="frame-decorator">
   <template>
      <section id="window-frame">
         <header>
            <a id="toggle" href="#">Min/Max</a>
            <a id="close" href="#">Close</a>
         </header>
         <content></content>
      </section>
   </template>
</decorator>

A few notes before we move on to event binding.

  1. Have you already read about the template element? This is how the decorator is applied.
  2. There is a content element. It is mandatory. It will be where content of the decorated element will be inserted.
  3. We use ids all over the place, while is real projects we are more careful with that. It is because you can think of ids inside decorators as being “scoped”. They will never appear in the DOM. document.getElementById(‘window-frame’) will return no elements, both before and after applying the decorator.

Of course inside the decorator, we can apply styles using the scoped attribute. Lets see an example:

<decorator id="frame-decorator">
   <template>
      <section id="window-frame">
         <style scoped>
            #toggle {float: right;}
            #close {float: right;}
         </style>
         <header class="clearfix">
            <a id="toggle" href="#">Min/Max</a>
            <a id="close" href="#">Close</a>
         </header>
         <content></content>
      </section>
   </template>
</decorator>

We float our two buttons at the right. At the same time, we added the .clearfix to the header element to clear the floats. Notice that styles outside the scope are still being applied if you use the proper classes.

And now to add behavior. When it comes to decorators, you can’t use events like you use them in normal elements. Attaching or detaching a decorator would cause the event to wipe if you had binded on an element. So, instead we have the ability to create an event controller and attach events using that. Lets see how our example would become:

<decorator id="frame-decorator">
   <script>
      this.listen({
         selector:"#toggle", type:"click",
         handler: function (event) {
            // do the toggle button logic here
         }
      });
      this.listen({
         selector:"#close", type:"click",
         handler: function (event) {
            // do the close button logic here
         }
      });
   </script>
   <template>
      <section id="window-frame">
         <style scoped>
            #toggle {float: right;}
            #close {float: right;}
         </style>
         <header class="clearfix">
            <a id="toggle" href="#">Min/Max</a>
            <a id="close" href="#">Close</a>
         </header>
         <content></content>
      </section>
   </template>
</decorator>

Keep in mind that the script is run only once, when the decorator element is insterted in the DOM.

There is one final step. Apply the decorator on our element. This is as simple as using a CSS property:

.car-item {
   decorator: url(#frame-decorator);
}

And that’s it! All your cars now have the specific frame around them!

Web components are still an editors draft. The spec will probably go through a lot of changes in the future. At the moment of writing of this blog post, no browsers supported decorators.

To be continued… Next up, Custom elements…

3 Responses to Decorators – NextGen Markup pt.2
  1. [...] Interested in Web Components? How about reading the next article in the series? Find out more about Deco... prevent-default.com/templates-nextgen-markup-pt-1
  2. Lawyer Blogs Peoria Il Reply

    Hey, I think your website might be having browser compatibility issues.
    When I look at your blog in Opera, it looks fine but when opening in Internet Explorer, it has some overlapping.
    I just wanted to give you a quick heads up! Other then that, excellent blog!

    my blog post: Lawyer Blogs Peoria Il

  3. Traditional LCMS Churches Omaha Reply

    We stumbled over here coming from a different web page and thought I
    might as well check things out. I like what I see so now i
    am following you. Look forward to looking at your web
    page again.

    Here is my web site; Traditional LCMS Churches Omaha

Leave a Reply

Your email address will not be published. Please enter your name, email and a comment.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>