HTML Element Names as Helper Methods
Summary
repository: http://svn.dangosaur.us/svn/elemental/
Introduces builder-like syntax to rhtml:
1 2 |
<%= p @item.content %> <%= p span @person.first_name, :id => dom_id(@person, "name_") %> |
1 2 3 4 |
<% table do @list.each do |item| tr do %> <%= td item.name %> <%= td item.content %> <% end end end %> |
Elemental allows you to use XHTML Transitional tags as helper methods in your rhtml. With traditional ERb, the code above would be written:
1 2 |
<p><%= @item.content %></p> <p><span id="<%= dom_id(@person, "name_") %>"><%= @person.first_name %></span></p> |
1 2 3 4 5 6 7 8 |
<table> <% @list.each do |item| -%> <tr> <td><%= item.name %></td> <td><%= item.content %></td> </tr> <% end %> </table> |
That’s more code, more noise as angle-brackets (especially embedded inside the html tag), and more lines. Elemental’s syntax is also cleaner and terser than when using content_tag:
1 2 |
<%= content_tag "p", @item.content %> <%= content_tag "p", content_tag "span", @person.first_name, :id => dom_id(@person, "name_") %> |
and you can’t send a block to content_tag
1 2 3 4 5 6 7 8 9 |
<table> <% @list.each do |item| -%> <tr> <%= content_tag "td", item.name %> <%= content_tag "td", item.content %> </tr> <% end %> </table> <table> |
Usage
Elemental has three basic usages:
1. Self-closing tags: no argument, or hash only for argument:
1 2 |
<% br %> <% br :class => "someClass" %> |
2. Content tags: first argument is the value of the content:
1 2 |
<%= p "some content" %> <%= p "some content", :id => dom_id(@object) %> |
3. Content tags with a block argument:
1 2 3 |
<% div :class => "some-class" do %> ... <% end %> |
You can nest Elemental methods:
1 2 3 4 5 |
<%= p span @object.value %> or <%= p(span(@object.value)) %> generates: <p><span>the object's value</span></p> |
The same thing with attributes (pay attention to your parentheses):
1 2 3 4 5 6 7 |
<%= p span @object.value, :id => "some_id", :class => "some_class" %> generates: <p><span id="some_id" class="some_class">the object's value</span></p> while <%= p span(@object.value, :id => "some_id"), :class => "some_class" %> generates: <p class="some_class"><span id="some_id">the object's value</span></p> |
You can nest the methods in blocks:
1 2 3 4 5 6 |
<% p do %> <% span :class => "someClass" do %> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. <% end %> <% end %> |
1 2 3 4 |
<% p do span :class => "someClass" do %> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. <% end end %> |
1 2 3 4 5 6 |
<p> <span class="someClass"> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </span> </p> |
This is useful for loops:
1 2 3 |
<% ul do ['one', 'two', 'three'].each do |item| %> <%= li item %> <% end end %> |
1 2 3 4 5 |
<ul> <li>one</li> <li>two</li> <li>three</li> </ul> |
Options/Attributes Hash
Options are converted to regular html attributes. None are filtered, so you can certainly insert invalid attributes.
1 2 3 |
<%= span :id => "some_id", :bogus_attribute => "some_value"%> generates: <span id="some_id" bogus_attribute="some_value"></span> |
Omitted Tags
Rails’ ActionView::Helpers already defines form, select, and input, so these are omitted from Elemental.
Motivation
Afer using Markaby a bit, I decided there were situations where I wanted a Markaby or Builder-type syntax within rhtml’s context. I had been using content_tag quite a bit for convenience, but wanted more legible and concise code, espcially for loops.
Acknowledgments
_why for Markaby and its list of XHTML and XHTML Transitional tag lists, which I used.