<% case $chart when 1: %>

Unobtrusive JavaScript. Hit or miss?

<% when 2: %>

What is Unobtrusive JavaScript?

Quoted from Wikipedia:

<% when 3: %>

Why should we use it?

<% when 4: %>

Some requirement for the team:

<% when 5: %>

How can we accomplish it?

<% when 6: %>

Stop talking, show some examples:

WRONG

<%=h %Q[Post a new entry] %>
	

COOL

<%=h %Q[Post a new entry

$('show-form').addEvent('click', function(e){
  e = Event(e).stop();

  $('entry-form').toggle();
});] %>
	
<% when 7 %>

Hey, wait a second...

That's much more code! Yes it is, but have a look at the following example:

<%=h %Q[Post a new entry
	
--- somewhere else in your app ---
	
Why don't you post a new entry?
	
$$('a.show-form').each(function(el){
  el.addEvent('click', function(e){
    e = Event(e).stop();
		
    $('entry-form').toggle();
  });
});] %>
	
<% when 8 %>

Mmmmhhhh....

Think about what happens if the name of the function changes, or some parameters need to be added. You have to go through all of your pages to change them. Sucks!

Using the unobtrusive way, you just need to change your JavaScript file. Awesome!

<% when 9 %>

Dynamic content example

WRONG

<%=h %Q[Show entry] %>
	

What if JavaScript is turned off? The user will never be able to delete an entry.

COOL

<%=h %Q[Show entry
	
$$('a.show-entry').each(function(el){
  el.addEvent('click', function(e){
    e = Event(e).stop();
			
    $('container').load(el.get('href'));
  });
});] %>
	

Now we can use AJAX, but the post will also be accessible when the JavaScript is turned off.

<% when 10 %>

Man, this is still a lot more code to handle.

Right, but what if you want to add some fancy hover effect?

WRONG

<%=h %Q[Show entry] %>
	

COOL

<%=h %Q[$$('a.show-entry').each(function(el){
  el.addEvent('click', function(e){
    e = Event(e).stop();
			
    $('container').load(el.get('href'));
  });
		
  el.addEvent('mouseenter', function(){
    el.fade('out', .5);
  });
		
  el.addEvent('mouseleave', function(){
    el.fade('in');
  });
});] %>
	

We don't need to touch the HTML to accomplish this effect.

<% when 11 %>

Why is it so bad that Rails guys mess with JavaScript?

<% when 12 %>

Bad usage example of JavaScript and how to make it cool.

Example

Goal: Use a link as the form submit button because of better styling possibilities.

<% when 13 %>

How to solve it:

WRONG

<%=h %Q[
Login
] %>

This will break Login for all non JavaScript supporting browsers!

COOL

<%=h %Q[
$$('form.submit').each(function(el){ if (el.getElement('input[type=submit])) { var submit = el.getElement('input[type=submit]); var button = new Element('a').set({ href: '#', html: submit.get('value') }).addClass('button').insertAfter('submit').addEvent('click', function(e){ e = Event(e).stop(); el.submit(); }); submit.destroy(); } });] %>

Awesome, now we can use this in the whole application without changing the HTML markup!

<% when 14 %>

Separate JavaScript and CSS.

WRONG

<%=h %Q[$$('.element').each(function(el){
  el.addEvent('mouseenter', function(){
    el.set({ style: 'border: 1px solid #AAA;' });
  });
  
  el.addEvent('mouseenter', function(){
    el.set({ style: 'border: 0;' });
  });
});] %>
	

COOL

<%=h %Q[$$('.element').each(function(el){
  el.addEvent('mouseenter', function(){
    el.addClass('border');
  });

  el.addEvent('mouseenter', function(){
    el.removeClass('border');
  });
});] %>
  	
<% when 15 %>

Developing Unobtrusive JavaScript with MooTools.

application.js

<%=h %Q[var Application = {

  init: function(){

    if (Browser.Engine.trident) Application.fixIE();
      
    if ($('form-entry')) Application.initFormEntry();

    if ($$('a.hover-me').length > 0) Application.initHoverEffects();

  },

  start: function(){

    if ($$('a.resize-me')) Application.resizeImages();

  },

  fixIE: function(){
     ...
  },

  ...

}

window.addEvent('domready', Application.init);
window.addEvent('load', Application.start);] %>
  
<% when 16 %>

Conclusion

Unobtrusive JavaScript is the way to go!

Quoted from Eran Galperin:

"Choosing a software library is a matter of personal and design preferences, and is influenced to a large degree from what you hope to get out of that particular library."

Prototype and Scriptaculous

MooTools

jQuery

<% end %>