Hard-coding IDs

Should HTML DOM IDs be hard-coded throughout a Rails app, or stored within..an appropriate model or helper or ..?

Here's an example problem:

/neighbourhoods/1/map/ has a form:   # map.html.erb   <% form_remote_tag ... :html => {:id => 'map-filter-form'} do %>

When the page loads, the form needs to be submitted:   # public/javascript/submit_map_filter_form.js   Event.observe(window, 'load', function() {     $('map-filter-form').onsubmit();     });

Thus, I include the Javascript file mentioned above:   # map.html.erb   <%= javascript_include_tag 'submit_map_filter_form' %>

This feels wrong because the form's DOM ID ("map-filter-form") is hard- coded in multiple locations (the view, and the Javascript file). As I add functionality that uses the form, the number of places where the form's DOM ID is hardcoded will increase.

Does anyone have suggestions or comments for how to deal with this?

Cheers, Nick

One solution I can think of is to put the DOM ID into an appropriate model. In this case, I'd make RentalMap#map_filter_form_dom_id return "map-filter-form".

However, if I do that, the contents of submit_map_filter_form.js would need to be placed elsewhere, because RentalMap#map_filter_form_dom_id can't be called from the Javascript file.

I could do something like this:

Add a class method to the RentalMap model for the DOM ID:   # rental_map.rb   class RentalMap     MAP_FILTER_FORM_DOM_ID = 'map-filter-form'

    def self.map_filter_form_dom_id       MAP_FILTER_FORM_DOM_ID     end   end

The form in /neighbourhoods/1/map/ calls the new method:   # map.html.erb   <% form_remote_tag ... :html => {:id => RentalMap.map_filter_form_dom_id} do %>

Move the Javascript into a partial so that the new method can be called:   # _submit_map_filter_form.html.erb   <script type='text/javascript'>     Event.observe(window, 'load', function() {       $('<%=h RentalMap.map_filter_form_dom_id -%>').onsubmit();       });   </script>

The partial above must be rendered:   # map.html.erb   <%= render :partial => 'submit_map_filter_form' %>

But that doesn't feel right, for several reasons: 1) Now there's a partial whose sole purpose is to spit out some Javascript code (as opposed to HTML code). 2) The form's DOM ID doesn't feel like it belongs in a model in the first place. 3) As the number of DOM IDs that shouldn't be hard-coded increases, the models get filled up with these tiny methods.

I'd love to hear any comments and suggestions you guys have. Thanks! Nick

When it comes to HTML... it's kind of hard to not... hard-code it. Either you end up having some dictionary that is a pain to manage or you just have good conventions.

This is what we do at Planet Argon to keep things a bit more organized.

* http://www.robbyonrails.com/articles/2007/08/01/designers-developers-and-the-x_-factor

Good luck!

Robby

Hi Robby. Thanks for the link and for sharing those conventions. The idea you guys decided upon definitely helps mitigate problems that involve renaming IDs.

Hard-coding the DOM IDs still doesn't sit right with me, though. It feels like the string-version of "magic" numbers, which was beaten out of me many, many years ago =P

Thanks again, Nick

By the way, did you write a follow-up to the blog post above? I looked through your archives and a couple of tags, but didn't find it. -Nick

For anyone else who finds this thread...

There's a plugin called "embedded javascripts": http://agilewebdevelopment.com/plugins/embedded_javascripts

In a nutshell, it defines ActionView::Base#include_javascript , which takes the name of a Javascript file as an argument, processes any ERB in the JS file, and returns the JS code sandwiched between <script type="text/javascript" ..> and </script>.

That sounds like a good tool to use in a solution for the originally- stated problem. However, it doesn't feel right to me. The Javascript file will never be cached by browsers, and it adds another call to read from the file system, which will slow things down a bit. However, for a small app, I think it's a great tool.

Dan Webb released two plugins - MinusR and MinusMOR - with the latter being an update of the former: http://www.danwebb.net/2006/11/17/rjs-minus-r http://www.danwebb.net/2006/11/24/minusmor-released

I like MinusMOR, as it doesn't hijack the .rjs file extension. However, I don't think it's a tool that could [easily] be used to solve the original problem. But it's still a pretty cool plugin!

In the end, I've decided to hard-code HTML elements' DOM IDs in views, partials, RJS templates, Javascript files, and wherever else. On top of that, every element that is touched by Javascript will have its DOM ID prefixed with "x_". This will make it very clear which elements' DOM IDs shouldn't be changed on a whim.

What I've just explained is Robby Russell's approach. He explained it quite well in a blog post: http://www.robbyonrails.com/articles/2007/08/01/designers-developers-and-the-x_-factor

Cheers, Nick