Allan & Steve are the chubby founders of LessEverything. This is their blog, hear them rant, praise, give advice and talk about Just Stuff, Less Accounting, Lovd by Less, More Honey, Less Memories, Code, Business, Design, Marketing
February 19th, 2008

Haml doesn't like javascript

written by Steven Bristol

We have been going back and forth on Haml lately. There is no doubt that it is nice, it is short, tight and does a lot for you. At the root of haml is yaml, a format for storing data. In yaml (and consequently in haml) indenting is very important, and for this reason haml and javascript go together like oil and grape jelly.

To haml, javascript is just plain text, which means to make haml happy all of your lines of javascript code must allign vertically. Here is an example:

In html:
<script type="text/javascript" charset="utf-8">
//<![CDATA[
jQuery(function(){
  tog("#forgot_password_clicker", "#login_form");
  tog("#forgot_password_clicker", "#forgot_form", forgot_text);
});
function forgot_text(){
  if (jQuery("#forgot_text").html() == "forgot")
    jQuery("#forgot_text").html("remember");
  else
    jQuery("#forgot_text").html("forgot");
}
//]]>
</script>
In haml:
%script{:type => "text/javascript", :charset => "utf-8"}
  //<![CDATA[
  jQuery(function(){
  tog("#forgot_password_clicker", "#login_form");
  tog("#forgot_password_clicker", "#forgot_form", forgot_text);
  });
  function forgot_text(){
  if (jQuery.trim(jQuery("#forgot_text").html()) == "forgot")
  jQuery("#forgot_text").html("remember");
  else
  jQuery("#forgot_text").html("forgot");
  }
  //]]>
A few things to note:
  1. Javascript becomes much harder to read and write.
  2. Textmate does not do syntax highlighting on the javascript.
  3. The haml requires the jQuery.trim() method in the first line of forgot_text() function because with haml you need to add a bunch of white space:
  4. If you’re going to output ruby variables into your javascript, it only gets worse.
html:
<span>I <span id="forgot_text">forgot</span> my 
  <a href="javascript:void(0)" id="forgot_password_clicker">password or username</a>
</span>
haml:
%span 
      I 
      %span#forgot_text
        forgot
      my 
      %a{:href => "javascript:void(0)", :id => "forgot_password_clicker"} password or username 
There are things one can do to overcome this:
  1. One could use :plain and then indent javascript.
    • The problem is doing that means one can’t render ruby variables to the javascript.
  2. Write unobtrusive javascript.
    • Nice, but I really like to cheat.
  3. Put all of your javascript in partials
    • Sorry, I just threw up in my mouth a little bit.
  4. Patch haml.
    • Let me know when you do this.
  5. Stop writing javascript.
    • I also think you should start using frames again.
  6. If anyone knows of any other way around this, please let me know. We’d love to use haml, but not at this price.
  7. Don’t use haml.
    • Our choice for today. Although we will review this regularly.

12 Responses to “Haml doesn't like javascript”

  1. Robert Fischer February 19th, 2008

    Thanks for posting this. I was wondering if I should try out Haml, and this saves me some time. Let me know if you discover that you love Haml after all—the idea, at least, is one I’m fond of.

    BTW, this— Put all of your javascript in partials * Sorry, I just threw up in my mouth a little bit. —brightened up my otherwise dreary Minnesota winter day. :)

  2. Evan Light February 19th, 2008

    But you can work around that by just not embedding JavaScript in your HAML and just linking to it instead.

  3. Evan Light February 19th, 2008

    Did I mention that I love HAML?

  4. Steven Bristol February 19th, 2008

    Evan:

    As I said, you can write all of your javascript unobtrusively, but I am like to cheat.

  5. Evan Light February 20th, 2008

    That’s what I get for skimming (from following too many Ruby developer blogs) instead of reading.

  6. Les February 21st, 2008

    Google says try :inline_javascript, but you do have to indent the block:

    :inline_javascript \tYour nice JS here \t… %b Yes we can

    See http://groups.google.com/group/haml/msg/2d890cf1ede761ea

  7. Steven Bristol February 21st, 2008

    Les,

    As i said “One could use :plain and then indent javascript.” This does the same thing without the need for a filter.

  8. Les February 21st, 2008

    Right, and inline_javascript lacks variable interpolation. So it adds about, say NADA [1], to the discussion. Please carry on :)

    [1] Would you like some sugar-free sugar with that?

  9. Nathan Weizenbaum February 23rd, 2008

    I’ve just pushed a bunch of commits to the Haml development branch that should make these issues go away. See http://groups.google.com/group/haml/t/d8fea02e213a16ce?hl=en for lots of details, but the upshot is that:

    • All Haml filters can now have template-context Ruby code interpolated using the known-and-loved #{} syntax.
    • There’s now a :javascript filter that’s based on the :inline_javascript patch that’s been floating around, and that adds script and CDATA tags.

    This means you can freely indent your code while still keeping it dynamic.

    Although this is just on the development branch, it tends to be quite stable. You can get it from git://github.com/nex3/haml/master.

  10. Josh Adams March 29th, 2008

    Steven,

    You could be unobtrusive – this is the solution. It has huge payoffs – reusability is stupid-easy, etc. In my code, when I want an expandable/toggled box I’d just use

    .expandable_box %h3 Some heading .content Wheeee

    ...except that use case is covered by Rails2’s layout partials for me…but in the background that’s what happens, and then my ExpandableBox class grabs all those after page load and converts them. Without unobtrusive javascript how do you make sure you support your non-js users well? We always build stuff sans-js first, then grapple onto the structure to add richer features.

    Of course, I’m potentially changing my tune there a little bit as well – considering building a RIA that hits my current app’s resources and separating the display logic out altogether for the preferred/recommended interface to the app – the RIA.

    As a side note – Ubuntu has items in its package manager now for things like ‘Google Docs in Prism’ which is just awesome.

  11. Steven Bristol March 30th, 2008

    @Josh

    I love unobtrusive. I love RESTful rails. I use both the vast majority of the time. But I am not religious. I cheat when it is easy and convenient and worth it.

  12. build credit June 5th, 2008

    Nice Site! http://google.com

Leave a Reply