- Really... Getting started with JavaScript "& Rails"
- Different levels of usage from beginner to advanced.
- Review some anti-patterns and best practices.
http://www.procata.com/blog/archives/2005/05/10/expert-programmers/
- Putting JavaScript at the end of the page in a
<script>
tag. - Writing everything in
jQuery.ready()
.
<%= form_for @user do |f| %>
<%= f.text_field :name %><br />
<%= f.text_field :email %><br />
<%= f.submit %>
<% end %>
<script type="text/javascript">
$(function(){
$('#user').submit(function(e){
var email = $('#user_email').val();
if (email.length === 0) {
e.preventDefault();
alert('Please enter your email.');
};
})
})
</script>
- Example could include any complex form behavior.
- Show or hide sections.
- Dynamic elements based on a select.
- Etc...
- The anonymous function to
jQuery(ƒ)
is shorthand for$(document).ready(ƒ)
. - All logic in anonymous functions and handlers.
- Even simple example demonstrates complexity and right drift.
- JavaScript is all loaded in the head.
- Naming functions, but still using top level scope.
- Basic scope separation of concerns.
<head>
<script type="text/javascript" src="/assets/application.js"></script>
</head>
<%= form_for @user do |f| %>
...
<% end %>
<script type="text/javascript">
$(function(){ $('#user').submit(submitUserForm); })
</script>
function fieldPresent(sel) {
var val = $(sel).val();
var present = val !== null && val !== undefined && val.length !== 0
return present;
}
function submitUserForm(e) {
if (fieldPresent('#user_email')) {
e.preventDefault();
alert('Please enter your email.');
};
}
- Still uses document ready to start the process off.
- Very functional and stateless.
- Perhaps you may even namespace
- Same application.js from above.
- Now, all your JavaScript is loaded at the bottom of the page.
<body>
<%= yield %>
<script type="text/javascript" src="/assets/application.js"></script>
<%= yield :footer %>
</body>
<%= form_for @user do |f| %>
...
<% end %>
<% content_for :footer do %>
<script type="text/javascript">
$('#user').submit(submitUserForm);
</script>
<% end %>
- No need to use document ready callback.
- Now using CoffeeScript.
- Class encapsulates a specific DOM element.
- Single instance instantiation solves per-page-specific.
- Confidence in your DOM and CSS class usage.
class ComplicatedUserForm
@form: '#user'
@load: -> new @(@form) if $(@form).length
constructor: (el) ->
@form = $(el)
@email = $('#user_email')
@form.data @constructor.name, @
submit: (event) ->
unless @email.val()?.length
event.preventDefault() if event?
alert 'Please enter your email.'
ComplicatedUserForm.load()
- Class here is private. File typically always in a closure.
- Using a MV* framework.